<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us">
    <generator uri="https://gohugo.io/" version="0.152.2">Hugo</generator><title type="html"><![CDATA[Matplotlib on Blog]]></title>
    
    
    
            <link href="https://blog.scientific-python.org/tags/matplotlib/" rel="alternate" type="text/html" title="html" />
            <link href="https://blog.scientific-python.org/tags/matplotlib/atom.xml" rel="self" type="application/atom" title="atom" />
    <updated>2026-04-04T04:32:36+00:00</updated>
    
    
    
    
        <id>https://blog.scientific-python.org/tags/matplotlib/</id>
    
        
        <entry>
            <title type="html"><![CDATA[PyPalettes: all the colors you'll ever need]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/pypalettes/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/how-to-create-custom-tables/?utm_source=atom_feed" rel="related" type="text/html" title="How to create custom tables" />
                <link href="https://blog.scientific-python.org/matplotlib/unc-biol222/?utm_source=atom_feed" rel="related" type="text/html" title="Art from UNC BIOL222" />
                <link href="https://blog.scientific-python.org/matplotlib/book/?utm_source=atom_feed" rel="related" type="text/html" title="Newly released open access book" />
                <link href="https://blog.scientific-python.org/matplotlib/visualising-usage-using-batteries/?utm_source=atom_feed" rel="related" type="text/html" title="Battery Charts - Visualise usage rates &amp; more" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_final/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Final Report" />
            
                <id>https://blog.scientific-python.org/matplotlib/pypalettes/</id>
            
            
            <published>2025-04-01T00:00:00+00:00</published>
            <updated>2025-04-01T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Matplotlib is the go-to library for data visualization in Python. While it offers quality built-in colormaps like viridis and inferno, the limited selection can make Matplotlib charts look similar. To address this, I developed pypalettes, a Python library with over 2,500 high-quality, pre-made color palettes, based on Paletteer. The library includes a web app for browsing and previewing all of them.</blockquote><h2 id="finding-the-right-color-has-never-been-easier">Finding the right color has never been easier<a class="headerlink" href="#finding-the-right-color-has-never-been-easier" title="Link to this heading">#</a></h2>
<p><a href="https://github.com/JosephBARBIERDARNAL/pypalettes">PyPalettes</a> is a new Python library designed to simplify the use of color palettes in Python charts.</p>
<p>It provides mainly two things:</p>
<ul>
<li>a <a href="https://github.com/JosephBARBIERDARNAL/pypalettes">super-easy-to-use library</a> that requires only 1 line of code (in 99.99% of cases, 2 otherwise 🙃) to access thousands of pre-defined and attractive palettes.</li>
<li>a <a href="https://python-graph-gallery.com/color-palette-finder/">web app</a> to browse, filter, search, and preview all available palettes (with <strong>bonus</strong>: copy-pastable code to reproduce the charts).</li>
</ul>
<p><a href="https://python-graph-gallery.com/color-palette-finder/"><img src="https://github.com/holtzy/The-Python-Graph-Gallery/raw/master/static/asset/pypalettes.gif" alt="Preview and try all the palettes"></a></p>
<center><i>A small sample of the available palettes</i></center>
<br>
<h2 id="from-r-to-python">From R to Python<a class="headerlink" href="#from-r-to-python" title="Link to this heading">#</a></h2>
<p>In R, there are dozens of packages dedicated to colors for data visualization. Then <a href="https://emilhvitfeldt.github.io/paletteer/">Paletteer</a> came out to <strong>aggregate</strong> every color palette from those packages into a single one, meaning you <strong>only need one package</strong> to access almost all the color palettes people have created!</p>
<p>While re-crafting the <a href="https://python-graph-gallery.com/python-colors/">colors section of the Python Graph Gallery</a>, I started thinking of a way to have a similar tool to Paletteer but for Python.</p>
<center><h3 style="color: lightgray;">That's where PyPalettes comes in.</h3></center>
<p>Paletteer has a community-maintained <a href="https://pmassicotte.github.io/paletteer_gallery/">gallery</a>—a single page showcasing all its color palettes, along with their original sources and names. With the author’s approval, I scraped this gallery to compile the data.</p>
<p>While there may have been other ways to obtain this information, using a short Python script to reproduce the dataset ensures both simplicity and reproducibility (the script scrapes a page stored locally instead of the web page). To make <strong>pypalettes</strong> more comprehensive, I also incorporated all <strong>built-in colors</strong> from <code>Matplotlib</code>.</p>
<p>As a result, I created a dataset containing approximately <strong>2,500 unique palettes</strong>, each with a name, a list of hexadecimal colors, and a source.</p>
<p>At this point, the hardest part was already done. I just had to create a simple API to make them usable in a Python environment and add some additional simple features.</p>
<p>And since <a href="https://www.yan-holtz.com/">Yan</a> supported the idea, he created this amazing <a href="https://python-graph-gallery.com/color-palette-finder/">web app</a>, making it much easier to browse available palettes.</p>
<p>As a thank-you to <code>Paletteer</code>, Yan also created a color finder that features only <code>Paletteer</code> palettes! If you use R, <a href="https://r-graph-gallery.com/color-palette-finder">check it out here</a>.</p>
<br>
<h2 id="how-to-use-pypalettes">How to use pypalettes<a class="headerlink" href="#how-to-use-pypalettes" title="Link to this heading">#</a></h2>
<p>The goal was to make the simplest API possible, and I&rsquo;m quite satisfied with the result. For example, you really like the <a href="https://python-graph-gallery.com/color-palette-finder/?palette=Esox_lucius">&ldquo;Esox lucius&rdquo; palette</a>, and you want to make a chart with it.</p>
<p>First, you import the <code>load_cmap()</code> function (the main function of the library):</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">pypalettes</span> <span class="kn">import</span> <span class="n">load_cmap</span></span></span></code></pre>
</div>
<p>And then you just have to call this function with <code>name=&quot;Esox_lucius&quot;</code></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">cmap</span> <span class="o">=</span> <span class="n">load_cmap</span><span class="p">(</span><span class="s2">&#34;Esox_lucius&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>The output of <code>load_cmap()</code> is either a <a href="https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.ListedColormap.html">matplotlib.colors.ListedColormap</a> or a <a href="https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html">matplotlib.colors.LinearSegmentedColormap</a>, depending on the value of the <code>cmap_type</code> argument (default is <code>&quot;discrete&quot;</code>, so it&rsquo;s <code>ListedColormap</code> in this case).</p>
<p>Finally, you can create your chart as you normally would:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># load libraries</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">cartopy.crs</span> <span class="k">as</span> <span class="nn">ccrs</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">geopandas</span> <span class="k">as</span> <span class="nn">gpd</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.font_manager</span> <span class="kn">import</span> <span class="n">FontProperties</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">highlight_text</span> <span class="kn">import</span> <span class="n">fig_text</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># load font</span>
</span></span><span class="line"><span class="cl"><span class="n">personal_path</span> <span class="o">=</span> <span class="s2">&#34;/Users/josephbarbier/Library/Fonts/&#34;</span>  <span class="c1"># change this to your own path</span>
</span></span><span class="line"><span class="cl"><span class="n">font</span> <span class="o">=</span> <span class="n">FontProperties</span><span class="p">(</span><span class="n">fname</span><span class="o">=</span><span class="n">personal_path</span> <span class="o">+</span> <span class="s2">&#34;FiraSans-Light.ttf&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">bold_font</span> <span class="o">=</span> <span class="n">FontProperties</span><span class="p">(</span><span class="n">fname</span><span class="o">=</span><span class="n">personal_path</span> <span class="o">+</span> <span class="s2">&#34;FiraSans-Medium.ttf&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># projection</span>
</span></span><span class="line"><span class="cl"><span class="n">proj</span> <span class="o">=</span> <span class="n">ccrs</span><span class="o">.</span><span class="n">Mercator</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># load the world dataset</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span> <span class="o">=</span> <span class="n">gpd</span><span class="o">.</span><span class="n">read_file</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;https://raw.githubusercontent.com/holtzy/The-Python-Graph-Gallery/master/static/data/all_world.geojson&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="o">~</span><span class="n">df</span><span class="p">[</span><span class="s2">&#34;name&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">isin</span><span class="p">([</span><span class="s2">&#34;Antarctica&#34;</span><span class="p">])]</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span> <span class="o">=</span> <span class="n">df</span><span class="o">.</span><span class="n">to_crs</span><span class="p">(</span><span class="n">proj</span><span class="o">.</span><span class="n">proj4_init</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">300</span><span class="p">,</span> <span class="n">subplot_kw</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;projection&#34;</span><span class="p">:</span> <span class="n">proj</span><span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_axis_off</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">column</span><span class="o">=</span><span class="s2">&#34;name&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">=</span><span class="n">ax</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">cmap</span><span class="o">=</span><span class="n">cmap</span><span class="p">,</span>  <span class="c1"># here we pass the colormap loaded before</span>
</span></span><span class="line"><span class="cl">    <span class="n">edgecolor</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">linewidth</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig_text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">x</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">y</span><span class="o">=</span><span class="mf">0.93</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">s</span><span class="o">=</span><span class="s2">&#34;World map with &lt;PyPalettes&gt; colors&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">fontsize</span><span class="o">=</span><span class="mi">25</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">font</span><span class="o">=</span><span class="n">font</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">highlight_textprops</span><span class="o">=</span><span class="p">[{</span><span class="s2">&#34;font&#34;</span><span class="p">:</span> <span class="n">bold_font</span><span class="p">}],</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig_text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">x</span><span class="o">=</span><span class="mf">0.85</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mf">0.14</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="s2">&#34;Joseph Barbier &amp; Yan Holtz&#34;</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">8</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">,</span> <span class="n">font</span><span class="o">=</span><span class="n">font</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<center>
<p><img src="/matplotlib/pypalettes/map.png" alt=""></p>
</center>
<p>And once the code is working, you can change the color map name and see straight away what it would look like!</p>
<br>
<h2 id="other-usages">Other usages<a class="headerlink" href="#other-usages" title="Link to this heading">#</a></h2>
<p>PyPalettes is primarily designed for <code>matplotlib</code> due to its <strong>high compatibility</strong> with the <code>cmap</code> argument, but one can imagine <strong>much more</strong>.</p>
<p>For example, the output of <code>load_cmap()</code> includes attributes like <code>colors</code> and <code>rgb</code>, which return lists of hexadecimal colors or RGB values. These can be used in <strong>any context</strong>—from Python visualization libraries like Plotly, Plotnine, and Altair to colorimetry, image processing, or any application that requires color!</p>
<br>
<h2 id="learn-more">Learn more<a class="headerlink" href="#learn-more" title="Link to this heading">#</a></h2>
<p>The main links to find out more about this project are as follows:</p>
<ul>
<li>the <a href="https://python-graph-gallery.com/color-palette-finder/">web app</a> to browse the palettes</li>
<li>this <a href="https://python-graph-gallery.com/introduction-to-pypalettes/">introduction to PyPalettes</a> for a more in-depth code explanation</li>
<li>the <a href="https://github.com/JosephBARBIERDARNAL/pypalettes">Github repo</a> with source code and palettes (give us a star! ⭐)</li>
</ul>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                             
                                <category scheme="taxonomy:Tags" term="color" label="color" />
                             
                                <category scheme="taxonomy:Tags" term="colormap" label="colormap" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[How to create custom tables]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/how-to-create-custom-tables/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/visualising-usage-using-batteries/?utm_source=atom_feed" rel="related" type="text/html" title="Battery Charts - Visualise usage rates &amp; more" />
                <link href="https://blog.scientific-python.org/matplotlib/python-graph-gallery.com/?utm_source=atom_feed" rel="related" type="text/html" title="The Python Graph Gallery: hundreds of python charts with reproducible code." />
                <link href="https://blog.scientific-python.org/matplotlib/stellar-chart-alternative-radar-chart/?utm_source=atom_feed" rel="related" type="text/html" title="Stellar Chart, a Type of Chart to Be on Your Radar" />
                <link href="https://blog.scientific-python.org/matplotlib/ipcc-sr15/?utm_source=atom_feed" rel="related" type="text/html" title="Figures in the IPCC Special Report on Global Warming of 1.5°C (SR15)" />
                <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="related" type="text/html" title="Visualizing Code-Switching with Step Charts" />
            
                <id>https://blog.scientific-python.org/matplotlib/how-to-create-custom-tables/</id>
            
            
            <published>2022-03-11T11:10:06+00:00</published>
            <updated>2022-03-11T11:10:06+00:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>A tutorial on how to create custom tables in Matplotlib which allow for flexible design and customization.</blockquote><h1 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Link to this heading">#</a></h1>
<p>This tutorial will teach you how to create custom tables in Matplotlib, which are extremely flexible in terms of the design and layout. You’ll hopefully see that the code is very straightforward! In fact, the main methods we will be using are <code>ax.text()</code> and <code>ax.plot()</code>.</p>
<p>I want to give a lot of credit to <a href="https://twitter.com/CrumpledJumper">Todd Whitehead</a> who has created these types of tables for various Basketball teams and players. His approach to tables is nothing short of fantastic due to the simplicity in design and how he manages to effectively communicate data to his audience. I was very much inspired by his approach and wanted to be able to achieve something similar in Matplotlib.</p>
<p>Before I begin with the tutorial, I wanted to go through the logic behind my approach as I think it&rsquo;s valuable and transferable to other visualizations (and tools!).</p>
<p>With that, I would like you to <strong>think of tables as highly structured and organized scatterplots</strong>. Let me explain why: for me, scatterplots are the most fundamental chart type (regardless of tool).</p>
<p><img src="/matplotlib/how-to-create-custom-tables/scatterplots.png" alt="Scatterplots"></p>
<p>For example <code>ax.plot()</code> automatically &ldquo;connects the dots&rdquo; to form a line chart or <code>ax.bar()</code> automatically &ldquo;draws rectangles&rdquo; across a set of coordinates. Very often (again regardless of tool) we may not always see this process happening. The point is, it is useful to think of any chart as a scatterplot or simply as a collection of shapes based on xy coordinates. This logic / thought process can unlock a ton of <em>custom</em> charts as the only thing you need are the coordinates (which can be mathematically computed).</p>
<p>With that in mind, we can move on to tables! So rather than plotting rectangles or circles we want to plot text and gridlines in a highly organized manner.</p>
<p>We will aim to create a table like this, which I have posted on Twitter <a href="https://twitter.com/TimBayer93/status/1476926897850359809">here</a>. Note, the only elements added outside of Matplotlib are the fancy arrows and their descriptions.</p>
<p><img src="/matplotlib/how-to-create-custom-tables/0_example.png" alt="Example"></p>
<h1 id="creating-a-custom-table">Creating a custom table<a class="headerlink" href="#creating-a-custom-table" title="Link to this heading">#</a></h1>
<p>Importing required libraries.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib</span> <span class="k">as</span> <span class="nn">mpl</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.patches</span> <span class="k">as</span> <span class="nn">patches</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib</span> <span class="kn">import</span> <span class="n">pyplot</span> <span class="k">as</span> <span class="n">plt</span></span></span></code></pre>
</div>
<p>First, we will need to set up a coordinate space - I like two approaches:</p>
<ol>
<li>working with the standard Matplotlib 0-1 scale (on both the x- and y-axis) or</li>
<li>an index system based on row / column numbers (this is what I will use here)</li>
</ol>
<p>I want to create a coordinate space for a table containing 6 columns and 10 rows - this means (similar to pandas row/column indices) each row will have an index between 0-9 and each column will have an index between 0-6 (this is technically 1 more column than what we defined but one of the columns with a lot of text will span two column “indices”)</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># first, we&#39;ll create a new figure and axis object</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># set the number of rows and cols for our table</span>
</span></span><span class="line"><span class="cl"><span class="n">rows</span> <span class="o">=</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="n">cols</span> <span class="o">=</span> <span class="mi">6</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># create a coordinate system based on the number of rows/columns</span>
</span></span><span class="line"><span class="cl"><span class="c1"># adding a bit of padding on bottom (-1), top (1), right (0.5)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">rows</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">cols</span> <span class="o">+</span> <span class="mf">0.5</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/how-to-create-custom-tables/1_coordinate_space.png" alt="Empty Coordinate Space"></p>
<p>Now, the data we want to plot is sports (football) data. We have information about 10 players and some values against a number of different metrics (which will form our columns) such as goals, shots, passes etc.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># sample data</span>
</span></span><span class="line"><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player10&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">79</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player9&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">72</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player8&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">47</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player7&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">99</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">5</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player6&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">84</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">4</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player5&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">56</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player4&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">7</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">67</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player3&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">91</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">1</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player2&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">75</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">2</span><span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;id&#34;</span><span class="p">:</span> <span class="s2">&#34;player1&#34;</span><span class="p">,</span> <span class="s2">&#34;shots&#34;</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s2">&#34;passes&#34;</span><span class="p">:</span> <span class="mi">70</span><span class="p">,</span> <span class="s2">&#34;goals&#34;</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">&#34;assists&#34;</span><span class="p">:</span> <span class="mi">0</span><span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span></span></span></code></pre>
</div>
<p>Next, we will start plotting the table (as a structured scatterplot). I did promise that the code will be very simple, less than 10 lines really, here it is:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># from the sample data, each dict in the list represents one row</span>
</span></span><span class="line"><span class="cl"><span class="c1"># each key in the dict represents a column</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">rows</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># extract the row data from the list</span>
</span></span><span class="line"><span class="cl">    <span class="n">d</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">row</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># the y (row) coordinate is based on the row index (loop)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># the x (column) coordinate is defined based on the order I want to display the data in</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># player name column</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">row</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&#34;id&#34;</span><span class="p">],</span> <span class="n">va</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;left&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># shots column - this is my &#34;main&#34; column, hence bold text</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">row</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&#34;shots&#34;</span><span class="p">],</span> <span class="n">va</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># passes column</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">row</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&#34;passes&#34;</span><span class="p">],</span> <span class="n">va</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># goals column</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">row</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&#34;goals&#34;</span><span class="p">],</span> <span class="n">va</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># assists column</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="n">row</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="n">d</span><span class="p">[</span><span class="s2">&#34;assists&#34;</span><span class="p">],</span> <span class="n">va</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/how-to-create-custom-tables/2_adding_data.png" alt="Adding data"></p>
<p>As you can see, we are starting to get a basic wireframe of our table. Let&rsquo;s add column headers to further make this <em>scatterplot</em> look like a table.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># Add column headers</span>
</span></span><span class="line"><span class="cl"><span class="c1"># plot them at height y=9.75 to decrease the space to the</span>
</span></span><span class="line"><span class="cl"><span class="c1"># first data row (you&#39;ll see why later)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.5</span><span class="p">,</span> <span class="mf">9.75</span><span class="p">,</span> <span class="s2">&#34;Player&#34;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;left&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mf">9.75</span><span class="p">,</span> <span class="s2">&#34;Shots&#34;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mf">9.75</span><span class="p">,</span> <span class="s2">&#34;Passes&#34;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mf">9.75</span><span class="p">,</span> <span class="s2">&#34;Goals&#34;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mf">9.75</span><span class="p">,</span> <span class="s2">&#34;Assists&#34;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mf">9.75</span><span class="p">,</span> <span class="s2">&#34;Special</span><span class="se">\n</span><span class="s2">Column&#34;</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;right&#34;</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s2">&#34;bottom&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/how-to-create-custom-tables/3_headers.png" alt="Adding Headers"></p>
<h1 id="formatting-our-table">Formatting our table<a class="headerlink" href="#formatting-our-table" title="Link to this heading">#</a></h1>
<p>The rows and columns of our table are now done. The only thing that is left to do is formatting - much of this is personal choice. The following elements I think are generally useful when it comes to good table design (more research <a href="https://www.storytellingwithdata.com/blog/2019/10/29/how-i-improved-the-table">here</a>):</p>
<p>Gridlines: Some level of gridlines are useful (less is more). Generally some guidance to help the audience trace their eyes or fingers across the screen can be helpful (this way we can <em>group</em> items too by drawing gridlines around them).</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">rows</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="n">cols</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span> <span class="p">[</span><span class="n">row</span> <span class="o">-</span> <span class="mf">0.5</span><span class="p">,</span> <span class="n">row</span> <span class="o">-</span> <span class="mf">0.5</span><span class="p">],</span> <span class="n">ls</span><span class="o">=</span><span class="s2">&#34;:&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="s2">&#34;.5&#34;</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="s2">&#34;grey&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># add a main header divider</span>
</span></span><span class="line"><span class="cl"><span class="c1"># remember that we plotted the header row slightly closer to the first data row</span>
</span></span><span class="line"><span class="cl"><span class="c1"># this helps to visually separate the header row from the data rows</span>
</span></span><span class="line"><span class="cl"><span class="c1"># each data row is 1 unit in height, thus bringing the header closer to our</span>
</span></span><span class="line"><span class="cl"><span class="c1"># gridline gives it a distinctive difference.</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="n">cols</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span> <span class="p">[</span><span class="mf">9.5</span><span class="p">,</span> <span class="mf">9.5</span><span class="p">],</span> <span class="n">lw</span><span class="o">=</span><span class="s2">&#34;.5&#34;</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/how-to-create-custom-tables/4_gridlines.png" alt="Adding Gridlines"></p>
<p>Another important element for tables in my opinion is highlighting the <em>key</em> data points. We already bolded the values that are in the &ldquo;Shots&rdquo; column but we can further shade this column to give it further importance to our readers.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># highlight the column we are sorting by</span>
</span></span><span class="line"><span class="cl"><span class="c1"># using a rectangle patch</span>
</span></span><span class="line"><span class="cl"><span class="n">rect</span> <span class="o">=</span> <span class="n">patches</span><span class="o">.</span><span class="n">Rectangle</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="mf">1.5</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.5</span><span class="p">),</span>  <span class="c1"># bottom left starting position (x,y)</span>
</span></span><span class="line"><span class="cl">    <span class="mf">0.65</span><span class="p">,</span>  <span class="c1"># width</span>
</span></span><span class="line"><span class="cl">    <span class="mi">10</span><span class="p">,</span>  <span class="c1"># height</span>
</span></span><span class="line"><span class="cl">    <span class="n">ec</span><span class="o">=</span><span class="s2">&#34;none&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">fc</span><span class="o">=</span><span class="s2">&#34;grey&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">alpha</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">zorder</span><span class="o">=-</span><span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">rect</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/how-to-create-custom-tables/5_highlight_column.png" alt="Highlight column"></p>
<p>We&rsquo;re almost there. The magic piece is <code>ax.axis(‘off’)</code>. This hides the axis, axis ticks, labels and everything “attached” to the axes, which means our table now looks like a clean table!</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="s2">&#34;off&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/how-to-create-custom-tables/6_hide_axis.png" alt="Hide axis"></p>
<p>Adding a title is also straightforward.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_title</span><span class="p">(</span><span class="s2">&#34;A title for our table!&#34;</span><span class="p">,</span> <span class="n">loc</span><span class="o">=</span><span class="s2">&#34;left&#34;</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">18</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/how-to-create-custom-tables/6_title.png" alt="Title"></p>
<h1 id="bonus-adding-special-columns">Bonus: Adding special columns<a class="headerlink" href="#bonus-adding-special-columns" title="Link to this heading">#</a></h1>
<p>Finally, if you wish to add images, sparklines, or other custom shapes and patterns then we can do this too.</p>
<p>To achieve this we will create new floating axes using <code>fig.add_axes()</code> to create a new set of floating axes based on the figure coordinates (this is different to our axes coordinate system!).</p>
<p>Remember that figure coordinates by default are between 0 and 1. [0,0] is the bottom left corner of the entire figure. If you’re unfamiliar with the differences between a figure and axes then check out <a href="https://matplotlib.org/stable/gallery/showcase/anatomy.html">Matplotlib&rsquo;s Anatomy of a Figure</a> for further details.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">newaxes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">rows</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># offset each new axes by a set amount depending on the row</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># this is probably the most fiddly aspect (TODO: some neater way to automate this)</span>
</span></span><span class="line"><span class="cl">    <span class="n">newaxes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">([</span><span class="mf">0.75</span><span class="p">,</span> <span class="mf">0.725</span> <span class="o">-</span> <span class="p">(</span><span class="n">row</span> <span class="o">*</span> <span class="mf">0.063</span><span class="p">),</span> <span class="mf">0.12</span><span class="p">,</span> <span class="mf">0.06</span><span class="p">]))</span></span></span></code></pre>
</div>
<p>You can see below what these <em>floating</em> axes will look like (I say floating because they’re on top of our main axis object). The only tricky thing is figuring out the xy (figure) coordinates for these.</p>
<p>These <em>floating</em> axes behave like any other Matplotlib axes. Therefore, we have access to the same methods such as ax.bar(), ax.plot(), patches, etc. Importantly, each axis has its own independent coordinate system. We can format them as we wish.</p>
<p><img src="/matplotlib/how-to-create-custom-tables/7_floating_axes.png" alt="Floating axes"></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># plot dummy data as a sparkline for illustration purposes</span>
</span></span><span class="line"><span class="cl"><span class="c1"># you can plot _anything_ here, images, patches, etc.</span>
</span></span><span class="line"><span class="cl"><span class="n">newaxes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="n">c</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">newaxes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># once again, the key is to hide the axis!</span>
</span></span><span class="line"><span class="cl"><span class="n">newaxes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="s2">&#34;off&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/how-to-create-custom-tables/8_sparklines.png" alt="Sparklines"></p>
<p>That’s it, custom tables in Matplotlib. I did promise very simple code and an ultra-flexible design in terms of what you want / need. You can adjust sizes, colors and pretty much anything with this approach and all you need is simply a loop that plots text in a structured and organized manner. I hope you found it useful. Link to a Google Colab notebook with the code is <a href="https://colab.research.google.com/drive/1JshATKxjs7NWz2U8Oy6xOJaLgjldC1CW">here</a></p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Art from UNC BIOL222]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/unc-biol222/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/ipcc-sr15/?utm_source=atom_feed" rel="related" type="text/html" title="Figures in the IPCC Special Report on Global Warming of 1.5°C (SR15)" />
                <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="related" type="text/html" title="Emoji Mosaic Art" />
                <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="related" type="text/html" title="Creating the Warming Stripes in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/using-matplotlib-to-advocate-for-postdocs/?utm_source=atom_feed" rel="related" type="text/html" title="Using Matplotlib to Advocate for Postdocs" />
                <link href="https://blog.scientific-python.org/matplotlib/book/?utm_source=atom_feed" rel="related" type="text/html" title="Newly released open access book" />
            
                <id>https://blog.scientific-python.org/matplotlib/unc-biol222/</id>
            
            
            <published>2021-11-19T08:46:00-08:00</published>
            <updated>2021-11-19T08:46:00-08:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>UNC BIOL222: Art created with Matplotlib</blockquote><p>As part of the University of North Carolina BIOL222 class, <a href="https://twitter.com/tylikcat">Dr. Catherine Kehl</a> asked her students to &ldquo;use <code>matplotlib.pyplot</code> to make art.&rdquo; BIOL222 is Introduction to Programming, aimed at students with no programming background. The emphasis is on practical, hands-on active learning.</p>
<p>The students completed the assignment with festive enthusiasm around Halloween. Here are some great examples:</p>
<p>Harris Davis showed an affinity for pumpkins, opting to go 3D!
<img src="/matplotlib/unc-biol222/pumpkin.png" alt="3D Pumpkin"></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># get library for 3d plotting</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">mpl_toolkits.mplot3d</span> <span class="kn">import</span> <span class="n">Axes3D</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># make a pumpkin :)</span>
</span></span><span class="line"><span class="cl"><span class="n">rho</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">theta</span><span class="p">,</span> <span class="n">phi</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">meshgrid</span><span class="p">(</span><span class="n">rho</span><span class="p">,</span> <span class="n">rho</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">r</span><span class="p">,</span> <span class="n">R</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span>
</span></span><span class="line"><span class="cl"><span class="n">X</span> <span class="o">=</span> <span class="p">(</span><span class="n">R</span> <span class="o">+</span> <span class="n">r</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">phi</span><span class="p">))</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">theta</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Y</span> <span class="o">=</span> <span class="p">(</span><span class="n">R</span> <span class="o">+</span> <span class="n">r</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">phi</span><span class="p">))</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">theta</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Z</span> <span class="o">=</span> <span class="n">r</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">phi</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># make the stem</span>
</span></span><span class="line"><span class="cl"><span class="n">theta1</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">90</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">r1</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">T1</span><span class="p">,</span> <span class="n">R1</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">meshgrid</span><span class="p">(</span><span class="n">theta1</span><span class="p">,</span> <span class="n">r1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">X1</span> <span class="o">=</span> <span class="n">R1</span> <span class="o">*</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">T1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Y1</span> <span class="o">=</span> <span class="n">R1</span> <span class="o">*</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">T1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Z1</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">X1</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">Y1</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span> <span class="o">-</span> <span class="mf">0.7</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Z1</span><span class="p">[</span><span class="n">Z1</span> <span class="o">&lt;</span> <span class="mf">0.3</span><span class="p">]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">nan</span>
</span></span><span class="line"><span class="cl"><span class="n">Z1</span><span class="p">[</span><span class="n">Z1</span> <span class="o">&gt;</span> <span class="mf">0.7</span><span class="p">]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">nan</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Display the pumpkin &amp; stem</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">gca</span><span class="p">(</span><span class="n">projection</span><span class="o">=</span><span class="s2">&#34;3d&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_xlim3d</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_ylim3d</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_zlim3d</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">plot_surface</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">Y</span><span class="p">,</span> <span class="n">Z</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;tab:orange&#34;</span><span class="p">,</span> <span class="n">rstride</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">cstride</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">plot_surface</span><span class="p">(</span><span class="n">X1</span><span class="p">,</span> <span class="n">Y1</span><span class="p">,</span> <span class="n">Z1</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;tab:green&#34;</span><span class="p">,</span> <span class="n">rstride</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">cstride</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p>Bryce Desantis stuck to the biological theme and demonstrated <a href="https://en.wikipedia.org/wiki/Fractal">fractal</a> art.
<img src="/matplotlib/unc-biol222/leaf.png" alt="Bryce Fern"></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Barnsley&#39;s Fern - Fractal; en.wikipedia.org/wiki/Barnsley_…</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># functions for each part of fern:</span>
</span></span><span class="line"><span class="cl"><span class="c1"># stem</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">stem</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">0.16</span> <span class="o">*</span> <span class="n">y</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># smaller leaflets</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">smallLeaf</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="mf">0.85</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="mf">0.04</span> <span class="o">*</span> <span class="n">y</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.04</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="mf">0.85</span> <span class="o">*</span> <span class="n">y</span> <span class="o">+</span> <span class="mf">1.6</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># large left leaflets</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">leftLarge</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="mf">0.2</span> <span class="o">*</span> <span class="n">x</span> <span class="o">-</span> <span class="mf">0.26</span> <span class="o">*</span> <span class="n">y</span><span class="p">,</span> <span class="mf">0.23</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="mf">0.22</span> <span class="o">*</span> <span class="n">y</span> <span class="o">+</span> <span class="mf">1.6</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># large right leftlets</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">rightLarge</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="o">-</span><span class="mf">0.15</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="mf">0.28</span> <span class="o">*</span> <span class="n">y</span><span class="p">,</span> <span class="mf">0.26</span> <span class="o">*</span> <span class="n">x</span> <span class="o">+</span> <span class="mf">0.24</span> <span class="o">*</span> <span class="n">y</span> <span class="o">+</span> <span class="mf">0.44</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">componentFunctions</span> <span class="o">=</span> <span class="p">[</span><span class="n">stem</span><span class="p">,</span> <span class="n">smallLeaf</span><span class="p">,</span> <span class="n">leftLarge</span><span class="p">,</span> <span class="n">rightLarge</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># number of data points and frequencies for parts of fern generated:</span>
</span></span><span class="line"><span class="cl"><span class="c1"># lists with all 75000 datapoints</span>
</span></span><span class="line"><span class="cl"><span class="n">datapoints</span> <span class="o">=</span> <span class="mi">75000</span>
</span></span><span class="line"><span class="cl"><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="n">datapointsX</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">datapointsY</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="c1"># For 75,000 datapoints</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">datapoints</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">FrequencyFunction</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">choice</span><span class="p">(</span><span class="n">componentFunctions</span><span class="p">,</span> <span class="n">p</span><span class="o">=</span><span class="p">[</span><span class="mf">0.01</span><span class="p">,</span> <span class="mf">0.85</span><span class="p">,</span> <span class="mf">0.07</span><span class="p">,</span> <span class="mf">0.07</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">FrequencyFunction</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">datapointsX</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">datapointsY</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">y</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Scatter plot &amp; scaled down to 0.1 to show more definition:</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">datapointsX</span><span class="p">,</span> <span class="n">datapointsY</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;g&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Title of Figure</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s2">&#34;Barnsley&#39;s Fern - Assignment 3&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Changing background color</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">axes</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="s2">&#34;#d8d7bf&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Grace Bell got a little trippy with this rotationally semetric art. It&rsquo;s pretty cool how she captured mouse events. It reminds us of a flower. What do you see?
<img src="/matplotlib/unc-biol222/rotations.png" alt="Rotations"></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.tri</span> <span class="kn">import</span> <span class="n">Triangulation</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.patches</span> <span class="kn">import</span> <span class="n">Polygon</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># I found this sample code online and manipulated it to make the art piece!</span>
</span></span><span class="line"><span class="cl"><span class="c1"># was interested in because it combined what we used for functions as well as what we used for plotting with (x,y)</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">update_polygon</span><span class="p">(</span><span class="n">tri</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">tri</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">points</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">points</span> <span class="o">=</span> <span class="n">triang</span><span class="o">.</span><span class="n">triangles</span><span class="p">[</span><span class="n">tri</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">xs</span> <span class="o">=</span> <span class="n">triang</span><span class="o">.</span><span class="n">x</span><span class="p">[</span><span class="n">points</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">ys</span> <span class="o">=</span> <span class="n">triang</span><span class="o">.</span><span class="n">y</span><span class="p">[</span><span class="n">points</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">polygon</span><span class="o">.</span><span class="n">set_xy</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">column_stack</span><span class="p">([</span><span class="n">xs</span><span class="p">,</span> <span class="n">ys</span><span class="p">]))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">on_mouse_move</span><span class="p">(</span><span class="n">event</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">inaxes</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">tri</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">tri</span> <span class="o">=</span> <span class="n">trifinder</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">xdata</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">ydata</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">update_polygon</span><span class="p">(</span><span class="n">tri</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_title</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;In triangle </span><span class="si">{</span><span class="n">tri</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">event</span><span class="o">.</span><span class="n">canvas</span><span class="o">.</span><span class="n">draw</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># this is the info that creates the angles</span>
</span></span><span class="line"><span class="cl"><span class="n">n_angles</span> <span class="o">=</span> <span class="mi">14</span>
</span></span><span class="line"><span class="cl"><span class="n">n_radii</span> <span class="o">=</span> <span class="mi">7</span>
</span></span><span class="line"><span class="cl"><span class="n">min_radius</span> <span class="o">=</span> <span class="mf">0.1</span>  <span class="c1"># the radius of the middle circle can move with this variable</span>
</span></span><span class="line"><span class="cl"><span class="n">radii</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="n">min_radius</span><span class="p">,</span> <span class="mf">0.95</span><span class="p">,</span> <span class="n">n_radii</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">angles</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span><span class="p">,</span> <span class="n">n_angles</span><span class="p">,</span> <span class="n">endpoint</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">angles</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">repeat</span><span class="p">(</span><span class="n">angles</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">newaxis</span><span class="p">],</span> <span class="n">n_radii</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">angles</span><span class="p">[:,</span> <span class="mi">1</span><span class="p">::</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span> <span class="o">/</span> <span class="n">n_angles</span>
</span></span><span class="line"><span class="cl"><span class="n">x</span> <span class="o">=</span> <span class="p">(</span><span class="n">radii</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">angles</span><span class="p">))</span><span class="o">.</span><span class="n">flatten</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">y</span> <span class="o">=</span> <span class="p">(</span><span class="n">radii</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">angles</span><span class="p">))</span><span class="o">.</span><span class="n">flatten</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">triang</span> <span class="o">=</span> <span class="n">Triangulation</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">triang</span><span class="o">.</span><span class="n">set_mask</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">np</span><span class="o">.</span><span class="n">hypot</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="n">triang</span><span class="o">.</span><span class="n">triangles</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">),</span> <span class="n">y</span><span class="p">[</span><span class="n">triang</span><span class="o">.</span><span class="n">triangles</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="o">&lt;</span> <span class="n">min_radius</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">trifinder</span> <span class="o">=</span> <span class="n">triang</span><span class="o">.</span><span class="n">get_trifinder</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="n">subplot_kw</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;aspect&#34;</span><span class="p">:</span> <span class="s2">&#34;equal&#34;</span><span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">triplot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">triang</span><span class="p">,</span> <span class="s2">&#34;y+-&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>  <span class="c1"># made the color of the plot yellow and there are &#34;+&#34; for the data points but you can&#39;t really see them because of the lines crossing</span>
</span></span><span class="line"><span class="cl"><span class="n">polygon</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">([[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]],</span> <span class="n">facecolor</span><span class="o">=</span><span class="s2">&#34;y&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">update_polygon</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">polygon</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">canvas</span><span class="o">.</span><span class="n">mpl_connect</span><span class="p">(</span><span class="s2">&#34;motion_notify_event&#34;</span><span class="p">,</span> <span class="n">on_mouse_move</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p>As a bonus, did you like that fox in the banner? That was created (and well documented) by Emily Foster!</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="s2">&#34;off&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># head</span>
</span></span><span class="line"><span class="cl"><span class="n">xhead</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="o">-</span><span class="mi">50</span><span class="p">,</span> <span class="mi">50</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">yhead</span> <span class="o">=</span> <span class="o">-</span><span class="mf">0.007</span> <span class="o">*</span> <span class="p">(</span><span class="n">xhead</span> <span class="o">*</span> <span class="n">xhead</span><span class="p">)</span> <span class="o">+</span> <span class="mi">100</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xhead</span><span class="p">,</span> <span class="n">yhead</span><span class="p">,</span> <span class="s2">&#34;darkorange&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># outer ears</span>
</span></span><span class="line"><span class="cl"><span class="n">xearL</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="o">-</span><span class="mf">45.8</span><span class="p">,</span> <span class="o">-</span><span class="mi">9</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">yearL</span> <span class="o">=</span> <span class="o">-</span><span class="mf">0.08</span> <span class="o">*</span> <span class="p">(</span><span class="n">xearL</span> <span class="o">*</span> <span class="n">xearL</span><span class="p">)</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">xearL</span> <span class="o">+</span> <span class="mi">70</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">xearR</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mf">45.8</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">yearR</span> <span class="o">=</span> <span class="o">-</span><span class="mf">0.08</span> <span class="o">*</span> <span class="p">(</span><span class="n">xearR</span> <span class="o">*</span> <span class="n">xearR</span><span class="p">)</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">xearR</span> <span class="o">+</span> <span class="mi">70</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xearL</span><span class="p">,</span> <span class="n">yearL</span><span class="p">,</span> <span class="s2">&#34;black&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xearR</span><span class="p">,</span> <span class="n">yearR</span><span class="p">,</span> <span class="s2">&#34;black&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># inner ears</span>
</span></span><span class="line"><span class="cl"><span class="n">xinL</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="o">-</span><span class="mf">41.1</span><span class="p">,</span> <span class="o">-</span><span class="mf">13.7</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">yinL</span> <span class="o">=</span> <span class="o">-</span><span class="mf">0.08</span> <span class="o">*</span> <span class="p">(</span><span class="n">xinL</span> <span class="o">*</span> <span class="n">xinL</span><span class="p">)</span> <span class="o">-</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">xinL</span> <span class="o">+</span> <span class="mi">59</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">xinR</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mf">13.7</span><span class="p">,</span> <span class="mf">41.1</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">yinR</span> <span class="o">=</span> <span class="o">-</span><span class="mf">0.08</span> <span class="o">*</span> <span class="p">(</span><span class="n">xinR</span> <span class="o">*</span> <span class="n">xinR</span><span class="p">)</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">xinR</span> <span class="o">+</span> <span class="mi">59</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xinL</span><span class="p">,</span> <span class="n">yinL</span><span class="p">,</span> <span class="s2">&#34;salmon&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xinR</span><span class="p">,</span> <span class="n">yinR</span><span class="p">,</span> <span class="s2">&#34;salmon&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># bottom of face</span>
</span></span><span class="line"><span class="cl"><span class="n">xfaceL</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="o">-</span><span class="mf">49.6</span><span class="p">,</span> <span class="o">-</span><span class="mi">14</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">xfaceR</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">14</span><span class="p">,</span> <span class="mf">49.3</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">xfaceM</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="o">-</span><span class="mi">14</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xfaceL</span><span class="p">,</span> <span class="nb">abs</span><span class="p">(</span><span class="n">xfaceL</span><span class="p">),</span> <span class="s2">&#34;darkorange&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xfaceR</span><span class="p">,</span> <span class="nb">abs</span><span class="p">(</span><span class="n">xfaceR</span><span class="p">),</span> <span class="s2">&#34;darkorange&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xfaceM</span><span class="p">,</span> <span class="nb">abs</span><span class="p">(</span><span class="n">xfaceM</span><span class="p">),</span> <span class="s2">&#34;black&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># nose</span>
</span></span><span class="line"><span class="cl"><span class="n">xnose</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="o">-</span><span class="mi">14</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mf">0.1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ynose</span> <span class="o">=</span> <span class="o">-</span><span class="mf">0.03</span> <span class="o">*</span> <span class="p">(</span><span class="n">xnose</span> <span class="o">*</span> <span class="n">xnose</span><span class="p">)</span> <span class="o">+</span> <span class="mi">20</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xnose</span><span class="p">,</span> <span class="n">ynose</span><span class="p">,</span> <span class="s2">&#34;black&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># whiskers</span>
</span></span><span class="line"><span class="cl"><span class="n">xwhiskR</span> <span class="o">=</span> <span class="p">[</span><span class="mi">50</span><span class="p">,</span> <span class="mi">70</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">70</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">70</span><span class="p">,</span> <span class="mf">49.3</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">xwhiskL</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">50</span><span class="p">,</span> <span class="o">-</span><span class="mi">70</span><span class="p">,</span> <span class="o">-</span><span class="mi">55</span><span class="p">,</span> <span class="o">-</span><span class="mi">70</span><span class="p">,</span> <span class="o">-</span><span class="mi">55</span><span class="p">,</span> <span class="o">-</span><span class="mi">70</span><span class="p">,</span> <span class="o">-</span><span class="mf">49.3</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">ywhisk</span> <span class="o">=</span> <span class="p">[</span><span class="mf">82.6</span><span class="p">,</span> <span class="mi">85</span><span class="p">,</span> <span class="mi">70</span><span class="p">,</span> <span class="mi">65</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="mi">45</span><span class="p">,</span> <span class="mf">49.3</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xwhiskR</span><span class="p">,</span> <span class="n">ywhisk</span><span class="p">,</span> <span class="s2">&#34;darkorange&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xwhiskL</span><span class="p">,</span> <span class="n">ywhisk</span><span class="p">,</span> <span class="s2">&#34;darkorange&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># eyes</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">marker</span><span class="o">=</span><span class="s2">&#34;o&#34;</span><span class="p">,</span> <span class="n">markersize</span><span class="o">=</span><span class="mi">15</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="o">-</span><span class="mi">20</span><span class="p">,</span> <span class="mi">60</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">marker</span><span class="o">=</span><span class="s2">&#34;o&#34;</span><span class="p">,</span> <span class="n">markersize</span><span class="o">=</span><span class="mi">15</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="mi">22</span><span class="p">,</span> <span class="mi">62</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;white&#34;</span><span class="p">,</span> <span class="n">marker</span><span class="o">=</span><span class="s2">&#34;o&#34;</span><span class="p">,</span> <span class="n">markersize</span><span class="o">=</span><span class="mi">6</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="o">-</span><span class="mi">18</span><span class="p">,</span> <span class="mi">62</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;white&#34;</span><span class="p">,</span> <span class="n">marker</span><span class="o">=</span><span class="s2">&#34;o&#34;</span><span class="p">,</span> <span class="n">markersize</span><span class="o">=</span><span class="mi">6</span><span class="p">)</span></span></span></code></pre>
</div>
<p>We look forward to seeing these students continue in their plotting and scientific adventures!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="art" label="art" />
                             
                                <category scheme="taxonomy:Tags" term="academia" label="academia" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Newly released open access book]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/book/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_final/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Final Report" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_quarter/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Quarter Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_prequarter/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Pre-Quarter Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_midterm/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Mid-Term Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_introduction/?utm_source=atom_feed" rel="related" type="text/html" title="Aitik Gupta joins as a Student Developer under GSoC&#39;21" />
            
                <id>https://blog.scientific-python.org/matplotlib/book/</id>
            
            
            <published>2021-11-15T14:26:51+01:00</published>
            <updated>2021-11-15T14:26:51+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>New open access book released</blockquote><p>It&rsquo;s my great pleasure to announce that I&rsquo;ve finished my book on matplotlib and it is now freely available at <a href="https://www.labri.fr/perso/nrougier/scientific-visualization.html">www.labri.fr/perso/nrougier/scientific-visualization.html</a> while sources for the book are hosted at <a href="https://github.com/rougier/scientific-visualization-book">github.com/rougier/scientific-visualization-book</a>.</p>
<h2 id="abstract">Abstract<a class="headerlink" href="#abstract" title="Link to this heading">#</a></h2>
<p>The Python scientific visualisation landscape is huge. It is composed of a myriad of tools, ranging from the most versatile and widely used down to the more specialised and confidential. Some of these tools are community based while others are developed by companies. Some are made specifically for the web, others are for the desktop only, some deal with 3D and large data, while others target flawless 2D rendering. In this landscape, Matplotlib has a very special place. It is a versatile and powerful library that allows you to design very high quality figures, suitable for scientific publishing. It also offers a simple and intuitive interface as well as an object oriented architecture that allows you to tweak anything within a figure. Finally, it can be used as a regular graphic library in order to design non‐scientific figures. This book is organized into four parts. The first part considers the fundamental principles of the Matplotlib library. This includes reviewing the different parts that constitute a figure, the different coordinate systems, the available scales and projections, and we’ll also introduce a few concepts related to typography and colors. The second part is dedicated to the actual design of a figure. After introducing some simple rules for generating better figures, we’ll then go on to explain the Matplotlib defaults and styling system before diving on into figure layout organization. We’ll then explore the different types of plot available and see how a figure can be ornamented with different elements. The third part is dedicated to more advanced concepts, namely 3D figures, optimization &amp; animation. The fourth and final part is a collection of showcases.</p>
<h3 id="book-gallery">Book gallery<a class="headerlink" href="#book-gallery" title="Link to this heading">#</a></h3>
<p><img src="/matplotlib/book/book-gallery.png" alt="A grid of multiple plots showing how data may be visualized."></p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Battery Charts - Visualise usage rates & more]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/visualising-usage-using-batteries/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/python-graph-gallery.com/?utm_source=atom_feed" rel="related" type="text/html" title="The Python Graph Gallery: hundreds of python charts with reproducible code." />
                <link href="https://blog.scientific-python.org/matplotlib/stellar-chart-alternative-radar-chart/?utm_source=atom_feed" rel="related" type="text/html" title="Stellar Chart, a Type of Chart to Be on Your Radar" />
                <link href="https://blog.scientific-python.org/matplotlib/ipcc-sr15/?utm_source=atom_feed" rel="related" type="text/html" title="Figures in the IPCC Special Report on Global Warming of 1.5°C (SR15)" />
                <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="related" type="text/html" title="Visualizing Code-Switching with Step Charts" />
                <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="related" type="text/html" title="Elementary Cellular Automata" />
            
                <id>https://blog.scientific-python.org/matplotlib/visualising-usage-using-batteries/</id>
            
            
            <published>2021-08-19T16:52:58+05:30</published>
            <updated>2021-08-19T16:52:58+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>A tutorial on how to show usage rates and more using batteries</blockquote><h1 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Link to this heading">#</a></h1>
<p>I have been creating common visualisations like scatter plots, bar charts, beeswarms etc. for a while and thought about doing something different. Since I&rsquo;m an avid football fan, I thought of ideas to represent players&rsquo; usage or involvement over a period (a season, a couple of seasons). I have seen some cool visualisations like donuts which depict usage and I wanted to make something different and simple to understand. I thought about representing batteries as a form of player usage and it made a lot of sense.</p>
<p>For players who have been barely used (played fewer minutes) show a <strong><em>large amount of battery</em></strong> present since they have enough energy left in the tank. And for heavily used players, do the opposite i.e. show <strong><em>drained or less amount of battery</em></strong></p>
<p>So, what is the purpose of a battery chart? You can use it to show usage, consumption, involvement, fatigue etc. (anything usage related).</p>
<p>The image below is a sample view of how a battery would look in our figure, although a single battery isn&rsquo;t exactly what we are going to recreate in this tutorial.</p>
<p><img src="/matplotlib/visualising-usage-using-batteries/battery.png" alt="A sample visualisation"></p>
<h1 id="tutorial">Tutorial<a class="headerlink" href="#tutorial" title="Link to this heading">#</a></h1>
<p>Before jumping on to the tutorial, I would like to make it known that the function can be tweaked to fit accordingly depending on the number of subplots or any other size parameter. Coming to the figure we are going to plot, there are a series of steps that is to be considered which we will follow one by one. The following are those steps:-</p>
<ol>
<li>Outlining what we are going to plot</li>
<li>Import necessary libraries</li>
<li>Write a function to draw the battery
<ul>
<li>This is the function that will be called to plot the battery chart</li>
</ul>
</li>
<li>Read the data and plot the chart accordingly
<ul>
<li>We will demonstrate it with an example</li>
</ul>
</li>
</ol>
<h2 id="plot-outline"><span style="text-decoration: underline">Plot Outline</span><a class="headerlink" href="#plot-outline" title="Link to this heading">#</a></h2>
<p>What is our use case?</p>
<ul>
<li>We are given a dataset where we have data of Liverpool&rsquo;s players and their minutes played in the last 2 seasons (for whichever club they for played in that time period). We will use this data for our visualisation.</li>
<li>The final visualisation is the featured image of this blog post. We will navigate step-by-step as to how we&rsquo;ll create the visualisation.</li>
</ul>
<h2 id="importing-libraries"><span style="text-decoration: underline">Importing Libraries</span><a class="headerlink" href="#importing-libraries" title="Link to this heading">#</a></h2>
<p>The first and foremost part is to import the essential libraries so that we can leverage the functions within. In this case, we will import the libraries we need.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="nn">pd</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.path</span> <span class="kn">import</span> <span class="n">Path</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.patches</span> <span class="kn">import</span> <span class="n">FancyBboxPatch</span><span class="p">,</span> <span class="n">PathPatch</span><span class="p">,</span> <span class="n">Wedge</span></span></span></code></pre>
</div>
<p>The functions imported from <code>matplotlib.path</code> and <code>matplotlib.patches</code> will be used to draw lines, rectangles, boxes and so on to display the battery as it is.</p>
<h2 id="drawing-the-battery---a-function"><span style="text-decoration: underline">Drawing the Battery - A function</span><a class="headerlink" href="#drawing-the-battery---a-function" title="Link to this heading">#</a></h2>
<p>The next part is to define a function named <code>draw_battery()</code>, which will be used to draw the battery. Later on, we will call this function by specifying certain parameters to build the figure as we require. The following below is the code to build the battery -</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">draw_battery</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">percentage</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">bat_ec</span><span class="o">=</span><span class="s2">&#34;grey&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">tip_fc</span><span class="o">=</span><span class="s2">&#34;none&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">tip_ec</span><span class="o">=</span><span class="s2">&#34;grey&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">bol_fc</span><span class="o">=</span><span class="s2">&#34;#fdfdfd&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">bol_ec</span><span class="o">=</span><span class="s2">&#34;grey&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">invert_perc</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">    Parameters
</span></span></span><span class="line"><span class="cl"><span class="s2">    ----------
</span></span></span><span class="line"><span class="cl"><span class="s2">    fig : figure
</span></span></span><span class="line"><span class="cl"><span class="s2">        The figure object for the plot
</span></span></span><span class="line"><span class="cl"><span class="s2">    ax : axes
</span></span></span><span class="line"><span class="cl"><span class="s2">        The axes/axis variable of the figure.
</span></span></span><span class="line"><span class="cl"><span class="s2">    percentage : int, optional
</span></span></span><span class="line"><span class="cl"><span class="s2">        This is the battery percentage - size of the fill. The default is 0.
</span></span></span><span class="line"><span class="cl"><span class="s2">    bat_ec : str, optional
</span></span></span><span class="line"><span class="cl"><span class="s2">        The edge color of the battery/cell. The default is &#34;grey&#34;.
</span></span></span><span class="line"><span class="cl"><span class="s2">    tip_fc : str, optional
</span></span></span><span class="line"><span class="cl"><span class="s2">        The fill/face color of the tip of battery. The default is &#34;none&#34;.
</span></span></span><span class="line"><span class="cl"><span class="s2">    tip_ec : str, optional
</span></span></span><span class="line"><span class="cl"><span class="s2">        The edge color of the tip of battery. The default is &#34;grey&#34;.
</span></span></span><span class="line"><span class="cl"><span class="s2">    bol_fc : str, optional
</span></span></span><span class="line"><span class="cl"><span class="s2">        The fill/face color of the lightning bolt. The default is &#34;#fdfdfd&#34;.
</span></span></span><span class="line"><span class="cl"><span class="s2">    bol_ec : str, optional
</span></span></span><span class="line"><span class="cl"><span class="s2">        The edge color of the lightning bolt. The default is &#34;grey&#34;.
</span></span></span><span class="line"><span class="cl"><span class="s2">    invert_perc : bool, optional
</span></span></span><span class="line"><span class="cl"><span class="s2">        A flag to invert the percentage shown inside the battery. The default is False
</span></span></span><span class="line"><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="cl"><span class="s2">    Returns
</span></span></span><span class="line"><span class="cl"><span class="s2">    -------
</span></span></span><span class="line"><span class="cl"><span class="s2">    None.
</span></span></span><span class="line"><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">fig</span><span class="o">.</span><span class="n">set_size_inches</span><span class="p">((</span><span class="mi">15</span><span class="p">,</span> <span class="mi">15</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">xlim</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">20</span><span class="p">),</span> <span class="n">ylim</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="s2">&#34;off&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">invert_perc</span> <span class="o">==</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">percentage</span> <span class="o">=</span> <span class="mi">100</span> <span class="o">-</span> <span class="n">percentage</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># color options - #fc3d2e red &amp; #53d069 green &amp; #f5c54e yellow</span>
</span></span><span class="line"><span class="cl">        <span class="n">bat_fc</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;#fc3d2e&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">percentage</span> <span class="o">&lt;=</span> <span class="mi">20</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span> <span class="s2">&#34;#53d069&#34;</span> <span class="k">if</span> <span class="n">percentage</span> <span class="o">&gt;=</span> <span class="mi">80</span> <span class="k">else</span> <span class="s2">&#34;#f5c54e&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">        Static battery and tip of battery
</span></span></span><span class="line"><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">battery</span> <span class="o">=</span> <span class="n">FancyBboxPatch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mf">2.1</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="mi">10</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="mf">0.8</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;round, pad=0.2, rounding_size=0.5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">fc</span><span class="o">=</span><span class="s2">&#34;none&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ec</span><span class="o">=</span><span class="n">bat_ec</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">fill</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ls</span><span class="o">=</span><span class="s2">&#34;-&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">lw</span><span class="o">=</span><span class="mf">1.5</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">tip</span> <span class="o">=</span> <span class="n">Wedge</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mf">15.35</span><span class="p">,</span> <span class="mf">2.5</span><span class="p">),</span> <span class="mf">0.2</span><span class="p">,</span> <span class="mi">270</span><span class="p">,</span> <span class="mi">90</span><span class="p">,</span> <span class="n">fc</span><span class="o">=</span><span class="s2">&#34;none&#34;</span><span class="p">,</span> <span class="n">ec</span><span class="o">=</span><span class="n">bat_ec</span><span class="p">,</span> <span class="n">fill</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">ls</span><span class="o">=</span><span class="s2">&#34;-&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">3</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">add_artist</span><span class="p">(</span><span class="n">battery</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">add_artist</span><span class="p">(</span><span class="n">tip</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">        Filling the battery cell with the data
</span></span></span><span class="line"><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">filler</span> <span class="o">=</span> <span class="n">FancyBboxPatch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mf">5.1</span><span class="p">,</span> <span class="mf">2.13</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="n">percentage</span> <span class="o">/</span> <span class="mi">10</span><span class="p">)</span> <span class="o">-</span> <span class="mf">0.2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="mf">0.74</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;round, pad=0.2, rounding_size=0.5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">fc</span><span class="o">=</span><span class="n">bat_fc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ec</span><span class="o">=</span><span class="n">bat_fc</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">fill</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ls</span><span class="o">=</span><span class="s2">&#34;-&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">lw</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">add_artist</span><span class="p">(</span><span class="n">filler</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">        Adding a lightning bolt in the centre of the cell
</span></span></span><span class="line"><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">verts</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mf">10.5</span><span class="p">,</span> <span class="mf">3.1</span><span class="p">),</span>  <span class="c1"># top</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mf">8.5</span><span class="p">,</span> <span class="mf">2.4</span><span class="p">),</span>  <span class="c1"># left</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mf">9.5</span><span class="p">,</span> <span class="mf">2.4</span><span class="p">),</span>  <span class="c1"># left mid</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mf">1.9</span><span class="p">),</span>  <span class="c1"># bottom</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="mf">2.6</span><span class="p">),</span>  <span class="c1"># right</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mf">2.6</span><span class="p">),</span>  <span class="c1"># right mid</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="mf">10.5</span><span class="p">,</span> <span class="mf">3.1</span><span class="p">),</span>  <span class="c1"># top</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="n">codes</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="n">Path</span><span class="o">.</span><span class="n">MOVETO</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">Path</span><span class="o">.</span><span class="n">LINETO</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">Path</span><span class="o">.</span><span class="n">LINETO</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">Path</span><span class="o">.</span><span class="n">LINETO</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">Path</span><span class="o">.</span><span class="n">LINETO</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">Path</span><span class="o">.</span><span class="n">LINETO</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">Path</span><span class="o">.</span><span class="n">CLOSEPOLY</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="n">path</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">verts</span><span class="p">,</span> <span class="n">codes</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">bolt</span> <span class="o">=</span> <span class="n">PathPatch</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">fc</span><span class="o">=</span><span class="n">bol_fc</span><span class="p">,</span> <span class="n">ec</span><span class="o">=</span><span class="n">bol_ec</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">1.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">add_artist</span><span class="p">(</span><span class="n">bolt</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="kn">import</span> <span class="nn">traceback</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;EXCEPTION FOUND!!! SAFELY EXITING!!! Find the details below:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">traceback</span><span class="o">.</span><span class="n">print_exc</span><span class="p">()</span></span></span></code></pre>
</div>
<h2 id="reading-the-data"><span style="text-decoration: underline">Reading the Data</span><a class="headerlink" href="#reading-the-data" title="Link to this heading">#</a></h2>
<p>Once we have created the API or function, we can now implement the same. And for that, we need to feed in required data. In our example, we have a dataset that has the list of Liverpool players and the minutes they have played in the past two seasons. The data was collected from <a href="http://www.fbref.com">Football Reference aka FBRef</a>.</p>
<p>We use the read excel function in the pandas library to read our dataset that is stored as an excel file.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">read_excel</span><span class="p">(</span><span class="s2">&#34;Liverpool Minutes Played.xlsx&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Now, let us have a look at how the data looks by listing out the first five rows of our dataset -</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">data</span><span class="o">.</span><span class="n">head</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/visualising-usage-using-batteries/head_data.PNG" alt="The first 5 rows of our dataset"></p>
<h2 id="plotting-our-data"><span style="text-decoration: underline">Plotting our data</span><a class="headerlink" href="#plotting-our-data" title="Link to this heading">#</a></h2>
<p>Now that everything is ready, we go ahead and plot the data. We have 25 players in our dataset, so a 5 x 5 figure is the one to go for. We&rsquo;ll also add some headers and set the colors accordingly.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">facecolor</span> <span class="o">=</span> <span class="s2">&#34;#00001a&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="n">facecolor</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="mf">0.35</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mf">0.95</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Liverpool: Player Usage/Involvement&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">color</span><span class="o">=</span><span class="s2">&#34;white&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">size</span><span class="o">=</span><span class="mi">18</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">fontname</span><span class="o">=</span><span class="s2">&#34;Libre Baskerville&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">fontweight</span><span class="o">=</span><span class="s2">&#34;bold&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="mf">0.25</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mf">0.92</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Data from 19/20 and 20/21 | Battery percentage indicate usage | less battery = played more/ more involved&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">color</span><span class="o">=</span><span class="s2">&#34;white&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">size</span><span class="o">=</span><span class="mi">12</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">fontname</span><span class="o">=</span><span class="s2">&#34;Libre Baskerville&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre>
</div>
<p>We have now now filled in appropriate headers, figure size etc. The next step is to plot all the axes i.e. batteries for each and every player. <code>p</code> is the variable used to iterate through the dataframe and fetch each players data. The <code>draw_battery()</code> function call will obviously plot the battery. We also add the required labels along with that - player name and usage rate/percentage in this case.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">p</span> <span class="o">=</span> <span class="mi">0</span>  <span class="c1"># The variable that&#39;ll iterate through each row of the dataframe (for every player)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span><span class="o">.</span><span class="n">text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="mi">10</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="mi">4</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nb">str</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">p</span><span class="p">,</span> <span class="mi">0</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">            <span class="n">color</span><span class="o">=</span><span class="s2">&#34;white&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">size</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">fontname</span><span class="o">=</span><span class="s2">&#34;Lora&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">va</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="n">facecolor</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">draw_battery</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">],</span> <span class="nb">round</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">p</span><span class="p">,</span> <span class="mi">8</span><span class="p">]),</span> <span class="n">invert_perc</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">        Add the battery percentage as text if a label is required
</span></span></span><span class="line"><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span><span class="o">.</span><span class="n">text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="mi">5</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="mf">0.9</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;Usage - &#34;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="mi">100</span> <span class="o">-</span> <span class="nb">round</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">p</span><span class="p">,</span> <span class="mi">8</span><span class="p">])))</span> <span class="o">+</span> <span class="s2">&#34;%&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">fontsize</span><span class="o">=</span><span class="mi">12</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">color</span><span class="o">=</span><span class="s2">&#34;white&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">p</span> <span class="o">+=</span> <span class="mi">1</span></span></span></code></pre>
</div>
<p>Now that everything is almost done, we do some final touchup and this is a completely optional part anyway. Since the visualisation is focused on Liverpool players, I add Liverpool&rsquo;s logo and also add my watermark. Also, crediting the data source/provider is more of an ethical habit, so we go ahead and do that as well before displaying the plot.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">liv</span> <span class="o">=</span> <span class="n">Image</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">&#34;Liverpool.png&#34;</span><span class="p">,</span> <span class="s2">&#34;r&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">liv</span> <span class="o">=</span> <span class="n">liv</span><span class="o">.</span><span class="n">resize</span><span class="p">((</span><span class="mi">80</span><span class="p">,</span> <span class="mi">80</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">liv</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">liv</span><span class="p">)</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">float</span><span class="p">)</span> <span class="o">/</span> <span class="mi">255</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">figimage</span><span class="p">(</span><span class="n">liv</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">890</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="mf">0.11</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="mf">0.08</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;viz: Rithwik Rajendran/@rithwikrajendra&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">color</span><span class="o">=</span><span class="s2">&#34;lightgrey&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">size</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">fontname</span><span class="o">=</span><span class="s2">&#34;Lora&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="mf">0.8</span><span class="p">,</span> <span class="mf">0.08</span><span class="p">,</span> <span class="s2">&#34;data: FBRef/Statsbomb&#34;</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;lightgrey&#34;</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">fontname</span><span class="o">=</span><span class="s2">&#34;Lora&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p>So, we have the plot below. You can customise the design as you want in the <code>draw_battery()</code> function - change size, colours, shapes etc</p>
<p><img src="/matplotlib/visualising-usage-using-batteries/Liverpool_Usage_Chart.png" alt="Usage Chart Liverpool"></p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC'21: Final Report]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_final/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_quarter/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Quarter Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_prequarter/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Pre-Quarter Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_midterm/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Mid-Term Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_introduction/?utm_source=atom_feed" rel="related" type="text/html" title="Aitik Gupta joins as a Student Developer under GSoC&#39;21" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2020_final_work_product/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC 2020 Work Product - Baseline Images Problem" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_2021_final/</id>
            
            
            <published>2021-08-17T17:36:40+05:30</published>
            <updated>2021-08-17T17:36:40+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Google Summer of Code 2021: Final Report - Aitik Gupta</blockquote><p><strong><ins>Matplotlib: Revisiting Text/Font Handling</ins></strong></p>
<p>To kick things off for the final report, here&rsquo;s a <a href="https://user-images.githubusercontent.com/43996118/129448683-bc136398-afeb-40ac-bbb7-0576757baf3c.jpg">meme</a> to nudge about the <a href="/tags/gsoc/">previous blogs</a>.</p>
<h2 id="about-matplotlib">About Matplotlib<a class="headerlink" href="#about-matplotlib" title="Link to this heading">#</a></h2>
<p>Matplotlib is a comprehensive library for creating static, animated, and interactive visualizations, which has become a <em>de-facto Python plotting library</em>.</p>
<p>Much of the implementation behind its font manager is inspired by <a href="https://www.w3.org/">W3C</a> compliant algorithms, allowing users to interact with font properties like <code>font-size</code>, <code>font-weight</code>, <code>font-family</code>, etc.</p>
<h4 id="however-the-way-matplotlib-handled-fonts-and-general-text-layout-was-not-ideal-which-is-what-summer-2021-was-all-about">However, the way Matplotlib handled fonts and general text layout was not ideal, which is what Summer 2021 was all about.<a class="headerlink" href="#however-the-way-matplotlib-handled-fonts-and-general-text-layout-was-not-ideal-which-is-what-summer-2021-was-all-about" title="Link to this heading">#</a></h4>
<blockquote>
<p>By &ldquo;not ideal&rdquo;, I do not mean that the library has design flaws, but that the design was engineered in the early 2000s, and is now <em>outdated</em>.</p>
</blockquote>
<p>(..more on this later)</p>
<h3 id="about-the-project">About the Project<a class="headerlink" href="#about-the-project" title="Link to this heading">#</a></h3>
<p>(PS: here&rsquo;s <a href="https://docs.google.com/document/d/11PrXKjMHhl0rcQB4p_W9JY_AbPCkYuoTT0t85937nB0/view#heading=h.feg5pv3x59u2">the link</a> to my GSoC proposal, if you&rsquo;re interested)</p>
<p>Overall, the project was divided into two major subgoals:</p>
<ol>
<li>Font Subsetting</li>
<li>Font Fallback</li>
</ol>
<p>But before we take each of them on, we should get an idea about some basic terminology for fonts (which are a <em>lot</em>, and are rightly <em>confusing</em>)</p>
<p>The <a href="https://github.com/matplotlib/matplotlib/pull/20346/files">PR: Clarify/Improve docs on family-names vs generic-families</a> brings about a bit of clarity about some of these terms. The next section has a linked PR which also explains the types of fonts and how that is relevant to Matplotlib.</p>
<h2 id="font-subsetting">Font Subsetting<a class="headerlink" href="#font-subsetting" title="Link to this heading">#</a></h2>
<p>An easy-to-read guide on Fonts and Matplotlib was created with <a href="https://github.com/matplotlib/matplotlib/pull/20450">PR: [Doc] Font Types and Font Subsetting</a>, which is currently live at <a href="https://matplotlib.org/devdocs/users/fonts.html">Matplotlib&rsquo;s DevDocs</a>.</p>
<p>Taking an excerpt from one of my previous blogs (and <a href="https://matplotlib.org/devdocs/users/fonts.html#subsetting">the doc</a>):</p>
<blockquote>
<p>Fonts can be considered as a collection of these glyphs, so ultimately the goal of subsetting is to find out which glyphs are <ins>required</ins> for a certain array of characters, and embed <ins>only those</ins> within the output.</p>
</blockquote>
<p>PDF, PS/EPS and SVG output document formats are special, as in <strong>the text within them can be <ins>editable</ins></strong>, i.e, one can copy/search text from documents (for eg, from a PDF file) if the text is editable.</p>
<h3 id="matplotlib-and-subsetting">Matplotlib and Subsetting<a class="headerlink" href="#matplotlib-and-subsetting" title="Link to this heading">#</a></h3>
<p>The PDF, PS/EPS and SVG backends used to support font subsetting, <em>only for a few types</em>. What that means is, before Summer &lsquo;21, Matplotlib could generate Type 3 subsets for PDF, PS/EPS backends, but it <ins><em>could not</em></ins> generate Type 42 / TrueType subsets.</p>
<p>With <a href="https://github.com/matplotlib/matplotlib/pull/20391">PR: Type42 subsetting in PS/PDF</a> merged in, users can expect their PDF/PS/EPS documents to contains subsetted glyphs from the original fonts.</p>
<p>This is especially beneficial for people who wish to use <ins>commercial</ins> (or <a href="https://en.wikipedia.org/wiki/CJK_characters">CJK</a>) fonts. Licenses for many fonts <strong><em>require</em></strong> subsetting such that they can’t be trivially copied from the output files generated from Matplotlib.</p>
<h2 id="font-fallback">Font Fallback<a class="headerlink" href="#font-fallback" title="Link to this heading">#</a></h2>
<p>Matplotlib was designed to work with a single font at runtime. A user <em>could</em> specify a <code>font.family</code>, which was supposed to correspond to <a href="https://www.w3schools.com/cssref/pr_font_font-family.asp">CSS</a> properties, but that was only used to find a <em>single</em> font present on the user&rsquo;s system.</p>
<p>Once that font was found (which is almost always found, since Matplotlib ships with a set of default fonts), all the user text was rendered only through that font. (which used to give out &ldquo;<ins>tofu</ins>&rdquo; if a character wasn&rsquo;t found)</p>
<hr>
<p>It might seem like an <em>outdated</em> approach for text rendering, now that we have these concepts like font-fallback, <ins>but these concepts weren&rsquo;t very well discussed in early 2000s</ins>. Even getting a single font to work <em>was considered a hard engineering problem</em>.</p>
<p>This was primarily because of the lack of <strong>any standardization</strong> for representation of fonts (Adobe had their own font representation, and so did Apple, Microsoft, etc.)</p>
<table>
  <thead>
      <tr>
          <th><img src="https://user-images.githubusercontent.com/43996118/128605750-9d76fa4a-ce57-45c6-af23-761334d48ef7.png" alt="Previous"></th>
          <th><img src="https://user-images.githubusercontent.com/43996118/128605746-9f79ebeb-c03d-407e-9e27-c3203a210908.png" alt="After"></th>
      </tr>
  </thead>
  <tbody>
  </tbody>
</table>
<p align="middle">
    <ins>Previous</ins> (notice <i>Tofus</i>) VS  <ins>After</ins> (CJK font as fallback)
</p>
<p>To migrate from a font-first approach to a text-first approach, there are multiple steps involved:</p>
<h3 id="parsing-the-whole-font-family">Parsing the whole font family<a class="headerlink" href="#parsing-the-whole-font-family" title="Link to this heading">#</a></h3>
<p>The very first (and crucial!) step is to get to a point where we have multiple font paths (ideally individual font files for the whole family). That is achieved with either:</p>
<ul>
<li><a href="https://github.com/matplotlib/matplotlib/pull/20496">PR: [with findfont diff] Parsing all families in font_manager</a>, or</li>
<li><a href="https://github.com/matplotlib/matplotlib/pull/20549">PR: [without findfont diff] Parsing all families in font_manager</a></li>
</ul>
<p>Quoting one of my <a href="../gsoc_2021_prequarter/">previous</a> blogs:</p>
<blockquote>
<p>Don’t break, a lot at stake!</p>
</blockquote>
<p>My first approach was to change the existing public <code>findfont</code> API to incorporate multiple filepaths. Since Matplotlib has a <em>very huge</em> userbase, there&rsquo;s a high chance it would break a chunk of people&rsquo;s workflow:</p>
<p align="center">
  <img src="https://user-images.githubusercontent.com/43996118/129636132-47b141b3-f149-49b7-b0c0-67c256bd6ee1.png" alt="FamilyParsingFlowChart" width="60%" />
  First PR (left), Second PR (right)
</p>
<h3 id="ft2font-overhaul">FT2Font Overhaul<a class="headerlink" href="#ft2font-overhaul" title="Link to this heading">#</a></h3>
<p>Once we get a list of font paths, we need to change the internal representation of a &ldquo;font&rdquo;. Matplotlib has a utility called FT2Font, which is written in C++, and used with wrappers as a Python extension, which in turn is used throughout the backends. For all intents and purposes, it used to mean: <code>FT2Font === SingleFont</code> (if you&rsquo;re interested, here&rsquo;s a <a href="https://user-images.githubusercontent.com/43996118/128352387-76a3f52a-20fc-4853-b624-0c91844fc785.png">meme</a> about how FT2Font was named!)</p>
<p>But that is not the case anymore, here&rsquo;s a flowchart to explain what happens now:</p>
<p align="center">
  <img src="https://user-images.githubusercontent.com/43996118/129720023-14f5d67f-f279-433f-ad78-e5eccb6c784a.png" alt="FamilyParsingFlowChart" width="100%" />
  Font-Fallback Algorithm
</p>
<p>With <a href="https://github.com/matplotlib/matplotlib/pull/20740">PR: Implement Font-Fallback in Matplotlib</a>, every FT2Font object has a <code>std::vector&lt;FT2Font *&gt; fallback_list</code>, which is used for filling the parent cache, as can be seen in the self-explanatory flowchart.</p>
<p>For simplicity, only one type of cache (<ins>character -&gt; FT2Font</ins>) is shown, whereas in actual implementation there&rsquo;s 2 types of caches, one shown above, and another for glyphs (<ins>glyph_id -&gt; FT2Font</ins>).</p>
<blockquote>
<p>Note: Only the parent&rsquo;s APIs are used in some backends, so for each of the individual public functions like <code>load_glyph</code>, <code>load_char</code>, <code>get_kerning</code>, etc., we find the FT2Font object which has that glyph from the parent FT2Font cache!</p>
</blockquote>
<h3 id="multi-font-embedding-in-pdfpseps">Multi-Font embedding in PDF/PS/EPS<a class="headerlink" href="#multi-font-embedding-in-pdfpseps" title="Link to this heading">#</a></h3>
<p>Now that we have multiple fonts to render a string, we also need to embed them for those special backends (i.e., PDF/PS, etc.). This was done with some patches to specific backends:</p>
<ul>
<li><a href="https://github.com/matplotlib/matplotlib/pull/20804">PR: Implement multi-font embedding for PDF Backend</a></li>
<li><a href="https://github.com/matplotlib/matplotlib/pull/20832">PR: Implement multi-font embedding for PS Backend</a></li>
</ul>
<p>With this, one could create a PDF or a PS/EPS document with multiple fonts which are embedded (and subsetted!).</p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Link to this heading">#</a></h2>
<p>From small contributions to eventually working on a core module of such a huge library, the road was not what I had imagined, and I learnt a lot while designing solutions to these problems.</p>
<h4 id="the-work-i-did-would-eventually-end-up-affecting-every-single-matplotlib-user">The work I did would eventually end up affecting every single Matplotlib user.<a class="headerlink" href="#the-work-i-did-would-eventually-end-up-affecting-every-single-matplotlib-user" title="Link to this heading">#</a></h4>
<p>&hellip;since all plots will work their way through the new codepath!</p>
<p>I think that single statement is worth the <ins>whole GSoC project</ins>.</p>
<h3 id="pull-request-statistics">Pull Request Statistics<a class="headerlink" href="#pull-request-statistics" title="Link to this heading">#</a></h3>
<p>For the sake of statistics (and to make GSoC sound a bit less intimidating), here&rsquo;s a list of contributions I made to Matplotlib <ins>before Summer &lsquo;21</ins>, most of which are only a few lines of diff:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: center">Created At</th>
          <th>PR Title</th>
          <th style="text-align: center">Diff</th>
          <th style="text-align: center">Status</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: center">Nov 2, 2020</td>
          <td><a href="https://github.com/matplotlib/matplotlib/pull/18870">Expand ScalarMappable.set_array to accept array-like inputs</a></td>
          <td style="text-align: center">(+28 −4)</td>
          <td style="text-align: center">MERGED</td>
      </tr>
      <tr>
          <td style="text-align: center">Nov 8, 2020</td>
          <td><a href="https://github.com/matplotlib/matplotlib/pull/18916">Add overset and underset support for mathtext</a></td>
          <td style="text-align: center">(+71 −0)</td>
          <td style="text-align: center">MERGED</td>
      </tr>
      <tr>
          <td style="text-align: center">Nov 14, 2020</td>
          <td><a href="https://github.com/matplotlib/matplotlib/pull/18947">Strictly increasing check with test coverage for streamplot grid</a></td>
          <td style="text-align: center">(+54 −2)</td>
          <td style="text-align: center">MERGED</td>
      </tr>
      <tr>
          <td style="text-align: center">Jan 11, 2021</td>
          <td><a href="https://github.com/matplotlib/matplotlib/pull/19271">WIP: Add support to edit subplot configurations via textbox</a></td>
          <td style="text-align: center">(+51 −11)</td>
          <td style="text-align: center">DRAFT</td>
      </tr>
      <tr>
          <td style="text-align: center">Jan 18, 2021</td>
          <td><a href="https://github.com/matplotlib/matplotlib/pull/19314">Fix over/under mathtext symbols</a></td>
          <td style="text-align: center">(+7,459 −4,169)</td>
          <td style="text-align: center">MERGED</td>
      </tr>
      <tr>
          <td style="text-align: center">Feb 11, 2021</td>
          <td><a href="https://github.com/matplotlib/matplotlib/pull/19497">Add overset/underset whatsnew entry</a></td>
          <td style="text-align: center">(+28 −17)</td>
          <td style="text-align: center">MERGED</td>
      </tr>
      <tr>
          <td style="text-align: center">May 15, 2021</td>
          <td><a href="https://github.com/matplotlib/matplotlib/pull/20235">Warn user when mathtext font is used for ticks</a></td>
          <td style="text-align: center">(+28 −0)</td>
          <td style="text-align: center">MERGED</td>
      </tr>
  </tbody>
</table>
<p>Here&rsquo;s a list of PRs I opened <ins>during Summer'21</ins>:</p>
<ul>
<li>[Status: ✅] <a href="https://github.com/matplotlib/matplotlib/pull/20346">Clarify/Improve docs on family-names vs generic-families</a></li>
<li>[Status: ✅] <a href="https://github.com/matplotlib/matplotlib/pull/20367">Add parse_math in Text and default it False for TextBox</a></li>
<li>[Status: ✅] <a href="https://github.com/matplotlib/matplotlib/pull/20391">Type42 subsetting in PS/PDF</a></li>
<li>[Status: ✅] <a href="https://github.com/matplotlib/matplotlib/pull/20450">[Doc] Font Types and Font Subsetting</a></li>
<li>[Status: 🚧] <a href="https://github.com/matplotlib/matplotlib/pull/20496">[with findfont diff] Parsing all families in font_manager</a></li>
<li>[Status: 🚧] <a href="https://github.com/matplotlib/matplotlib/pull/20549">[without findfont diff] Parsing all families in font_manager</a></li>
<li>[Status: 🚧] <a href="https://github.com/matplotlib/matplotlib/pull/20740">Implement Font-Fallback in Matplotlib</a></li>
<li>[Status: 🚧] <a href="https://github.com/matplotlib/matplotlib/pull/20804">Implement multi-font embedding for PDF Backend</a></li>
<li>[Status: 🚧] <a href="https://github.com/matplotlib/matplotlib/pull/20832">Implement multi-font embedding for PS Backend</a></li>
</ul>
<h2 id="acknowledgements">Acknowledgements<a class="headerlink" href="#acknowledgements" title="Link to this heading">#</a></h2>
<p>From learning about software engineering fundamentals from <a href="https://github.com/tacaswell">Tom</a> to learning about nitty-gritty details about font representations from <a href="https://github.com/jkseppan">Jouni</a>;</p>
<p>From learning through <a href="https://github.com/anntzer">Antony</a>&rsquo;s patches and pointers to receiving amazing feedback on these blogs from <a href="https://github.com/story645">Hannah</a>, it has been an adventure! 💯</p>
<p><em>Special Mentions: <a href="https://github.com/sauerburger">Frank</a>, <a href="https://github.com/srijan-paul">Srijan</a> and <a href="https://github.com/tfidfwastaken">Atharva</a> for their helping hands!</em></p>
<p>And lastly, <em>you</em>, the reader; if you&rsquo;ve been following my <a href="/tags/gsoc/">previous blogs</a>, or if you&rsquo;ve landed at this one directly, I thank you nevertheless. (one last <a href="https://user-images.githubusercontent.com/43996118/126441988-5a2067fd-055e-44e5-86e9-4dddf47abc9d.png">meme</a>, I promise!)</p>
<p>I know I speak for every developer out there, when I say <ins><strong><em>it means a lot</em></strong></ins> when you choose to look at their journey or their work product; it could as well be a tiny website, or it could be as big as designing a complete library!</p>
<hr>
<blockquote>
<p>I&rsquo;m grateful to <a href="https://matplotlib.org/">Maptlotlib</a> (under the parent organisation: <a href="https://numfocus.org/">NumFOCUS</a>), and of course, <a href="https://summerofcode.withgoogle.com/">Google Summer of Code</a> for this incredible learning opportunity.</p>
</blockquote>
<p>Farewell, reader! :&rsquo;)</p>
<p align="center">
  <img src="https://user-images.githubusercontent.com/43996118/118876008-5e6dd580-b90a-11eb-96db-0abc930c6993.png" alt="MatplotlibGSoC" />
  Consider contributing to Matplotlib (Open Source in general) ❤️
</p>
<h4 id="note-this-blog-post-is-also-available-at-my-personal-website">NOTE: This blog post is also available at my <a href="https://aitikgupta.github.io/gsoc-final/">personal website</a>.<a class="headerlink" href="#note-this-blog-post-is-also-available-at-my-personal-website" title="Link to this heading">#</a></h4>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC'21: Quarter Progress]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_quarter/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_prequarter/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Pre-Quarter Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_midterm/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Mid-Term Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_introduction/?utm_source=atom_feed" rel="related" type="text/html" title="Aitik Gupta joins as a Student Developer under GSoC&#39;21" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2020_final_work_product/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC 2020 Work Product - Baseline Images Problem" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_5/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 3 Blog 1" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_2021_quarter/</id>
            
            
            <published>2021-08-03T18:48:00+05:30</published>
            <updated>2021-08-03T18:48:00+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Quarter Progress with Google Summer of Code 2021 project under NumFOCUS: Aitik Gupta</blockquote><p><strong>“<ins>Matplotlib, I want 多个汉字 in between my text.</ins>”</strong></p>
<p>Let&rsquo;s say you asked Matplotlib to render a plot with some label containing 多个汉字 (multiple Chinese characters) in between your English text.</p>
<p>Or conversely, let&rsquo;s say you use a Chinese font with Matplotlib, but you had English text in between (which is quite common).</p>
<blockquote>
<p>Assumption: the Chinese font doesn&rsquo;t have those English glyphs, and vice versa</p>
</blockquote>
<p>With this short writeup, I&rsquo;ll talk about how does a migration from a font-first to a text-first approach in Matplotlib looks like, which ideally solves the above problem.</p>
<h3 id="have-the-fonts">Have the fonts?<a class="headerlink" href="#have-the-fonts" title="Link to this heading">#</a></h3>
<p>Logically, the very first step to solving this would be to ask whether you <em>have</em> multiple fonts, right?</p>
<p>Matplotlib doesn&rsquo;t ship <a href="https://en.wikipedia.org/wiki/List_of_CJK_fonts">CJK</a> (Chinese Japanese Korean) fonts, which ideally contains these Chinese glyphs. It does try to cover most grounds with the <a href="https://matplotlib.org/stable/users/dflt_style_changes.html#normal-text">default font</a> it ships with, however.</p>
<p>So if you don&rsquo;t have a font to render your Chinese characters, go ahead and install one! Matplotlib will find your installed fonts (after rebuilding the cache, that is).</p>
<h3 id="parse-the-fonts">Parse the fonts<a class="headerlink" href="#parse-the-fonts" title="Link to this heading">#</a></h3>
<p>This is where things get interesting, and what my <a href="../gsoc_2021_prequarter/">previous writeup</a> was all about..</p>
<blockquote>
<p>Parsing the whole family to get multiple fonts for given font properties</p>
</blockquote>
<h2 id="ft2font-magic">FT2Font Magic!<a class="headerlink" href="#ft2font-magic" title="Link to this heading">#</a></h2>
<p>To give you an idea about how things used to work for Matplotlib:</p>
<ol>
<li>A single font was chosen <em>at draw time</em>
(fixed: re <a href="../gsoc_2021_prequarter/">previous writeup</a>)</li>
<li>Every character displayed in your document was rendered by only that font
(partially fixed: re <ins><em>this writeup</em></ins>)</li>
</ol>
<blockquote>
<p>FT2Font is a matplotlib-to-font module, which provides high-level Python API to interact with a <em>single font&rsquo;s operations</em> like read/draw/extract/etc.</p>
</blockquote>
<p>Being written in C++, the module needs wrappers around it to be converted into a <a href="https://docs.python.org/3/extending/extending.html">Python extension</a> using Python&rsquo;s C-API.</p>
<blockquote>
<p>It allows us to use C++ functions directly from Python!</p>
</blockquote>
<p>So wherever you see a use of font within the library (by library I mean the readable Python codebase XD), you could have derived that:</p>

<div class="highlight">
  <pre>FT2Font === SingleFont</pre>
</div>

<p>Things are be a bit different now however..</p>
<h2 id="designing-a-multi-font-system">Designing a multi-font system<a class="headerlink" href="#designing-a-multi-font-system" title="Link to this heading">#</a></h2>
<p>FT2Font is basically itself a wrapper around a library called <a href="https://www.freetype.org/">FreeType</a>, which is a freely available software library to render fonts.</p>
<p align="center">
    <figure>
        <img src="https://user-images.githubusercontent.com/43996118/128352387-76a3f52a-20fc-4853-b624-0c91844fc785.png" alt="FT2Font Naming" />
        <figcaption style="text-align: center; font-style: italic;">How FT2Font was named</figcaption>
    </figure>
</p>
<p>In my initial proposal.. while looking around how FT2Font is structured, I figured:</p>

<div class="highlight">
  <pre>Oh, looks like all we need are Faces!</pre>
</div>

<blockquote>
<p>If you don&rsquo;t know what faces/glyphs/ligatures are, head over to why <a href="https://gankra.github.io/blah/text-hates-you/">Text Hates You</a>. I can guarantee you&rsquo;ll definitely enjoy some real life examples of why text rendering is hard. 🥲</p>
</blockquote>
<p>Anyway, if you already know what Faces are, it might strike you:</p>
<p>If we already have all the faces we need from multiple fonts (let&rsquo;s say we created a child of FT2Font.. which only <ins>tracks the faces</ins> for its families), we should be able to render everything from that parent FT2Font right?</p>
<p>As I later figured out while finding segfaults in implementing this design:</p>

<div class="highlight">
  <pre>Each FT2Font is linked to a single FT_Library object!</pre>
</div>

<p>If you tried to load the face/glyph/character (basically anything) from a different FT2Font object.. you&rsquo;ll run into serious segfaults. (because one object linked to an <code>FT_Library</code> can&rsquo;t really access another object which has it&rsquo;s own <code>FT_Library</code>)</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1">// face is linked to FT2Font; which is
</span></span></span><span class="line"><span class="cl"><span class="c1">// linked to a single FT_Library object
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">FT_Face</span> <span class="n">face</span> <span class="o">=</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">get_face</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">FT_Get_Glyph</span><span class="p">(</span><span class="n">face</span><span class="o">-&gt;</span><span class="n">glyph</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">placeholder</span><span class="p">);</span> <span class="c1">// works like a charm
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// somehow get another FT2Font&#39;s face
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">FT_Face</span> <span class="n">family_face</span> <span class="o">=</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">get_family_member</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">get_face</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">FT_Get_Glyph</span><span class="p">(</span><span class="n">family_face</span><span class="o">-&gt;</span><span class="n">glyph</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">placeholder</span><span class="p">);</span> <span class="c1">// segfaults!
</span></span></span></code></pre>
</div>
<p>Realizing this took a good amount of time! After this I quickly came up with a recursive approach, wherein we:</p>
<ol>
<li>Create a list of FT2Font objects within Python, and pass it down to FT2Font</li>
<li>FT2Font will hold pointers to its families via a <br>
<code>std::vector&lt;FT2Font *&gt; fallback_list</code></li>
<li>Find if the character we want is available in the current font
<ol>
<li>If the character is available, use that FT2Font to render that character</li>
<li>If the character isn&rsquo;t found, go to step 3 again, but now iterate through the <code>fallback_list</code></li>
</ol>
</li>
<li>That&rsquo;s it!</li>
</ol>
<p>A quick overhaul of the above piece of code^</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kt">bool</span> <span class="nf">ft_get_glyph</span><span class="p">(</span><span class="n">FT_Glyph</span> <span class="o">&amp;</span><span class="n">placeholder</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="n">FT_Error</span> <span class="n">not_found</span> <span class="o">=</span> <span class="n">FT_Get_Glyph</span><span class="p">(</span><span class="k">this</span><span class="o">-&gt;</span><span class="n">get_face</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">placeholder</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="p">(</span><span class="n">not_found</span><span class="p">)</span> <span class="k">return</span> <span class="n">False</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">	<span class="k">else</span> <span class="k">return</span> <span class="n">True</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// within driver code
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="k">for</span> <span class="p">(</span><span class="n">uint</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">fallback_list</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="c1">// iterate through all FT2Font objects
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>	<span class="kt">bool</span> <span class="n">was_found</span> <span class="o">=</span> <span class="n">fallback_list</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-&gt;</span><span class="n">ft_get_glyph</span><span class="p">(</span><span class="n">placeholder</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="p">(</span><span class="n">was_found</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre>
</div>
<p>With the idea surrounding this implementation, the <a href="https://matplotlib.org/stable/api/backend_agg_api.html">Agg backend</a> is able to render a document (either through GUI, or a PNG) with multiple fonts!</p>
<p align="center">
    <figure>
        <img src="https://user-images.githubusercontent.com/43996118/128347495-1f4f858d-33d3-4119-8732-5b26c4e9ca2a.png" alt="ChineseInBetween" />
        <figcaption style="text-align: center; font-style: italic;">PNG straight outta Matplotlib!</figcaption>
    </figure>
</p>
<h2 id="python-c-api-is-hard-at-first">Python C-API is hard, at first!<a class="headerlink" href="#python-c-api-is-hard-at-first" title="Link to this heading">#</a></h2>
<p>I&rsquo;ve spent days at Python C-API&rsquo;s <a href="https://docs.python.org/3/c-api/arg.html">argument doc</a>, and it&rsquo;s hard to get what you need at first, ngl.</p>
<p>But, with the help of some amazing people in the GSoC community (<a href="https://srijan-paul.github.io/">@srijan-paul</a>, <a href="https://atharvaraykar.me/">@atharvaraykar</a>) and amazing mentors, blockers begone!</p>
<h2 id="so-are-we-done">So are we done?<a class="headerlink" href="#so-are-we-done" title="Link to this heading">#</a></h2>
<p>Oh no. XD</p>
<p>Things work just fine for the Agg backend, but to generate a PDF/PS/SVG with multiple fonts is another story altogether! I think I&rsquo;ll save that for later.</p>
<p align="center">
    <figure>
        <img src="https://user-images.githubusercontent.com/43996118/128350093-13695b91-5ad2-4f96-91f5-8373ee7a189e.gif" alt="ThankYouDwight" />
        <figcaption style="text-align: center; font-style: italic;">If you've been following the progress so far, mayn you're awesome!</figcaption>
    </figure>
</p>
<h4 id="note-this-blog-post-is-also-available-at-my-personal-website">NOTE: This blog post is also available at my <a href="https://aitikgupta.github.io/gsoc-quarter/">personal website</a>.<a class="headerlink" href="#note-this-blog-post-is-also-available-at-my-personal-website" title="Link to this heading">#</a></h4>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[The Python Graph Gallery: hundreds of python charts with reproducible code.]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/python-graph-gallery.com/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="related" type="text/html" title="Visualizing Code-Switching with Step Charts" />
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/stellar-chart-alternative-radar-chart/?utm_source=atom_feed" rel="related" type="text/html" title="Stellar Chart, a Type of Chart to Be on Your Radar" />
                <link href="https://blog.scientific-python.org/matplotlib/ipcc-sr15/?utm_source=atom_feed" rel="related" type="text/html" title="Figures in the IPCC Special Report on Global Warming of 1.5°C (SR15)" />
                <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="related" type="text/html" title="Elementary Cellular Automata" />
            
                <id>https://blog.scientific-python.org/matplotlib/python-graph-gallery.com/</id>
            
            
            <published>2021-07-24T14:06:57+02:00</published>
            <updated>2021-07-24T14:06:57+02:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>The Python Graph Gallery is a website that displays hundreds of chart examples made with python. It goes from very basic to highly customized examples and is based on common viz libraries like matplotlib, seaborn or plotly.</blockquote><p>Data visualization is a key step in a data science pipeline. <a href="https://www.python.org">Python</a> offers great possibilities when it comes to representing some data graphically, but it can be hard and time-consuming to create the appropriate chart.</p>
<p>The <a href="https://www.python-graph-gallery.com">Python Graph Gallery</a> is here to help. It displays many examples, always providing the reproducible code. It allows to build the desired chart in minutes.</p>
<h1 id="about-400-charts-in-40-sections">About 400 charts in 40 sections<a class="headerlink" href="#about-400-charts-in-40-sections" title="Link to this heading">#</a></h1>
<p>The gallery currently provides more than <a href="https://www.python-graph-gallery.com/all-charts/">400 chart examples</a>. Those examples are organized in 40 sections, one for each chart types: <a href="https://www.python-graph-gallery.com/scatter-plot/">scatterplot</a>, <a href="https://www.python-graph-gallery.com/boxplot/">boxplot</a>, <a href="https://www.python-graph-gallery.com/barplot/">barplot</a>, <a href="https://www.python-graph-gallery.com/treemap/">treemap</a> and so on. Those chart types are organized in 7 big families as suggested by <a href="https://www.data-to-viz.com">data-to-viz.com</a>: one for each visualization purpose.</p>
<p>It is important to note that not only the most common chart types are covered. Lesser known charts like <a href="https://www.python-graph-gallery.com/chord-diagram/">chord diagrams</a>, <a href="https://www.python-graph-gallery.com/streamchart/">streamgraphs</a> or <a href="https://www.python-graph-gallery.com/bubble-map/">bubble maps</a> are also available.</p>
<p><img src="/matplotlib/python-graph-gallery.com/sections-overview.png" alt="overview of the python graph gallery sections"></p>
<h1 id="master-the-basics">Master the basics<a class="headerlink" href="#master-the-basics" title="Link to this heading">#</a></h1>
<p>Each section always starts with some very basic examples. It allows to understand how to build a chart type in a few seconds. Hopefully applying the same technique on another dataset will thus be very quick.</p>
<p>For instance, the <a href="https://www.python-graph-gallery.com/scatter-plot/">scatterplot section</a> starts with this <a href="https://matplotlib.org/">matplotlib</a> example. It shows how to create a dataset with <a href="https://pandas.pydata.org/">pandas</a> and plot it with the <code>plot()</code> function. The main graph argument like <code>linestyle</code> and <code>marker</code> are described to make sure the code is understandable.</p>
<p><a href="https://www.python-graph-gallery.com/130-basic-matplotlib-scatterplot"><em>blogpost overview</em>:</a></p>
<p><img src="/matplotlib/python-graph-gallery.com/scatterplot-example.png" alt="a basic scatterplot example"></p>
<h1 id="matplotlib-customization">Matplotlib customization<a class="headerlink" href="#matplotlib-customization" title="Link to this heading">#</a></h1>
<p>The gallery uses several libraries like <a href="https://www.python-graph-gallery.com/seaborn/">seaborn</a> or <a href="https://www.python-graph-gallery.com/plotly/">plotly</a> to produce its charts, but is mainly focus on matplotlib. Matplotlib comes with great flexibility and allows to build any kind of chart without limits.</p>
<p>A <a href="https://www.python-graph-gallery.com/matplotlib/">whole page</a> is dedicated to matplotlib. It describes how to solve recurring issues like customizing <a href="https://www.python-graph-gallery.com/191-custom-axis-on-matplotlib-chart">axes</a> or <a href="https://www.python-graph-gallery.com/190-custom-matplotlib-title">titles</a>, adding <a href="https://www.python-graph-gallery.com/193-annotate-matplotlib-chart">annotations</a> (see below) or even using <a href="https://www.python-graph-gallery.com/custom-fonts-in-matplotlib">custom fonts</a>.</p>
<p><img src="/matplotlib/python-graph-gallery.com/annotations.png" alt="annotation examples"></p>
<p>The gallery is also full of non-straightforward examples. For instance, it has a <a href="https://www.python-graph-gallery.com/streamchart-basic-matplotlib">tutorial</a> explaining how to build a streamchart with matplotlib. It is based on the <code>stackplot()</code> function and adds some smoothing to it:</p>
<p><img src="/matplotlib/python-graph-gallery.com/streamchart.png" alt="stream chart with python and matplotlib"></p>
<p>Last but not least, the gallery also displays some publication ready charts. They usually involve a lot of matplotlib code, but showcase the fine grain control one has over a plot.</p>
<p>Here is an example with a post inspired by <a href="https://www.r-graph-gallery.com/web-violinplot-with-ggstatsplot.html">Tuo Wang</a>&rsquo;s work for the tidyTuesday project. (Code translated from R available <a href="https://www.python-graph-gallery.com/web-ggbetweenstats-with-matplotlib">here</a>)</p>
<p><img src="/matplotlib/python-graph-gallery.com/boxplot.png" alt="python violin and boxplot example"></p>
<h1 id="contributing">Contributing<a class="headerlink" href="#contributing" title="Link to this heading">#</a></h1>
<p>The python graph gallery is an ever growing project. It is open-source, with all its related code hosted on <a href="https://github.com/holtzy/The-Python-Graph-Gallery">github</a>.</p>
<p>Contributions are very welcome to the gallery. Each blogpost is just a jupyter notebook so suggestion should be very easy to do through issues or pull requests!</p>
<h1 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Link to this heading">#</a></h1>
<p>The <a href="https://www.python-graph-gallery.com">python graph gallery</a> is a project developed by <a href="https://www.yan-holtz.com">Yan Holtz</a> in his free time. It can help you improve your technical skills when it comes to visualizing data with python.</p>
<p>The gallery belongs to an ecosystem of educative websites. <a href="https://www.data-to-viz.com">Data to viz</a> describes best practices in data visualization, the <a href="https://www.r-graph-gallery.com">R</a>, <a href="https://www.python-graph-gallery.com">python</a> and <a href="https://www.d3-graph-gallery.com">d3.js</a> graph galleries provide technical help to build charts with the 3 most common tools.</p>
<p>For any question regarding the project, please say hi on twitter at <a href="https://twitter.com/R_Graph_Gallery">@R_Graph_Gallery</a>!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="graphs" label="graphs" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC'21: Pre-Quarter Progress]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_prequarter/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_midterm/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC&#39;21: Mid-Term Progress" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_introduction/?utm_source=atom_feed" rel="related" type="text/html" title="Aitik Gupta joins as a Student Developer under GSoC&#39;21" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2020_final_work_product/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC 2020 Work Product - Baseline Images Problem" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_5/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 3 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_4/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 2" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_2021_prequarter/</id>
            
            
            <published>2021-07-19T07:32:05+05:30</published>
            <updated>2021-07-19T07:32:05+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Pre-Quarter Progress with Google Summer of Code 2021 project under NumFOCUS: Aitik Gupta</blockquote><p><strong>“<ins>Well? Did you get it working?!</ins>”</strong></p>
<p>Before I answer that question, if you&rsquo;re missing the context, check out my <a href="../gsoc_2021_midterm/">previous blog</a>&rsquo;s last few lines.. promise it won&rsquo;t take you more than 30 seconds to get the whole problem!</p>
<p>With this short writeup, I intend to talk about <em>what</em> we did and <em>why</em> we did, what we did. XD</p>
<h2 id="ostrich-algorithm">Ostrich Algorithm<a class="headerlink" href="#ostrich-algorithm" title="Link to this heading">#</a></h2>
<p>Ring any bells? Remember OS (Operating Systems)? It&rsquo;s one of the core CS subjects which I bunked then and regret now. (╥﹏╥)</p>
<p>The <a href="https://en.wikipedia.org/wiki/Ostrich_algorithm">wikipedia page</a> has a 2-liner explanation if you have no idea what&rsquo;s an Ostrich Algorithm.. but I know most of y&rsquo;all won&rsquo;t bother clicking it XD, so here goes:</p>
<blockquote>
<p>Ostrich algorithm is a strategy of ignoring potential problems by &ldquo;sticking one&rsquo;s head in the sand and pretending there is no problem&rdquo;</p>
</blockquote>
<p>An important thing to note: it is used when it is more <strong>cost-effective</strong> to <em>allow the problem to occur than to attempt its prevention</em>.</p>
<p>As you might&rsquo;ve guessed by now, we ultimately ended up with the <em>not-so-clean</em> API (more on this later).</p>
<h2 id="what-was-the-problem">What was the problem?<a class="headerlink" href="#what-was-the-problem" title="Link to this heading">#</a></h2>
<p>The highest level overview of the problem was:</p>

<div class="highlight">
  <pre>❌ fontTools -&gt; buffer -&gt; ttconv_with_buffer
✅ fontTools -&gt; buffer -&gt; tempfile -&gt; ttconv_with_file</pre>
</div>

<p>The first approach created corrupted outputs, however the second approach worked fine. A point to note here would be that <em>Method 1</em> is better in terms of separation of <em>reading</em> the file from <em>parsing</em> the data.</p>
<ol>
<li><a href="https://github.com/fonttools/fonttools">fontTools</a> handles the Type42 subsetting for us, whereas <a href="https://github.com/matplotlib/matplotlib/tree/master/extern/ttconv">ttconv</a> handles the embedding.</li>
<li><code>ttconv_with_buffer</code> is a modification to the original <code>ttconv_with_file</code>; that allows it to input a file buffer instead of a file-path</li>
</ol>
<p>You might be tempted to say:</p>
<blockquote>
<p>&ldquo;Well, <code>ttconv_with_buffer</code> must be wrongly modified, duh.&rdquo;</p>
</blockquote>
<p>Logically, yes. <code>ttconv</code> was designed to work with a file-path and not a file-object (buffer), and modifying a codebase <strong>written in 1998</strong> turned out to be a larger pain than we anticipated.</p>
<h4 id="it-came-to-a-point-where-one-of-my-mentors-decided-to-implement-everything-in-python">It came to a point where one of my mentors decided to implement everything in Python!<a class="headerlink" href="#it-came-to-a-point-where-one-of-my-mentors-decided-to-implement-everything-in-python" title="Link to this heading">#</a></h4>
<p>He even did, but <ins>the efforts</ins> to get it to production / or to fix <code>ttconv</code> embedding were ⋙ to just get on with the second method. That damn ostrich really helped us get out of that debugging hell. 🙃</p>
<h2 id="font-fallback---initial-steps">Font Fallback - initial steps<a class="headerlink" href="#font-fallback---initial-steps" title="Link to this heading">#</a></h2>
<p>Finally, we&rsquo;re onto the second subgoal for the summer: <a href="https://www.w3schools.com/css/css_font_fallbacks.asp">Font Fallback</a>!</p>
<p>To give an idea about how things work right now:</p>
<ol>
<li>User asks Matplotlib to use certain font families, specified by:</li>
</ol>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">matplotlib</span><span class="o">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s2">&#34;font-family&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;list&#34;</span><span class="p">,</span> <span class="s2">&#34;of&#34;</span><span class="p">,</span> <span class="s2">&#34;font&#34;</span><span class="p">,</span> <span class="s2">&#34;families&#34;</span><span class="p">]</span></span></span></code></pre>
</div>
<ol start="2">
<li>This list is used to search for available fonts on a user&rsquo;s system.</li>
<li>However, in current (and previous) versions of Matplotlib:
<blockquote>
<p><ins>As soon as a font is found by iterating the font-family, <strong>all text</strong> is rendered by that <em>and only that</em> font.</ins></p>
</blockquote>
</li>
</ol>
<p>You can immediately see the problems with this approach; using the same font for every character will not render any glyph which isn&rsquo;t present in that font, and will instead spit out a square rectangle called &ldquo;tofu&rdquo; (read the first line <a href="https://www.google.com/get/noto/">here</a>).</p>
<p>And that is exactly the first milestone! That is, parsing the <em><ins>entire list</ins></em> of font families to get an intermediate representation of a multi-font interface.</p>
<h2 id="dont-break-a-lot-at-stake">Don&rsquo;t break, a lot at stake!<a class="headerlink" href="#dont-break-a-lot-at-stake" title="Link to this heading">#</a></h2>
<p>Imagine if you had the superpower to change Python standard library&rsquo;s internal functions, <em>without</em> consulting anybody. Let&rsquo;s say you wanted to write a solution by hooking in and changing, let&rsquo;s say <code>str(&quot;dumb&quot;)</code> implementation by returning:</p>

<div class="highlight">
  <pre>&gt;&gt;&gt; str(&#34;dumb&#34;)
[&#34;d&#34;, &#34;u&#34;, &#34;m&#34;, &#34;b&#34;]</pre>
</div>

<p>Pretty &ldquo;<ins>dumb</ins>&rdquo;, right? xD</p>
<p>For your usecase it might work fine, but it would also mean breaking the <em>entire</em> Python userbase&rsquo; workflow, not to mention the 1000000+ libraries that depend on the original functionality.</p>
<p>On a similar note, Matplotlib has a public API known as <code>findfont(prop: str)</code>, which when given a string (or <a href="https://matplotlib.org/stable/api/font_manager_api.html#matplotlib.font_manager.FontProperties">FontProperties</a>) finds you a font that best matches the given properties in your system.</p>
<p>It is used <ins>throughout the library</ins>, as well as at multiple other places, including downstream libraries. Being naive as I was, I changed this function signature and submitted the <a href="https://github.com/matplotlib/matplotlib/pull/20496">PR</a>. 🥲</p>
<p>Had an insightful discussion about this with my mentors, and soon enough raised the <a href="https://github.com/matplotlib/matplotlib/pull/20549">other PR</a>, which didn&rsquo;t touch the <code>findfont</code> API at all.</p>
<hr>
<p>One last thing to note: Even if we do complete the first milestone, we wouldn&rsquo;t be done yet, since this is just parsing the entire list to get multiple fonts..</p>
<p>We still need to migrate the library&rsquo;s internal implementation from <strong>font-first</strong> to <strong>text-first</strong>!</p>
<p>But that&rsquo;s for later, for now:
<img src="https://user-images.githubusercontent.com/43996118/126441988-5a2067fd-055e-44e5-86e9-4dddf47abc9d.png" alt="Bernie Sanders with text that read ‘I am once again thanking you for reading.’"></p>
<h4 id="note-this-blog-post-is-also-available-at-my-personal-website">NOTE: This blog post is also available at my <a href="https://aitikgupta.github.io/gsoc-pre-quarter/">personal website</a>.<a class="headerlink" href="#note-this-blog-post-is-also-available-at-my-personal-website" title="Link to this heading">#</a></h4>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC'21: Mid-Term Progress]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_midterm/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_introduction/?utm_source=atom_feed" rel="related" type="text/html" title="Aitik Gupta joins as a Student Developer under GSoC&#39;21" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2020_final_work_product/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC 2020 Work Product - Baseline Images Problem" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_5/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 3 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_4/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_3/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 1" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_2021_midterm/</id>
            
            
            <published>2021-07-02T08:32:05+05:30</published>
            <updated>2021-07-02T08:32:05+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Mid-Term Progress with Google Summer of Code 2021 project under NumFOCUS: Aitik Gupta</blockquote><p><strong>&quot;<ins>Aitik, how is your GSoC going?</ins>&quot;</strong></p>
<p>Well, it&rsquo;s been a while since I last wrote. But I wasn&rsquo;t spending time watching <em>Loki</em> either! (that&rsquo;s a lie.)</p>
<p>During this period the project took on some interesting (and stressful) curves, which I intend to talk about in this small writeup.</p>
<h2 id="new-mentor">New Mentor!<a class="headerlink" href="#new-mentor" title="Link to this heading">#</a></h2>
<p>The first week of coding period, and I met one of my new mentors, <a href="https://github.com/jkseppan">Jouni</a>. Without him, along with <a href="https://github.com/tacaswell">Tom</a> and <a href="https://github.com/anntzer">Antony</a>, the project wouldn&rsquo;t have moved <em>an inch</em>.</p>
<p>It was initially Jouni&rsquo;s <a href="https://github.com/matplotlib/matplotlib/pull/18143">PR</a> which was my starting point of the first milestone in my proposal, <ins>Font Subsetting</ins>.</p>
<h2 id="what-is-font-subsetting-anyway">What is Font Subsetting anyway?<a class="headerlink" href="#what-is-font-subsetting-anyway" title="Link to this heading">#</a></h2>
<p>As was proposed by Tom, a good way to understand something is to document your journey along the way! (well, that&rsquo;s what GSoC wants us to follow anyway right?)</p>
<p>Taking an excerpt from one of the paragraphs I wrote <a href="https://github.com/matplotlib/matplotlib/blob/a94f52121cea4194a5d6f6fc94eafdfb03394628/doc/users/fonts.rst#subsetting">here</a>:</p>
<blockquote>
<p>Font Subsetting can be used before generating documents, to embed only the <em>required</em> glyphs within the documents. Fonts can be considered as a collection of these glyphs, so ultimately the goal of subsetting is to find out which glyphs are required for a certain array of characters, and embed only those within the output.</p>
</blockquote>
<p>Now this may seem straightforward, right?</p>
<h4 id="wrong">Wrong.<a class="headerlink" href="#wrong" title="Link to this heading">#</a></h4>
<p>The glyph programs can call their own subprograms, for example, characters like <code>ä</code> could be composed by calling subprograms for <code>a</code> and <code>¨</code>; or <code>→</code> could be composed by a program that changes the display matrix and calls the subprogram for <code>←</code>.</p>
<p>Since the subsetter has to find out <em>all such subprograms</em> being called by <em>every glyph</em> included in the subset, this is a generally difficult problem!</p>
<p>Something which one of my mentors said which <em>really</em> stuck with me:</p>
<blockquote>
<p>Matplotlib isn&rsquo;t a font library, and shouldn&rsquo;t try to be one.</p>
</blockquote>
<p>It&rsquo;s really easy to fall into the trap of trying to do <em>everything</em> within your own project, which ends up rather <em>hurting</em> itself.</p>
<p>Since this holds true even for Matplotlib, it uses external dependencies like <a href="https://www.freetype.org/">FreeType</a>, <a href="https://github.com/sandflow/ttconv">ttconv</a>, and newly proposed <a href="https://github.com/fonttools/fonttools">fontTools</a> to handle font subsetting, embedding, rendering, and related stuff.</p>
<p>PS: If that font stuff didn&rsquo;t make sense, I would recommend going through a friendly tutorial I wrote, which is all about <a href="https://matplotlib.org/stable/users/fonts.html">Matplotlib and Fonts</a>!</p>
<h2 id="unexpected-complications">Unexpected Complications<a class="headerlink" href="#unexpected-complications" title="Link to this heading">#</a></h2>
<p>Matplotlib uses an external dependency <code>ttconv</code> which was initially forked into Matplotlib&rsquo;s repository <strong>in 2003</strong>!</p>
<blockquote>
<p>ttconv was a standalone commandline utility for converting TrueType fonts to subsetted Type 3 fonts (among other features) written in 1995, which Matplotlib forked in order to make it work as a library.</p>
</blockquote>
<p>Over the time, there were a lot of issues with it which were either hard to fix, or didn&rsquo;t attract a lot of attention. (See the above paragraph for a valid reason)</p>
<p>One major utility which is still used is <code>convert_ttf_to_ps</code>, which takes a <em>font path</em> as input and converts it into a Type 3 or Type 42 PostScript font, which can be embedded within PS/EPS output documents. The guide I wrote (<a href="https://matplotlib.org/stable/users/fonts.html">link</a>) contains decent descriptions, the differences between these type of fonts, etc.</p>
<h4 id="so-we-need-to-convert-that-font-path-input-to-a-font-buffer-input">So we need to convert that <em>font path</em> input to a <em>font buffer</em> input.<a class="headerlink" href="#so-we-need-to-convert-that-font-path-input-to-a-font-buffer-input" title="Link to this heading">#</a></h4>
<p>Why do we need to? Type 42 subsetting isn&rsquo;t really supported by ttconv, so we use a new dependency called fontTools, whose &lsquo;full-time job&rsquo; is to subset Type 42 fonts for us (among other things).</p>
<blockquote>
<p>It provides us with a font buffer, however ttconv expects a font path to embed that font</p>
</blockquote>
<p>Easily enough, this can be done by Python&rsquo;s <code>tempfile.NamedTemporaryFile</code>:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">with</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">NamedTemporaryFile</span><span class="p">(</span><span class="n">suffix</span><span class="o">=</span><span class="s2">&#34;.ttf&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">tmp</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># fontdata is the subsetted buffer</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># returned from fontTools</span>
</span></span><span class="line"><span class="cl">    <span class="n">tmp</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">fontdata</span><span class="o">.</span><span class="n">getvalue</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># TODO: allow convert_ttf_to_ps</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># to input file objects (BytesIO)</span>
</span></span><span class="line"><span class="cl">    <span class="n">convert_ttf_to_ps</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">os</span><span class="o">.</span><span class="n">fsencode</span><span class="p">(</span><span class="n">tmp</span><span class="o">.</span><span class="n">name</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">fh</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">fonttype</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">glyph_ids</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span></span></span></code></pre>
</div>
<p><strong><em>But this is far from a clean API; in terms of separation of *reading* the file from *parsing* the data.</em></strong></p>
<p>What we <em>ideally</em> want is to pass the buffer down to <code>convert_ttf_to_ps</code>, and modify the embedding code of <code>ttconv</code> (written in C++). And <em>here</em> we come across a lot of unexplored codebase, <em>which wasn&rsquo;t touched a lot ever since it was forked</em>.</p>
<p>Funnily enough, just yesterday, after spending a lot of quality time, me and my mentors figured out that the <strong>whole logging system of ttconv was broken</strong>, all because of a single debugging function. 🥲</p>
<hr>
<p>This is still an ongoing problem that we need to tackle over the coming weeks, hopefully by the next time I write one of these blogs, it gets resolved!</p>
<p>Again, thanks a ton for spending time reading these blogs. :D</p>
<h4 id="note-this-blog-post-is-also-available-at-my-personal-website">NOTE: This blog post is also available at my <a href="https://aitikgupta.github.io/gsoc-mid/">personal website</a>.<a class="headerlink" href="#note-this-blog-post-is-also-available-at-my-personal-website" title="Link to this heading">#</a></h4>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Aitik Gupta joins as a Student Developer under GSoC'21]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_2021_introduction/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2020_final_work_product/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC 2020 Work Product - Baseline Images Problem" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_5/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 3 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_4/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_3/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_2/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 2" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_2021_introduction/</id>
            
            
            <published>2021-05-19T20:03:57+05:30</published>
            <updated>2021-05-19T20:03:57+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Introduction about Aitik Gupta, Google Summer of Code 2021 Intern under the parent organisation: NumFOCUS</blockquote><p><strong><ins>The day of result, was a very, very long day.</ins></strong></p>
<p>With this small writeup, I intend to talk about everything before <em>that day</em>, my experiences, my journey, and the role of Matplotlib throughout!</p>
<h2 id="about-me">About Me<a class="headerlink" href="#about-me" title="Link to this heading">#</a></h2>
<p>I am a third-year undergraduate student currently pursuing a Dual Degree (B.Tech + M.Tech) in Information Technology at Indian Institute of Information Technology, Gwalior.</p>
<p>During my sophomore year, my interests started expanding in the domain of Machine Learning, where I learnt about various amazing open-source libraries like <em>NumPy</em>, <em>SciPy</em>, <em>pandas</em>, and <em>Matplotlib</em>! Gradually, in my third year, I explored the field of Computer Vision during my internship at a startup, where a big chunk of my work was to integrate their native C++ codebase to Android via JNI calls.</p>
<p>To actuate my learnings from the internship, I worked upon my own research along with a <a href="https://linkedin.com/in/aaditagarwal">friend from my university</a>. The paper was accepted in CoDS-COMAD’21 and is published at ACM Digital Library. (<a href="https://dl.acm.org/doi/abs/10.1145/3430984.3430986">Link</a>, if anyone&rsquo;s interested)</p>
<p>During this period, I also picked up the knack for open-source and started glaring at various issues (and pull requests) in libraries, including OpenCV [<a href="https://github.com/opencv/opencv/issues?q=author%3Aaitikgupta&#43;">contributions</a>] and NumPy [<a href="https://github.com/numpy/numpy/issues?q=author%3Aaitikgupta&#43;">contributions</a>].</p>
<p>I quickly got involved in Matplotlib’s community; it was very welcoming and beginner-friendly.</p>
<p><strong>Fun fact: Its dev call was the very first I attended with people from all around the world!</strong></p>
<h2 id="first-contributions">First Contributions<a class="headerlink" href="#first-contributions" title="Link to this heading">#</a></h2>
<p>We all mess up, my <a href="https://github.com/opencv/opencv/pull/18440">very first PR</a> to an organisation like OpenCV went horrible, till date, it looks like this:
<img src="https://user-images.githubusercontent.com/43996118/118848259-35d6e300-b8ec-11eb-8cdc-387e9f5a37a3.png" alt="OpenCV_PR"></p>
<p>In all honesty, I added a single commit with only a few lines of diff.</p>
<blockquote>
<p>However, I pulled all the changes from upstream <code>master</code> to my working branch, whereas the PR was to be made on <code>3.4</code> branch.</p>
</blockquote>
<p>I&rsquo;m sure I could&rsquo;ve done tons of things to solve it, but at that time I couldn&rsquo;t do anything - imagine the anxiety!</p>
<p>At this point when I look back at those fumbled PRs, I feel like they were important for my learning process.</p>
<p><strong>Fun Fact: Because of one of these initial contributions, I got a shiny little badge [<a href="https://github.com/readme/nasa-ingenuity-helicopter">Mars 2020 Helicopter Contributor</a>] on GitHub!</strong></p>
<img src="https://github.githubassets.com/images/modules/profile/badge--mars-64.png" style="width: 25%">
<h2 id="getting-started-with-matplotlib">Getting started with Matplotlib<a class="headerlink" href="#getting-started-with-matplotlib" title="Link to this heading">#</a></h2>
<p>It was around initial weeks of November last year, I was scanning through <code>Good First Issue</code> and <code>New Feature</code> labels, I realised a pattern - most <ins>Mathtext</ins> related issues were unattended.</p>
<p>To make it simple, Mathtext is a part of Matplotlib which parses mathematical expressions and provides TeX-like outputs, for example:
<span><img src="https://matplotlib.org/stable/_images/mathmpl/math-050e387807.png" style="width: 25%"></span></p>
<p>I scanned the related source code to try to figure out how to solve those Mathtext issues. Eventually, with the help of maintainers reviewing the PRs and <ins>a lot of verbose discussions</ins> on GitHub issues/pull requests and on the <a href="https://gitter.im/matplotlib/matplotlib">Gitter</a> channel, I was able to get my initial PRs merged!</p>
<h2 id="learning-throughout-the-process">Learning throughout the process<a class="headerlink" href="#learning-throughout-the-process" title="Link to this heading">#</a></h2>
<p>Most of us use libraries without understanding the underlining structure of them, which sometimes can cause downstream bugs!</p>
<p>While I was studying Matplotlib&rsquo;s architecture, I figured that I could use the same ideology for one of my <a href="https://aitikgupta.github.io/swi-ml/">own projects</a>!</p>
<p>Matplotlib uses a global dictionary-like object named as <code>rcParams</code>, I used a smaller interface, similar to rcParams, in <a href="https://pypi.org/project/swi-ml/">swi-ml</a> - a small Python library I wrote, implementing a subset of ML algorithms, with a <ins>switchable backend</ins>.</p>
<h2 id="where-does-gsoc-fit">Where does GSoC fit?<a class="headerlink" href="#where-does-gsoc-fit" title="Link to this heading">#</a></h2>
<p>It was around January, I had a conversation with one of the maintainers (hey <a href="https://github.com/anntzer">Antony</a>!) about the long-list of issues with the current ways of handling texts/fonts in the library.</p>
<p>After compiling them into an order, after few tweaks from maintainers, <a href="https://github.com/matplotlib/matplotlib/wiki/GSOC-2021-ideas">GSoC Idea-List</a> for Matplotlib was born. And so did my journey of building a strong proposal!</p>
<h2 id="about-the-project">About the Project<a class="headerlink" href="#about-the-project" title="Link to this heading">#</a></h2>
<h4 id="proposal-link-google-docs-will-stay-alive-after-gsoc-gsoc-website-not-so-sure">Proposal Link: <a href="https://docs.google.com/document/d/11PrXKjMHhl0rcQB4p_W9JY_AbPCkYuoTT0t85937nB0/edit?usp=sharing">Google Docs</a> (will stay alive after GSoC), <a href="https://storage.googleapis.com/summerofcode-prod.appspot.com/gsoc/core_project/doc/6319153410998272_1617936740_GSoC_Proposal_-_Matplotlib.pdf?Expires=1621539234&amp;GoogleAccessId=summerofcode-prod%40appspot.gserviceaccount.com&amp;Signature=QU8uSdPnXpa%2FooDtzVnzclz809LHjh9eU7Y7iR%2FH1NM32CBgzBO4%2FFbMeDmMsoic91B%2BKrPZEljzGt%2Fx9jtQeCR9X4O53JJLPVjw9Bg%2Fzb2YKjGzDk0oFMRPXjg9ct%2BV58PD6f4De1ucqARLtHGjis5jhK1W08LNiHAo88NB6BaL8Q5hqcTBgunLytTNBJh5lW2kD8eR2WeENnW9HdIe53aCdyxJkYpkgILJRoNLCvp111AJGC3RLYba9VKeU6w2CdrumPfRP45FX6fJlrKnClvxyf5VHo3uIjA3fGNWIQKwGgcd1ocGuFN3YnDTS4xkX3uiNplwTM4aGLQNhtrMqA%3D%3D">GSoC Website</a> (not so sure)<a class="headerlink" href="#proposal-link-google-docs-will-stay-alive-after-gsoc-gsoc-website-not-so-sure" title="Link to this heading">#</a></h4>
<h3 id="revisiting-textfont-handling">Revisiting Text/Font Handling<a class="headerlink" href="#revisiting-textfont-handling" title="Link to this heading">#</a></h3>
<p>The aim of the project is divided into 3 subgoals:</p>
<ol>
<li>
<p><strong>Font-Fallback</strong>: A redesigned text-first font interface - essentially parsing all family before rendering a &ldquo;tofu&rdquo;.</p>
<p><em>(similar to specifying <ins>font-family in CSS</ins>!)</em></p>
</li>
<li>
<p><strong>Font Subsetting</strong>: Every exported PS/PDF would contain embedded glyphs subsetted from the whole font.</p>
<p><em>(imagine a plot with just a single letter &ldquo;a&rdquo;, would you like it if the PDF you exported from Matplotlib to <ins>embed the whole font</ins> file within it?)</em></p>
</li>
<li>
<p>Most mpl backends would use the <ins>unified TeX exporting</ins> mechanism</p>
</li>
</ol>
<p><strong>Mentors</strong> <a href="https://github.com/tacaswell">Thomas A Caswell</a>, <a href="https://github.com/anntzer">Antony Lee</a>, <a href="https://github.com/story645">Hannah</a>.</p>
<p>Thanks a lot for spending time reading the blog! I&rsquo;ll be back with my progress in subsequent posts.</p>
<h5 id="note-this-blog-post-is-also-available-at-my-personal-website">NOTE: This blog post is also available at my <a href="https://aitikgupta.github.io/gsoc-intro/">personal website</a>!<a class="headerlink" href="#note-this-blog-post-is-also-available-at-my-personal-website" title="Link to this heading">#</a></h5>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Stellar Chart, a Type of Chart to Be on Your Radar]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/stellar-chart-alternative-radar-chart/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/ipcc-sr15/?utm_source=atom_feed" rel="related" type="text/html" title="Figures in the IPCC Special Report on Global Warming of 1.5°C (SR15)" />
                <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="related" type="text/html" title="Visualizing Code-Switching with Step Charts" />
                <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="related" type="text/html" title="Elementary Cellular Automata" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-fractals/?utm_source=atom_feed" rel="related" type="text/html" title="Animate Your Own Fractals in Python with Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-polar-plot/?utm_source=atom_feed" rel="related" type="text/html" title="Animated polar plot with oceanographic data" />
            
                <id>https://blog.scientific-python.org/matplotlib/stellar-chart-alternative-radar-chart/</id>
            
            
            <published>2021-01-10T20:29:40+00:00</published>
            <updated>2021-01-10T20:29:40+00:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Learn how to create a simple stellar chart, an alternative to the radar chart.</blockquote><p>In May 2020, Alexandre Morin-Chassé published a blog post about the <strong>stellar chart</strong>. This type of chart is an (approximately) direct alternative to the <strong>radar chart</strong> (also known as web, spider, star, or cobweb chart) — you can read more about this chart <a href="https://medium.com/nightingale/the-stellar-chart-an-elegant-alternative-to-radar-charts-ae6a6931a28e">here</a>.</p>
<p><img src="/matplotlib/stellar-chart-alternative-radar-chart/radar_stellar_chart.png" alt="Comparison of a radar chart and a stellar chart"></p>
<p>In this tutorial, we will see how we can create a quick-and-dirty stellar chart. First of all, let&rsquo;s get the necessary modules/libraries, as well as prepare a dummy dataset (with just a single record).</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">chain</span><span class="p">,</span> <span class="n">zip_longest</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">math</span> <span class="kn">import</span> <span class="n">ceil</span><span class="p">,</span> <span class="n">pi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;V1&#34;</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;V2&#34;</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;V3&#34;</span><span class="p">,</span> <span class="mi">9</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;V4&#34;</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;V5&#34;</span><span class="p">,</span> <span class="mi">6</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;V6&#34;</span><span class="p">,</span> <span class="mi">14</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;V7&#34;</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="s2">&#34;V8&#34;</span><span class="p">,</span> <span class="mi">25</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span></span></span></code></pre>
</div>
<p>We will also need some helper functions, namely a function to round up to the nearest 10 (<code>round_up()</code>) and a function to join two sequences (<code>even_odd_merge()</code>). In the latter, the values of the first sequence (a list or a tuple, basically) will fill the even positions and the values of the second the odd ones.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">round_up</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">    &gt;&gt;&gt; round_up(25)
</span></span></span><span class="line"><span class="cl"><span class="s2">    30
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">ceil</span><span class="p">(</span><span class="n">value</span> <span class="o">/</span> <span class="mf">10.0</span><span class="p">))</span> <span class="o">*</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">even_odd_merge</span><span class="p">(</span><span class="n">even</span><span class="p">,</span> <span class="n">odd</span><span class="p">,</span> <span class="n">filter_none</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">    &gt;&gt;&gt; list(even_odd_merge([1,3], [2,4]))
</span></span></span><span class="line"><span class="cl"><span class="s2">    [1, 2, 3, 4]
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">filter_none</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="nb">filter</span><span class="p">(</span><span class="kc">None</span><span class="o">.</span><span class="fm">__ne__</span><span class="p">,</span> <span class="n">chain</span><span class="o">.</span><span class="n">from_iterable</span><span class="p">(</span><span class="n">zip_longest</span><span class="p">(</span><span class="n">even</span><span class="p">,</span> <span class="n">odd</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">chain</span><span class="o">.</span><span class="n">from_iterable</span><span class="p">(</span><span class="n">zip_longest</span><span class="p">(</span><span class="n">even</span><span class="p">,</span> <span class="n">odd</span><span class="p">))</span></span></span></code></pre>
</div>
<p>That said, to plot <code>data</code> on a stellar chart, we need to apply some transformations, as well as calculate some auxiliary values. So, let&rsquo;s start by creating a function (<code>prepare_angles()</code>) to calculate the angle of each axis on the chart (<code>N</code> corresponds to the number of variables to be plotted).</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">prepare_angles</span><span class="p">(</span><span class="n">N</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">angles</span> <span class="o">=</span> <span class="p">[</span><span class="n">n</span> <span class="o">/</span> <span class="n">N</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">pi</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">N</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Repeat the first angle to close the circle</span>
</span></span><span class="line"><span class="cl">    <span class="n">angles</span> <span class="o">+=</span> <span class="n">angles</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">angles</span></span></span></code></pre>
</div>
<p>Next, we need a function (<code>prepare_data()</code>) responsible for adjusting the original data (<code>data</code>) and separating it into several easy-to-use objects.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">prepare_data</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">labels</span> <span class="o">=</span> <span class="p">[</span><span class="n">d</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">data</span><span class="p">]</span>  <span class="c1"># Variable names</span>
</span></span><span class="line"><span class="cl">    <span class="n">values</span> <span class="o">=</span> <span class="p">[</span><span class="n">d</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">data</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Repeat the first value to close the circle</span>
</span></span><span class="line"><span class="cl">    <span class="n">values</span> <span class="o">+=</span> <span class="n">values</span><span class="p">[:</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">N</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">labels</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">angles</span> <span class="o">=</span> <span class="n">prepare_angles</span><span class="p">(</span><span class="n">N</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">labels</span><span class="p">,</span> <span class="n">values</span><span class="p">,</span> <span class="n">angles</span><span class="p">,</span> <span class="n">N</span></span></span></code></pre>
</div>
<p>Lastly, for this specific type of chart, we require a function (<code>prepare_stellar_aux_data()</code>) that, from the previously calculated angles, prepares two lists of auxiliary values: a list of <strong>intermediate angles</strong> for each pair of angles (<code>stellar_angles</code>) and a list of small <strong>constant values</strong> (<code>stellar_values</code>), which will act as the values of the variables to be plotted in order to achieve the <strong>star-like shape</strong> intended for the stellar chart.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">prepare_stellar_aux_data</span><span class="p">(</span><span class="n">angles</span><span class="p">,</span> <span class="n">ymax</span><span class="p">,</span> <span class="n">N</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">angle_midpoint</span> <span class="o">=</span> <span class="n">pi</span> <span class="o">/</span> <span class="n">N</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">stellar_angles</span> <span class="o">=</span> <span class="p">[</span><span class="n">angle</span> <span class="o">+</span> <span class="n">angle_midpoint</span> <span class="k">for</span> <span class="n">angle</span> <span class="ow">in</span> <span class="n">angles</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span>
</span></span><span class="line"><span class="cl">    <span class="n">stellar_values</span> <span class="o">=</span> <span class="p">[</span><span class="mf">0.05</span> <span class="o">*</span> <span class="n">ymax</span><span class="p">]</span> <span class="o">*</span> <span class="n">N</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">stellar_angles</span><span class="p">,</span> <span class="n">stellar_values</span></span></span></code></pre>
</div>
<p>At this point, we already have all the necessary <em>ingredients</em> for the stellar chart, so let&rsquo;s move on to the Matplotlib side of this tutorial. In terms of <strong>aesthetics</strong>, we can rely on a function (<code>draw_peripherals()</code>) designed for this specific purpose (feel free to customize it!).</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">draw_peripherals</span><span class="p">(</span><span class="n">ax</span><span class="p">,</span> <span class="n">labels</span><span class="p">,</span> <span class="n">angles</span><span class="p">,</span> <span class="n">ymax</span><span class="p">,</span> <span class="n">outer_color</span><span class="p">,</span> <span class="n">inner_color</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># X-axis</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xticks</span><span class="p">(</span><span class="n">angles</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xticklabels</span><span class="p">(</span><span class="n">labels</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="n">outer_color</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">8</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Y-axis</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">ymax</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_yticklabels</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">ymax</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="n">color</span><span class="o">=</span><span class="n">inner_color</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">7</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">ymax</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_rlabel_position</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Both axes</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_axisbelow</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Boundary line</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;polar&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="n">outer_color</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Grid lines</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">xaxis</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">True</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="n">inner_color</span><span class="p">,</span> <span class="n">linestyle</span><span class="o">=</span><span class="s2">&#34;-&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">yaxis</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">True</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="n">inner_color</span><span class="p">,</span> <span class="n">linestyle</span><span class="o">=</span><span class="s2">&#34;-&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>To <strong>plot the data</strong> and orchestrate (almost) all the steps necessary to have a stellar chart, we just need one last function: <code>draw_stellar()</code>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">draw_stellar</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">labels</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">values</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">angles</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">N</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">shape_color</span><span class="o">=</span><span class="s2">&#34;tab:blue&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">outer_color</span><span class="o">=</span><span class="s2">&#34;slategrey&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">inner_color</span><span class="o">=</span><span class="s2">&#34;lightgrey&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Limit the Y-axis according to the data to be plotted</span>
</span></span><span class="line"><span class="cl">    <span class="n">ymax</span> <span class="o">=</span> <span class="n">round_up</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">values</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Get the lists of angles and variable values</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># with the necessary auxiliary values injected</span>
</span></span><span class="line"><span class="cl">    <span class="n">stellar_angles</span><span class="p">,</span> <span class="n">stellar_values</span> <span class="o">=</span> <span class="n">prepare_stellar_aux_data</span><span class="p">(</span><span class="n">angles</span><span class="p">,</span> <span class="n">ymax</span><span class="p">,</span> <span class="n">N</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">all_angles</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">even_odd_merge</span><span class="p">(</span><span class="n">angles</span><span class="p">,</span> <span class="n">stellar_angles</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">all_values</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">even_odd_merge</span><span class="p">(</span><span class="n">values</span><span class="p">,</span> <span class="n">stellar_values</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Apply the desired style to the figure elements</span>
</span></span><span class="line"><span class="cl">    <span class="n">draw_peripherals</span><span class="p">(</span><span class="n">ax</span><span class="p">,</span> <span class="n">labels</span><span class="p">,</span> <span class="n">angles</span><span class="p">,</span> <span class="n">ymax</span><span class="p">,</span> <span class="n">outer_color</span><span class="p">,</span> <span class="n">inner_color</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Draw (and fill) the star-shaped outer line/area</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">all_angles</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">all_values</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">linewidth</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">linestyle</span><span class="o">=</span><span class="s2">&#34;solid&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">solid_joinstyle</span><span class="o">=</span><span class="s2">&#34;round&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="n">shape_color</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">fill</span><span class="p">(</span><span class="n">all_angles</span><span class="p">,</span> <span class="n">all_values</span><span class="p">,</span> <span class="n">shape_color</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Add a small hole in the center of the chart</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">marker</span><span class="o">=</span><span class="s2">&#34;o&#34;</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;white&#34;</span><span class="p">,</span> <span class="n">markersize</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Finally, let&rsquo;s get our chart on a <em>blank canvas</em> (figure).</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="mi">111</span><span class="p">,</span> <span class="n">polar</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>  <span class="c1"># Don&#39;t forget the projection!</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">draw_stellar</span><span class="p">(</span><span class="n">ax</span><span class="p">,</span> <span class="o">*</span><span class="n">prepare_data</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/stellar-chart-alternative-radar-chart/stellar_chart.png" alt="Example of a stellar chart"></p>
<p>It&rsquo;s done! Right now, you have an example of a stellar chart and the boilerplate code to add this type of chart to your <em>repertoire</em>. If you end up creating your own stellar charts, feel free to share them with the <em>world</em> (and <a href="https://twitter.com/joaompalmeiro">me</a>!). I hope this tutorial was useful and interesting for you!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Figures in the IPCC Special Report on Global Warming of 1.5°C (SR15)]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/ipcc-sr15/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="related" type="text/html" title="Creating the Warming Stripes in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="related" type="text/html" title="Visualizing Code-Switching with Step Charts" />
                <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="related" type="text/html" title="Elementary Cellular Automata" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-fractals/?utm_source=atom_feed" rel="related" type="text/html" title="Animate Your Own Fractals in Python with Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-polar-plot/?utm_source=atom_feed" rel="related" type="text/html" title="Animated polar plot with oceanographic data" />
            
                <id>https://blog.scientific-python.org/matplotlib/ipcc-sr15/</id>
            
            
            <published>2020-12-31T08:32:45+01:00</published>
            <updated>2020-12-31T08:32:45+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Many figures in the IPCC SR15 were generated using Matplotlib.
The data and open-source notebooks were published to increase the transparency and reproducibility of the analysis.</blockquote><h2 id="background">Background<a class="headerlink" href="#background" title="Link to this heading">#</a></h2>
<figure style="float: right; ">
  <a href="https://www.ipcc.ch/sr15">
  <img src="IPCC-SR15-cover.jpg" style="width: 180px; "/>
  <figcaption style="text-align: center; color: grey; font-size: small">
  Cover of the IPCC SR15</figcaption></a>
</figure>
<p>The IPCC&rsquo;s <em>Special Report on Global Warming of 1.5°C</em> (SR15), published in October 2018,
presented the latest research on anthropogenic climate change.
It was written in response to the 2015 UNFCCC&rsquo;s &ldquo;Paris Agreement&rdquo; of</p>
<blockquote>
<p>holding the increase in the global average temperature to well below 2 °C
above pre-industrial levels and to pursue efforts to limit the temperature increase to 1.5 °C [&hellip;]&quot;.</p>
</blockquote>
<p>cf. <a href="https://unfccc.int/process-and-meetings/the-paris-agreement/the-paris-agreement">Article 2.1.a of the Paris Agreement</a></p>
<p>As part of the SR15 assessment, an ensemble of quantitative, model-based scenarios
was compiled to underpin the scientific analysis.
Many of the headline statements widely reported by media
are based on this scenario ensemble, including the finding that</p>
<blockquote>
<p>global net anthropogenic CO2 emissions decline by ~45% from 2010 levels by 2030</p>
</blockquote>
<p>in all pathways limiting global warming to 1.5°C
(cf. <a href="https://www.ipcc.ch/sr15/chapter/spm/">statement C.1</a> in the <em>Summary For Policymakers</em>).</p>
<h2 id="open-source-notebooks-for-transparency-and-reproducibility-of-the-assessment">Open-source notebooks for transparency and reproducibility of the assessment<a class="headerlink" href="#open-source-notebooks-for-transparency-and-reproducibility-of-the-assessment" title="Link to this heading">#</a></h2>
<p>When preparing the SR15, the authors wanted to go beyond previous reports
not just regarding the scientific rigor and scope of the analysis,
but also establish new standards in terms of openness, transparency and reproducibility.</p>
<p>The scenario ensemble was made accessible via an interactive <em>IAMC 1.5°C Scenario Explorer</em>
(<a href="http://data.ene.iiasa.ac.at/iamc-1.5c-explorer/#/workspaces">link</a>) in line with the
<a href="https://www.go-fair.org/fair-principles/">FAIR principles for scientific data management and stewardship</a>.
The process for compiling, validating and analyzing the scenario ensemble
was described in an open-access manuscript published in <em>Nature Climate Change</em>
(doi: <a href="https://doi.org/10.1038/s41558-018-0317-4">10.1038/s41558-018-0317-4</a>).</p>
<p>In addition, the Jupyter notebooks generating many of the headline statements,
tables and figures (using Matplotlib) were released under an open-source license
to facilitate a better understanding of the analysis
and enable reuse for subsequent research.
The notebooks are available in <a href="https://data.ene.iiasa.ac.at/sr15_scenario_analysis">rendered format</a>
and on <a href="https://github.com/iiasa/ipcc_sr15_scenario_analysis">GitHub</a>.</p>
<figure style="width: 600px ">
  <img src="sr15-fig2.4.png" style="width: 600px; "/>
  <figcaption style="text-align: center; color: grey; font-size: small">
  Figure 2.4 of the IPCC SR15, showing the range of assumptions of socioeconomic drivers<br />
  across the IAMC 1.5°C Scenario Ensemble<br />
  Drawn with Matplotlib, source code available <a href="https://data.ene.iiasa.ac.at/sr15_scenario_analysis/assessment/sr15_2.3.1_range_of_assumptions.html">here</a>
  </figcaption>
</figure>
<figure style="width: 600px ">
  <img src="sr15-fig2.15.png" style="width: 600px; "/>
  <figcaption style="text-align: center; color: grey; font-size: small">
  Figure 2.15 of the IPCC SR15, showing the primary energy development in illustrative pathways<br />
  Drawn with Matplotlib, source code available <a href="https://data.ene.iiasa.ac.at/sr15_scenario_analysis/assessment/sr15_2.4.2.1_primary_energy_marker-scenarios.html">here</a>
  </figcaption>
</figure>
<h2 id="a-package-for-scenario-analysis--visualization">A package for scenario analysis &amp; visualization<a class="headerlink" href="#a-package-for-scenario-analysis--visualization" title="Link to this heading">#</a></h2>
<p>To facilitate reusability of the scripts and plotting utilities
developed for the SR15 analysis, we started the open-source Python package <strong>pyam</strong>
as a toolbox for working with scenarios from integrated-assessment and energy system models.</p>
<p>The package is a wrapper for <a href="https://pandas.pydata.org">pandas</a> and Matplotlib
geared for several data formats commonly used in energy modelling.
<a href="https://pyam-iamc.readthedocs.io">Read the docs!</a></p>
<p><a href="https://pyam-iamc.readthedocs.io"><img src="pyam-header.png"></a></p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="academia" label="academia" />
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoD: Developing Matplotlib Entry Paths]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsod-developing-matplotlib-entry-paths/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="related" type="text/html" title="Visualizing Code-Switching with Step Charts" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_2020_final_work_product/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC 2020 Work Product - Baseline Images Problem" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_5/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 3 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_4/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="related" type="text/html" title="Elementary Cellular Automata" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsod-developing-matplotlib-entry-paths/</id>
            
            
            <published>2020-12-08T08:16:42-08:00</published>
            <updated>2020-12-08T08:16:42-08:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>This is my first post contribution to Matplotlib.</blockquote><h1 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Link to this heading">#</a></h1>
<p>This year’s Google Season of Docs (GSoD) provided me the opportunity to work with the open source organization, Matplotlib. In early summer, I submitted my proposal of Developing Matplotlib Entry Paths with the goal of improving the documentation with an alternative approach to writing.</p>
<p>I had set out to identify with users more by providing real world contexts to examples and programming. My purpose was to lower the barrier of entry for others to begin using the Python library with an expository approach. I focused on aligning with users based on consistent derived purposes and a foundation of task-based empathy.</p>
<p>The project began during the community bonding phase with learning the fundamentals of building documentation and working with open source code. I later generated usability testing surveys to the community and consolidated findings. From these results, I developed two new documents for merging into the Matplotlib repository, a Getting Started introductory tutorial and a lean Style Guide for the documentation.</p>
<h1 id="project-report">Project Report<a class="headerlink" href="#project-report" title="Link to this heading">#</a></h1>
<p>Throughout this year’s Season of Docs with Matplotlib, I learned a great deal about working on open source projects, provided contributions of surveying communities and interviewing subject matter experts in documentation usability testing, and produced a comprehensive introductory guide for improving entry-level content with an initiative style guide section.</p>
<p>As a new user to Git and GitHub, I had a learning curve in getting started with building documentation locally on my machine. Working with cloning repositories and familiarizing myself with commits and pull requests took the bulk of the first few weeks on this project. However, with experiencing errors and troubleshooting broken branches, it was excellent to be able to lean on my mentors for resolving these issues. Platforms like Gitter, Zoom, and HackMD were key in keeping communication timely and concise. I was fortunate to be able to get in touch with the team to help me as soon as I had problems.</p>
<p>With programming, I was not a completely fresh face to Python and Matplotlib. However, installing the library from the source and breaking down functionality to core essentials helped me grow in my understanding of not only the fundamentals, but also the terminology. Tackling everything through my own experience of using Python and then also having suggestions and advice from the development team accelerated the ideas and implementations I aimed to work towards.</p>
<p>New formats and standards with reStructuredText files and Sphinx compatibility were unfamiliar avenues to me at first. In building documentation and reading through already written content, I adapted to making the most of the features available with the ideas I had for writing material suited for users new to Matplotlib. Making use of tables and code examples embedded allowed me to be more flexible in visual layout and navigation.</p>
<p>During the beginning stages of the project, I was able to incorporate usability testing for the current documentation. By reaching out to communities on Twitter, Reddit, and various Slack channels, I compiled and consolidated findings that helped shape the language and focus of new content to create. I summarized and shared the community’s responses in addition to separate informational interviews conducted with subject matter experts in my location. These data points helped in justifying and supporting decisions for the scope and direction of the language and content.</p>
<p>At the end of the project, I completed our agreed upon expectations for the documentation. The focused goal consisted of a Getting Started tutorial to introduce and give context to Matplotlib for new users. In addition, through the documentation as well as the meetings with the community, we acknowledged a missing element of a Style Guide. Though a comprehensive document for the entire library was out of the scope of the project, I put together, in conjunction with the featured task, a lean version that serves as a foundational resource for writing Matplotlib documentation.</p>
<p>The two sections are part of a current pull request to merge into Matplotlib’s repository. I have already worked through smaller changes to the content and am working with the community in moving forward with the process.</p>
<h1 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Link to this heading">#</a></h1>
<p>This Season of Docs proposal began as a vision of ideals I hoped to share and work towards with an organization and has become a technical writing experience full of growth and camaraderie. I am pleased with the progress I had made and cannot thank the team enough for the leadership and mentorship they provided. It is fulfilling and rewarding to both appreciate and be appreciated within a team.</p>
<p>In addition, the opportunity put together by the team at Google to foster collaboration among skilled contributors cannot be understated. Highlighting the accomplishments of these new teams raises the bar for the open source community.</p>
<h1 id="details">Details<a class="headerlink" href="#details" title="Link to this heading">#</a></h1>
<h2 id="acknowledgements">Acknowledgements<a class="headerlink" href="#acknowledgements" title="Link to this heading">#</a></h2>
<p>Special thanks to Emily Hsu, Joe McEwen, and Smriti Singh for their time and responses, fellow Matplotlib Season of Docs writer Bruno Beltran for his insight and guidance, and the Matplotlib development team mentors Tim, Tom, and Hannah for their patience, support, and approachability for helping a new technical writer like me with my own Getting Started.</p>
<h2 id="external-links">External Links<a class="headerlink" href="#external-links" title="Link to this heading">#</a></h2>
<ul>
<li><a href="https://github.com/matplotlib/matplotlib/pull/18873">Getting Started GSoD Pull Request</a></li>
<li><a href="https://docs.google.com/forms/d/e/1FAIpQLSfPX13wXNOV5LM4OoHUYT3xtSZzVQ6I3ZA4cvz5P6DKuph4aw/viewform?usp=sf_link">Matplotlib User Survey</a></li>
<li><a href="https://docs.google.com/spreadsheets/d/1z_bAu7hG-IgtFkM5uPezkUHQvi6gsWKxoDnh0Hz1K5U/edit?usp=sharing">User Survey Responses</a></li>
<li><a href="https://docs.google.com/spreadsheets/d/15EzVNmWVn2SjCUBc-Kt5Y0_entLgvWRMRYy8syt_-Xg/edit?usp=sharing">User Survey Open Questions</a></li>
<li><a href="https://hackmd.io/cSNb2JhrSo26zJGag3bvLg">HackMD GSoD Meeting Agenda</a></li>
</ul>
<h2 id="about-me">About Me<a class="headerlink" href="#about-me" title="Link to this heading">#</a></h2>
<p>My name is <a href="https://www.linkedin.com/in/jeromefuertevillegas/">Jerome Villegas</a> and I&rsquo;m a technical writer based in Seattle. I&rsquo;ve been in education and education-adjacent fields for several years before transitioning to the industry of technical communication. My career has taken me to Taiwan to teach English and work in publishing, then to New York City to work in higher education, and back to Seattle where I worked at a private school.</p>
<p>Since leaving my job, I&rsquo;ve taken to supporting my family while studying technical writing at the University of Washington and supplementing the knowledge with learning programming on the side. Along with a former classmate, the two of us have worked with the UX writing community in the Pacific Northwest. We host interview sessions, moderate sessions at conferences, and generate content analyzing trends and patterns in UX/tech writing.</p>
<p>In telling people what I&rsquo;ve got going on in my life, you can find work I&rsquo;ve done at my <a href="https://jeromefvillegas.wordpress.com">personal site</a> and see what we&rsquo;re up to at <a href="https://teamshiftj.wordpress.com">shift J</a>. Thanks for reading!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="gsod" label="GSoD" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Visualizing Code-Switching with Step Charts]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/codeswitching-visualization/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="related" type="text/html" title="Elementary Cellular Automata" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-fractals/?utm_source=atom_feed" rel="related" type="text/html" title="Animate Your Own Fractals in Python with Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-polar-plot/?utm_source=atom_feed" rel="related" type="text/html" title="Animated polar plot with oceanographic data" />
                <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="related" type="text/html" title="Emoji Mosaic Art" />
            
                <id>https://blog.scientific-python.org/matplotlib/codeswitching-visualization/</id>
            
            
            <published>2020-09-26T19:41:21-07:00</published>
            <updated>2020-09-26T19:41:21-07:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Learn how to easily create step charts through examining the multilingualism of pop group WayV</blockquote><p><img src="/matplotlib/codeswitching-visualization/Image1.png" alt="Frequency of Code-Switching 200403 WayV Instagram Live, a step chart. The figure shows a plot of ‘cumulative number of times of code-switching’ against the ‘duration of Instagram Live (in seconds)’. There are four members in the livestream: Yangyang (represented with a dark red line), Hendery (represented with a pink line), Ten (represented with a light blue line), Kun (represented with a dark blue line)."></p>
<h1 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Link to this heading">#</a></h1>
<p>Code-switching is the practice of alternating between two or more languages in the context of a single conversation, either consciously or unconsciously. As someone who grew up bilingual and is currently learning other languages, I find code-switching a fascinating facet of communication from not only a purely linguistic perspective, but also a social one. In particular, I&rsquo;ve personally found that code-switching often helps build a sense of community and familiarity in a group and that the unique ways in which speakers code-switch with each other greatly contribute to shaping group dynamics.</p>
<p>This is something that&rsquo;s evident in seven-member pop boy group WayV. Aside from their discography, artistry, and group chemistry, WayV is well-known among fans and many non-fans alike for their multilingualism and code-switching, which many fans have affectionately coined as &ldquo;WayV language.&rdquo; Every member in the group is fluent in both Mandarin and Korean, and at least one member in the group is fluent in one or more of the following: English, Cantonese, Thai, Wenzhounese, and German. It&rsquo;s an impressive trait that&rsquo;s become a trademark of WayV as they&rsquo;ve quickly drawn a global audience since their debut in January 2019. Their multilingualism is reflected in their music as well. On top of their regular album releases in Mandarin, WayV has also released singles in Korean and English, with their latest single &ldquo;Bad Alive (English Ver.)&rdquo; being a mix of English, Korean, and Mandarin.</p>
<p>As an independent translator who translates WayV content into English, I&rsquo;ve become keenly aware of the true extent and rate of WayV&rsquo;s code-switching when communicating with each other. In a lot of their content, WayV frequently switches between three or more languages every couple of seconds, a phenomenon that can make translating quite challenging at times, but also extremely rewarding and fun. I wanted to be able to present this aspect of WayV in a way that would both highlight their linguistic skills and present this dimension of their group dynamic in a more concrete, quantitative, and visually intuitive manner, beyond just stating that &ldquo;they code-switch a lot.&rdquo; This prompted me to make step charts - perfect for displaying data that changes at irregular intervals but remains constant between the changes - in hopes of enriching the viewer&rsquo;s experience and helping make a potentially abstract concept more understandable and readily consumable. With a step chart, it becomes more apparent to the viewer the extent of how a group communicates, and cross-sections of the graph allow a rudimentary look into how multilinguals influence each other in code-switching.</p>
<h1 id="tutorial">Tutorial<a class="headerlink" href="#tutorial" title="Link to this heading">#</a></h1>
<p>This tutorial on creating step charts uses one of WayV&rsquo;s livestreams as an example. There were four members in this livestream and a total of eight languages/dialects spoken. I will go through the basic steps of creating a step chart that depicts the frequency of code-switching for just one member. A full code chunk that shows how to layer two or more step chart lines in one graph to depict code-switching for multiple members can be found near the end.</p>
<h2 id="dataset">Dataset<a class="headerlink" href="#dataset" title="Link to this heading">#</a></h2>
<p>First, we import the required libraries and load the data into a Pandas dataframe.</p>
<pre><code>import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
</code></pre>
<p>This dataset includes the timestamp of every switch (in seconds) and the language of switch for one speaker.</p>
<pre><code>df_h = pd.read_csv(&quot;WayVHendery.csv&quot;)
HENDERY = df_h.reset_index()
HENDERY.head()
</code></pre>
<table>
  <thead>
      <tr>
          <th>index</th>
          <th>time</th>
          <th>lang</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0</td>
          <td>2</td>
          <td>ENG</td>
      </tr>
      <tr>
          <td>1</td>
          <td>3</td>
          <td>KOR</td>
      </tr>
      <tr>
          <td>2</td>
          <td>10</td>
          <td>ENG</td>
      </tr>
      <tr>
          <td>3</td>
          <td>13</td>
          <td>MAND</td>
      </tr>
      <tr>
          <td>4</td>
          <td>15</td>
          <td>ENG</td>
      </tr>
  </tbody>
</table>
<h2 id="plotting">Plotting<a class="headerlink" href="#plotting" title="Link to this heading">#</a></h2>
<p>With the dataset loaded, we can now set up our graph in terms of determining the size of the figure, dpi, font size, and axes limits. We can also play around with the aesthetics, such as modifying the colors of our plot. These few simple steps easily transform the default all-white graph into a more visually appealing one.</p>
<h3 id="without-customization">Without Customization<a class="headerlink" href="#without-customization" title="Link to this heading">#</a></h3>
<pre><code>fig, ax = plt.subplots(figsize = (20,12))
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/fig1.png" alt="An all-white graph with the x and y axis defined on the range [0, 1]."></p>
<h3 id="with-customization">With Customization<a class="headerlink" href="#with-customization" title="Link to this heading">#</a></h3>
<pre><code>sns.set(rc={'axes.facecolor':'aliceblue', 'figure.facecolor':'c'})
fig, ax = plt.subplots(figsize = (20,12), dpi = 300)

plt.xlabel(&quot;Duration of Instagram Live (seconds)&quot;, fontsize = 18)
plt.ylabel(&quot;Cumulative Number of Times of Code-Switching&quot;, fontsize = 18)

plt.xlim(0, 570)
plt.ylim(0, 85)
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/fig2.png" alt="A styled, blank graph with the ‘cumulative number of times of code-switching’ values on the y-axis and the ‘duration of Instagram Live (in seconds)’ values on the x-axis"></p>
<!--     ax.step(HENDERY.time, HENDERY.index, label = "HENDERY") -->
<p>Following this, we can make our step chart line easily with matplotlib.pyplot.step, in which we plot the x and y values and determine the text of the legend, color of the step chart line, and width of the step chart line.</p>
<pre><code>ax.step(HENDERY.time, HENDERY.index, label = &quot;HENDERY&quot;, color = &quot;palevioletred&quot;, linewidth = 4)
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/fig3.png" alt="A graph with the ‘cumulative number of times of code-switching’ values on the y-axis and the ‘duration of Instagram Live (in seconds)’ values on the x-axis showing a step chart line (in pink) for Hendery."></p>
<h2 id="labeling">Labeling<a class="headerlink" href="#labeling" title="Link to this heading">#</a></h2>
<p>Of course, we want to know not only how many switches there were and when they occurred, but also to what language the member switched. For this, we can write a for loop that labels each switch with its respective language as recorded in our dataset.</p>
<pre><code>for x,y,z in zip(HENDERY[&quot;time&quot;], HENDERY[&quot;index&quot;], HENDERY[&quot;lang&quot;]):
    label = z
    ax.annotate(label, #text
                 (x,y), #label coordinate
                 textcoords = &quot;offset points&quot;, #how to position text
                 xytext = (15,-5), #distance from text to coordinate (x,y)
                 ha = &quot;center&quot;, #alignment
                 fontsize = 8.5) #font size of text
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/fig4.png" alt="Language labels for each step on the graph. Languages include English, Korean, Mandarin, and German. The graph has the ‘cumulative number of times of code-switching’ values on the y-axis and the ‘duration of Instagram Live (in seconds)’ values on the x-axis showing a step chart line (in pink) for Hendery."></p>
<h2 id="final-touches">Final Touches<a class="headerlink" href="#final-touches" title="Link to this heading">#</a></h2>
<p>Now add a title, save the graph, and there you have it!</p>
<pre><code>plt.title(&quot;WayV Livestream Code-Switching&quot;, fontsize = 35)

fig.savefig(&quot;wayv_codeswitching.png&quot;, bbox_inches = &quot;tight&quot;, facecolor = fig.get_facecolor())
</code></pre>
<p>Below is the complete code for layering step chart lines for multiple speakers in one graph. You can see how easy it is to take the code for visualizing the code-switching of one speaker and adapt it to visualizing that of multiple speakers. In addition, you can see that I&rsquo;ve intentionally left the title blank so I can incorporate external graphic adjustments after I created the chart in Matplotlib, such as the addition of my social media handle and the use of a specific font I wanted, which you can see in the final graph. With visualizations being all about communicating information, I believe using Matplotlib in conjunction with simple elements of graphic design can be another way to make whatever you&rsquo;re presenting that little bit more effective and personal, especially when you&rsquo;re doing so on social media platforms.</p>
<h2 id="complete-code-for-step-chart-of-multiple-speakers">Complete Code for Step Chart of Multiple Speakers<a class="headerlink" href="#complete-code-for-step-chart-of-multiple-speakers" title="Link to this heading">#</a></h2>
<!-- ![](fig5.png) -->
<pre><code># Initialize graph color and size
sns.set(rc={'axes.facecolor':'aliceblue', 'figure.facecolor':'c'})

fig, ax = plt.subplots(figsize = (20,12), dpi = 120)

# Set up axes and labels
plt.xlabel(&quot;Duration of Instagram Live (seconds)&quot;, fontsize = 18)
plt.ylabel(&quot;Cumulative Number of Times of Code-Switching&quot;, fontsize = 18)

plt.xlim(0, 570)
plt.ylim(0, 85)

# Layer step charts for each speaker
ax.step(YANGYANG.time, YANGYANG.index, label = &quot;YANGYANG&quot;, color = &quot;firebrick&quot;, linewidth = 4)
ax.step(HENDERY.time, HENDERY.index, label = &quot;HENDERY&quot;, color = &quot;palevioletred&quot;, linewidth = 4)
ax.step(TEN.time, TEN.index, label = &quot;TEN&quot;, color = &quot;mediumpurple&quot;, linewidth = 4)
ax.step(KUN.time, KUN.index, label = &quot;KUN&quot;, color = &quot;mediumblue&quot;, linewidth = 4)

# Add legend
ax.legend(fontsize = 17)

# Label each data point with the language switch
for i in (KUN, TEN, HENDERY, YANGYANG): #for each dataset
    for x,y,z in zip(i[&quot;time&quot;], i[&quot;index&quot;], i[&quot;lang&quot;]): #looping within the dataset
        label = z
        ax.annotate(label, #text
                     (x,y), #label coordinate
                     textcoords = &quot;offset points&quot;, #how to position text
                     xytext = (15,-5), #distance from text to coordinate (x,y)
                     ha = &quot;center&quot;, #alignment
                     fontsize = 8.5) #font size of text

# Add title (blank to leave room for external graphics)
plt.title(&quot;\n\n&quot;, fontsize = 35)

# Save figure
fig.savefig(&quot;wayv_codeswitching.png&quot;, bbox_inches = &quot;tight&quot;, facecolor = fig.get_facecolor())
</code></pre>
<p><img src="/matplotlib/codeswitching-visualization/Image1.png" alt="Frequency of Code-Switching 200403 WayV Instagram Live, a step chart. The figure shows a plot of ‘cumulative number of times of code-switching’ against the ‘duration of Instagram Live (in seconds)’. There are four members in the livestream: Yangyang (represented with a dark red line), Hendery (represented with a pink line), Ten (represented with a light blue line), Kun (represented with a dark blue line)."></p>
<p>Languages/dialects: Korean (KOR), English (ENG), Mandarin (MAND), German (GER), Cantonese (CANT), Hokkien (HOKK), Teochew (TEO), Thai (THAI)</p>
<p>186 total switches! That&rsquo;s approximately one code-switch in the group every 2.95 seconds.</p>
<p>And voilà! There you have it: a brief guide on how to make step charts. While I utilized step charts here to visualize code-switching, you can use them to visualize whatever data you would like. Please feel free to contact me <a href="https://twitter.com/WayVSubs2019">here</a> if you have any questions or comments. I hope you enjoyed this tutorial, and thank you so much for reading!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="graphs" label="graphs" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC 2020 Work Product - Baseline Images Problem]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_2020_final_work_product/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_5/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 3 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_4/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_3/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_2/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_1/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 1" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_2020_final_work_product/</id>
            
            
            <published>2020-08-16T09:47:51+05:30</published>
            <updated>2020-08-16T09:47:51+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Final Work Product Report for the Google Summer of Code 2020 for the Baseline Images Problem</blockquote><p>Google Summer of Code 2020 is completed. Hurray!! This post discusses about the progress so far in the three months of the coding period from 1 June to 24 August 2020 regarding the project <code>Baseline Images Problem</code> under <code>matplotlib</code> organisation under the umbrella of <code>NumFOCUS</code> organization.</p>
<h2 id="project-details">Project Details:<a class="headerlink" href="#project-details" title="Link to this heading">#</a></h2>
<p>This project helps with the difficulty in adding/modifying tests which require a baseline image. Baseline images are problematic because</p>
<ul>
<li>Baseline images cause the repo size to grow rather quickly.</li>
<li>Baseline images force matplotlib contributors to pin to a somewhat old version of FreeType because nearly every release of FreeType causes tiny rasterization changes that would entail regenerating all baseline images (and thus cause even more repo size growth).</li>
</ul>
<p>So, the idea is to not store the baseline images in the repository, instead to create them from the existing tests.</p>
<h2 id="creation-of-the-matplotlib_baseline_images-package">Creation of the matplotlib_baseline_images package<a class="headerlink" href="#creation-of-the-matplotlib_baseline_images-package" title="Link to this heading">#</a></h2>
<p>We had created the <code>matplotlib_baseline_images</code> package. This package is involved in the sub-wheels directory so that more packages can be added in the same directory, if needed in future. The <code>matplotlib_baseline_images</code> package contain baseline images for both <code>matplotlib</code> and <code>mpl_toolkits</code>.
The package can be installed by using <code>python3 -mpip install matplotlib_baseline_images</code>.</p>
<h2 id="creation-of-the-matplotlib-baseline-image-generation-flag">Creation of the matplotlib baseline image generation flag<a class="headerlink" href="#creation-of-the-matplotlib-baseline-image-generation-flag" title="Link to this heading">#</a></h2>
<p>We successfully created the <code>generate_missing</code> command line flag for baseline image generation for <code>matplotlib</code> and <code>mpl_toolkits</code> in the previous months. It was generating the <code>matplotlib</code> and the <code>mpl_toolkits</code> baseline images initially. Now, we have also modified the existing flow to generate any missing baseline images, which would be fetched from the <code>master</code> branch on doing <code>git pull</code> or <code>git checkout -b feature_branch</code>.</p>
<p>Now, the image generation on the time of fresh install of matplotlib and the generation of missing baseline images works with the <code>python3 -pytest lib/matplotlib matplotlib_baseline_image_generation</code> for the <code>lib/matplotlib</code> folder and <code>python3 -pytest lib/mpl_toolkits matplotlib_baseline_image_generation</code> for the <code>lib/mpl_toolkits</code> folder.</p>
<h2 id="documentation">Documentation<a class="headerlink" href="#documentation" title="Link to this heading">#</a></h2>
<p>We have written documentation explaining the following scenarios:</p>
<ol>
<li>How to generate the baseline images on a fresh install of matplotlib?</li>
<li>How to generate the missing baseline images on fetching changes from master?</li>
<li>How to install the <code>matplotlib_baseline_images_package</code> to be used for testing by the developer?</li>
<li>How to intentionally change an image?</li>
</ol>
<h2 id="links-to-the-work-done">Links to the work done<a class="headerlink" href="#links-to-the-work-done" title="Link to this heading">#</a></h2>
<ul>
<li><a href="https://github.com/matplotlib/matplotlib/issues/16447">Issue</a></li>
<li><a href="https://github.com/matplotlib/matplotlib/pull/17793">Pull Request</a></li>
<li><a href="/tags/gsoc/">Blog Posts</a></li>
</ul>
<h2 id="mentors">Mentors<a class="headerlink" href="#mentors" title="Link to this heading">#</a></h2>
<ul>
<li>Thomas A Caswell</li>
<li>Hannah</li>
<li>Antony Lee</li>
</ul>
<p>I am grateful to be part of such a great community. Project is really interesting and challenging :)</p>
<p>Thanks Thomas, Antony and Hannah for helping me to complete this project.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC Coding Phase 3 Blog 1]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_5/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_4/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_3/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_2/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_1/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/introductory-gsoc2020-post/?utm_source=atom_feed" rel="related" type="text/html" title="Sidharth Bansal joined as GSoC&#39;20 intern" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_5/</id>
            
            
            <published>2020-08-08T09:47:51+05:30</published>
            <updated>2020-08-08T09:47:51+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Progress Report for the first half of the Google Summer of Code 2020 Phase 3 for the Baseline Images Problem</blockquote><p>Google Summer of Code 2020&rsquo;s second evaluation is completed. I passed!!! Hurray! Now we are in the mid way of the last evaluation. This post discusses about the progress so far in the first two weeks of the third coding period from 26 July to 9 August 2020.</p>
<h2 id="completion-of-the-modification-logic-for-the-matplotlib_baseline_images-package">Completion of the modification logic for the matplotlib_baseline_images package<a class="headerlink" href="#completion-of-the-modification-logic-for-the-matplotlib_baseline_images-package" title="Link to this heading">#</a></h2>
<p>We successfully created the <code>matplotlib_baseline_image_generation</code> command line flag for baseline image generation for <code>matplotlib</code> and <code>mpl_toolkits</code> in the previous months. It was generating the matplotlib and the matplotlib toolkit baseline images successfully. Now, we modified the existing flow to generate any missing baseline images, which would be fetched from the <code>master</code> branch on doing <code>git pull</code> or <code>git checkout -b feature_branch</code>.</p>
<p>We initially thought of creating a command line flag <code>generate_baseline_images_for_test &quot;test_a,test_b&quot;</code>, but later on analysis of the approach, we came to the conclusion that the developer will not know about the test names to be given along with the flag. So, we tried to generate the missing images by <code>generate_missing</code> without the test names. This worked successfully.</p>
<h2 id="adopting-reusability-and-do-not-repeat-yourself-dry-principles">Adopting reusability and Do not Repeat Yourself (DRY) Principles<a class="headerlink" href="#adopting-reusability-and-do-not-repeat-yourself-dry-principles" title="Link to this heading">#</a></h2>
<p>Later, we refactored the <code>matplot_baseline_image_generation</code> and <code>generate_missing</code> command line flags to single command line flag <code>matplotlib_baseline_image_generation</code> as the logic was similar for both of them. Now, the image generation on the time of fresh install of matplotlib and the generation of missing baseline images works with the <code>python3 -pytest lib/matplotlib matplotlib_baseline_image_generation</code> for the <code>lib/matplotlib</code> folder and <code>python3 -pytest lib/mpl_toolkits matplotlib_baseline_image_generation</code> for the <code>lib/mpl_toolkits</code> folder.</p>
<h2 id="writing-the-documentation">Writing the documentation<a class="headerlink" href="#writing-the-documentation" title="Link to this heading">#</a></h2>
<p>We have written documentation explaining the following scenarios:</p>
<ol>
<li>How to generate the baseline images on a fresh install of matplotlib?</li>
<li>How to generate the missing baseline images on fetching changes from master?</li>
<li>How to install the <code>matplotlib_baseline_images_package</code> to be used for testing by the developer?</li>
<li>How to intentionally change an image?</li>
</ol>
<h2 id="refactoring-and-improving-the-code-quality-before-merging">Refactoring and improving the code quality before merging<a class="headerlink" href="#refactoring-and-improving-the-code-quality-before-merging" title="Link to this heading">#</a></h2>
<p>Right now, we are trying to refactor the code and maintain git clean history. The <a href="https://github.com/matplotlib/matplotlib/pull/17793">current PR</a> is under review. I am working on the suggested changes. We are trying to merge this :)</p>
<h2 id="daily-meet-ups">Daily Meet-ups<a class="headerlink" href="#daily-meet-ups" title="Link to this heading">#</a></h2>
<p>Monday to Thursday meeting initiated at <a href="https://everytimezone.com/">11:00pm IST</a> via Zoom. Meeting notes are present at HackMD.</p>
<p>I am grateful to be part of such a great community. Project is really interesting and challenging :) Thanks Thomas, Antony and Hannah for helping me so far.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC Coding Phase 2 Blog 2]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_4/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_3/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 2 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_2/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_1/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/introductory-gsoc2020-post/?utm_source=atom_feed" rel="related" type="text/html" title="Sidharth Bansal joined as GSoC&#39;20 intern" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-rsef/?utm_source=atom_feed" rel="related" type="text/html" title="Elliott Sales de Andrade hired as Matplotlib Software Research Engineering Fellow" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_4/</id>
            
            
            <published>2020-07-23T19:47:51+05:30</published>
            <updated>2020-07-23T19:47:51+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Progress Report for the second half of the Google Summer of Code 2020 Phase 2 for the Baseline Images Problem</blockquote><p>Google Summer of Code 2020&rsquo;s second evaluation is about to complete. Now we are about to start with the final coding phase. This post discusses about the progress so far in the last two weeks of the second coding period from 13 July to 26 July 2020.</p>
<h2 id="modular-approach-towards-removal-of-matplotlib-baseline-images">Modular approach towards removal of matplotlib baseline images<a class="headerlink" href="#modular-approach-towards-removal-of-matplotlib-baseline-images" title="Link to this heading">#</a></h2>
<p>We have divided the work in two parts as discussed in the <a href="../gsoc_coding_phase_blog_3/">previous blog</a>. The first part is the generation of the baseline images discussed below. The second part is the modification of the baseline images. The modification part will be implemented in the last phase of the Google Summer of Code 2020.</p>
<h2 id="generation-of-the-matplotlib-baseline-images">Generation of the matplotlib baseline images<a class="headerlink" href="#generation-of-the-matplotlib-baseline-images" title="Link to this heading">#</a></h2>
<p>Now, we have started removing the use of the <code>matplotlib_baseline_images</code> package. After the changes proposed in the <a href="https://github.com/matplotlib/matplotlib/pull/17557">previous PR</a>, the developer will have no baseline images on fresh install of matplotlib. So, the developer would need to generate matplotlib baseline images locally to get started with the testing part of the mpl.
The images can be generated by the image comparison tests with use of <code>matplotlib_baseline_image_generation</code> flag from the command line. Once these images are generated for the first time, then they can be used as the baseline images for the later times for comparison. This is the main principle adopted.</p>
<h2 id="completion-of-the-generation-of-images-for-the-matplotlib-directory">Completion of the generation of images for the matplotlib directory<a class="headerlink" href="#completion-of-the-generation-of-images-for-the-matplotlib-directory" title="Link to this heading">#</a></h2>
<p>We successfully created the <code>matplotlib_baseline_image_generation</code> flag in the beginning of the second evaluation but images were not created in the <code>baseline images</code> directory inside the <code>matplotlib</code> and <code>mpl_toolkits</code> directories, instead they were created in the <code>result_images</code> directory. So, we implemented this functionality. The images are created in the <code>lib/matplotlib/tests/baseline_images</code> directory directly now in the baseline image generation step. The baseline image generation step uses <code>python3 -mpytest lib/matplotlib --matplotlib_baseline_image_generation</code> command. Later on, running the pytests with <code>python3 -mpytest lib/matplotlib</code> will start the image comparison.</p>
<p>Right now, the matplotlib_baseline_image_generation flag works for the matplotlib directory. We are trying to achieve the same functionality for the mpl_toolkits directory.</p>
<h2 id="future-goals">Future Goals<a class="headerlink" href="#future-goals" title="Link to this heading">#</a></h2>
<p>Once the generation of the baseline images for <code>mpl_toolkits</code> directory is completed in the <a href="https://github.com/matplotlib/matplotlib/pull/17793">current PR</a>, we will move to the modification of the baseline images in the third coding phase. The addition of new baseline image and deletion of the old baseline image will also be implemented in the last phase of GSoC. Modification of baseline images will be further divided into two sub tasks: addition of new baseline image and the deletion of the previous baseline image.</p>
<h2 id="daily-meet-ups">Daily Meet-ups<a class="headerlink" href="#daily-meet-ups" title="Link to this heading">#</a></h2>
<p>Monday to Thursday meeting initiated at <a href="https://everytimezone.com/">11:00pm IST</a> via Zoom. Meeting notes are present at HackMD.</p>
<p>I am grateful to be part of such a great community. Project is really interesting and challenging :) Thanks Thomas, Antony and Hannah for helping me so far.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Elementary Cellular Automata]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/animated-fractals/?utm_source=atom_feed" rel="related" type="text/html" title="Animate Your Own Fractals in Python with Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-polar-plot/?utm_source=atom_feed" rel="related" type="text/html" title="Animated polar plot with oceanographic data" />
                <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="related" type="text/html" title="Emoji Mosaic Art" />
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib Cyberpunk Style" />
            
                <id>https://blog.scientific-python.org/matplotlib/elementary-cellular-automata/</id>
            
            
            <published>2020-07-14T15:48:23-04:00</published>
            <updated>2020-07-14T15:48:23-04:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>A brief tour through the world of elementary cellular automata</blockquote><p><a href="https://en.wikipedia.org/wiki/Cellular_automaton">Cellular automata</a> are discrete models, typically on a grid, which evolve in time. Each grid cell has a finite state, such as 0 or 1, which is updated based on a certain set of rules. A specific cell uses information of the surrounding cells, called it&rsquo;s <em>neighborhood</em>, to determine what changes should be made. In general cellular automata can be defined in any number of dimensions. A famous two dimensional example is <a href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life">Conway&rsquo;s Game of Life</a> in which cells &ldquo;live&rdquo; and &ldquo;die&rdquo;, sometimes producing beautiful patterns.</p>
<p>In this post we will be looking at a one dimensional example known as <a href="https://en.wikipedia.org/wiki/Elementary_cellular_automaton">elementary cellular automaton</a>, popularized by <a href="https://en.wikipedia.org/wiki/Stephen_Wolfram">Stephen Wolfram</a> in the 1980s.</p>
<p><img src="/matplotlib/elementary-cellular-automata/ca-bar.png" alt="A row of cells, arranged side by side, each of which is colored black or white. The first few cells are white, then one black cell, and alternates in a similar pattern."></p>
<p>Imagine a row of cells, arranged side by side, each of which is colored black or white. We label black cells 1 and white cells 0, resulting in an array of bits. As an example lets consider a random array of 20 bits.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">rng</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">RandomState</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="n">rng</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">data</span><span class="p">)</span></span></span></code></pre>
</div>
<pre><code>[0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 1 1 1 0]
</code></pre>
<p>To update the state of our cellular automaton we will need to define a set of rules.
A given cell \(C\) only knows about the state of it&rsquo;s left and right neighbors, labeled \(L\) and \(R\) respectively. We can define a function or rule, \(f(L, C, R)\), which maps the cell state to either 0 or 1.</p>
<p>Since our input cells are binary values there are \(2^3=8\) possible inputs into the function.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">binary_repr</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span></span></span></code></pre>
</div>
<pre><code>000
001
010
011
100
101
110
111
</code></pre>
<p>For each input triplet, we can assign 0 or 1 to the output. The output of \(f\) is the value which will replace the current cell \(C\) in the next time step. In total there are \(2^{2^3} = 2^8 = 256\) possible rules for updating a cell. Stephen Wolfram introduced a naming convention, now known as the <a href="https://en.wikipedia.org/wiki/Wolfram_code">Wolfram Code</a>, for the update rules in which each rule is represented by an 8 bit binary number.</p>
<p>For example &ldquo;Rule 30&rdquo; could be constructed by first converting to binary and then building an array for each bit</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">rule_number</span> <span class="o">=</span> <span class="mi">30</span>
</span></span><span class="line"><span class="cl"><span class="n">rule_string</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">binary_repr</span><span class="p">(</span><span class="n">rule_number</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">rule</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="n">bit</span><span class="p">)</span> <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">rule_string</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">rule</span><span class="p">)</span></span></span></code></pre>
</div>
<pre><code>[0 0 0 1 1 1 1 0]
</code></pre>
<p>By convention the Wolfram code associates the leading bit with &lsquo;111&rsquo; and the final bit with &lsquo;000&rsquo;. For rule 30 the relationship between the input, rule index and output is as follows:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">triplet</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">binary_repr</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;input:</span><span class="si">{</span><span class="n">triplet</span><span class="si">}</span><span class="s2">, index:</span><span class="si">{</span><span class="mi">7</span><span class="o">-</span><span class="n">i</span><span class="si">}</span><span class="s2">, output </span><span class="si">{</span><span class="n">rule</span><span class="p">[</span><span class="mi">7</span><span class="o">-</span><span class="n">i</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<pre><code>input:000, index:7, output 0
input:001, index:6, output 1
input:010, index:5, output 1
input:011, index:4, output 1
input:100, index:3, output 1
input:101, index:2, output 0
input:110, index:1, output 0
input:111, index:0, output 0
</code></pre>
<p>We can define a function which maps the input cell information with the associated rule index. Essentially we are converting the binary input to decimal and adjusting the index range.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">rule_index</span><span class="p">(</span><span class="n">triplet</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">L</span><span class="p">,</span> <span class="n">C</span><span class="p">,</span> <span class="n">R</span> <span class="o">=</span> <span class="n">triplet</span>
</span></span><span class="line"><span class="cl">    <span class="n">index</span> <span class="o">=</span> <span class="mi">7</span> <span class="o">-</span> <span class="p">(</span><span class="mi">4</span> <span class="o">*</span> <span class="n">L</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">C</span> <span class="o">+</span> <span class="n">R</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">index</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Now we can take in any input and look up the output based on our rule, for example:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">rule</span><span class="p">[</span><span class="n">rule_index</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">))]</span></span></span></code></pre>
</div>
<pre><code>0
</code></pre>
<p>Finally, we can use Numpy to create a data structure containing all the triplets for our state array and apply the function across the appropriate axis to determine our new state.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">all_triplets</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">stack</span><span class="p">([</span><span class="n">np</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">data</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)])</span>
</span></span><span class="line"><span class="cl"><span class="n">new_data</span> <span class="o">=</span> <span class="n">rule</span><span class="p">[</span><span class="n">np</span><span class="o">.</span><span class="n">apply_along_axis</span><span class="p">(</span><span class="n">rule_index</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">all_triplets</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">new_data</span><span class="p">)</span></span></span></code></pre>
</div>
<pre><code>[1 1 1 0 1 1 1 0 1 1 1 0 0 1 1 0 1 0 0 1]
</code></pre>
<p>That is the process for a single update of our cellular automata.</p>
<p>To do many updates and record the state over time, we will create a function.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">CA_run</span><span class="p">(</span><span class="n">initial_state</span><span class="p">,</span> <span class="n">n_steps</span><span class="p">,</span> <span class="n">rule_number</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">rule_string</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">binary_repr</span><span class="p">(</span><span class="n">rule_number</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">rule</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="n">bit</span><span class="p">)</span> <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="n">rule_string</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">m_cells</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">initial_state</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">CA_run</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">((</span><span class="n">n_steps</span><span class="p">,</span> <span class="n">m_cells</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">CA_run</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="p">:]</span> <span class="o">=</span> <span class="n">initial_state</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">step</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n_steps</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">all_triplets</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">stack</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span>
</span></span><span class="line"><span class="cl">                <span class="n">np</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="n">CA_run</span><span class="p">[</span><span class="n">step</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="p">:],</span> <span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="n">CA_run</span><span class="p">[</span><span class="n">step</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="p">:],</span>
</span></span><span class="line"><span class="cl">                <span class="n">np</span><span class="o">.</span><span class="n">roll</span><span class="p">(</span><span class="n">CA_run</span><span class="p">[</span><span class="n">step</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="p">:],</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">CA_run</span><span class="p">[</span><span class="n">step</span><span class="p">,</span> <span class="p">:]</span> <span class="o">=</span> <span class="n">rule</span><span class="p">[</span><span class="n">np</span><span class="o">.</span><span class="n">apply_along_axis</span><span class="p">(</span><span class="n">rule_index</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">all_triplets</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">CA_run</span></span></span></code></pre>
</div>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">initial</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="n">CA_run</span><span class="p">(</span><span class="n">initial</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">data</span><span class="p">)</span></span></span></code></pre>
</div>
<pre><code>[[0. 1. 0. 0. 0. 1. 0. 0. 0. 1. 0. 0. 0. 0. 1. 0. 1. 1. 1. 0.]
 [1. 1. 1. 0. 1. 1. 1. 0. 1. 1. 1. 0. 0. 1. 1. 0. 1. 0. 0. 1.]
 [0. 0. 0. 0. 1. 0. 0. 0. 1. 0. 0. 1. 1. 1. 0. 0. 1. 1. 1. 1.]
 [1. 0. 0. 1. 1. 1. 0. 1. 1. 1. 1. 1. 0. 0. 1. 1. 1. 0. 0. 0.]
 [1. 1. 1. 1. 0. 0. 0. 1. 0. 0. 0. 0. 1. 1. 1. 0. 0. 1. 0. 1.]
 [0. 0. 0. 0. 1. 0. 1. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 1. 0. 1.]
 [1. 0. 0. 1. 1. 0. 1. 0. 0. 1. 1. 1. 0. 1. 1. 1. 0. 0. 0. 1.]
 [0. 1. 1. 1. 0. 0. 1. 1. 1. 1. 0. 0. 0. 1. 0. 0. 1. 0. 1. 1.]
 [0. 1. 0. 0. 1. 1. 1. 0. 0. 0. 1. 0. 1. 1. 1. 1. 1. 0. 1. 0.]
 [1. 1. 1. 1. 1. 0. 0. 1. 0. 1. 1. 0. 1. 0. 0. 0. 0. 0. 1. 1.]]
</code></pre>
<h2 id="lets-get-visual">Let&rsquo;s Get Visual<a class="headerlink" href="#lets-get-visual" title="Link to this heading">#</a></h2>
<p>For larger simulations, interesting patterns start to emerge. To visualize our simulation results we will use the <code>ax.matshow</code> function.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s2">&#34;image.cmap&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;binary&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">rng</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">RandomState</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="n">CA_run</span><span class="p">(</span><span class="n">rng</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">300</span><span class="p">),</span> <span class="mi">150</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">9</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">matshow</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/elementary-cellular-automata/output_18_0.png" alt="png"></p>
<h2 id="learning-the-rules">Learning the Rules<a class="headerlink" href="#learning-the-rules" title="Link to this heading">#</a></h2>
<p>With the code set up to produce the simulation, we can now start to explore the properties of these different rules. Wolfram separated the rules into four classes which are outlined below.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">plot_CA_class</span><span class="p">(</span><span class="n">rule_list</span><span class="p">,</span> <span class="n">class_label</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">rng</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">RandomState</span><span class="p">(</span><span class="n">seed</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="p">,</span> <span class="n">axs</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">rule_list</span><span class="p">),</span> <span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mf">3.5</span><span class="p">),</span> <span class="n">constrained_layout</span><span class="o">=</span><span class="kc">True</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">initial</span> <span class="o">=</span> <span class="n">rng</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">ax</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">axs</span><span class="o">.</span><span class="n">ravel</span><span class="p">()):</span>
</span></span><span class="line"><span class="cl">        <span class="n">data</span> <span class="o">=</span> <span class="n">CA_run</span><span class="p">(</span><span class="n">initial</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="n">rule_list</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">set_title</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Rule </span><span class="si">{</span><span class="n">rule_list</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">matshow</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">suptitle</span><span class="p">(</span><span class="n">class_label</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">16</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">fig</span><span class="p">,</span> <span class="n">ax</span></span></span></code></pre>
</div>
<h3 id="class-one">Class One<a class="headerlink" href="#class-one" title="Link to this heading">#</a></h3>
<p>Cellular automata which rapidly converge to a uniform state</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">_</span> <span class="o">=</span> <span class="n">plot_CA_class</span><span class="p">([</span><span class="mi">4</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">172</span><span class="p">],</span> <span class="s2">&#34;Class One&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/elementary-cellular-automata/output_22_0.png" alt="png"></p>
<h3 id="class-two">Class Two<a class="headerlink" href="#class-two" title="Link to this heading">#</a></h3>
<p>Cellular automata which rapidly converge to a repetitive or stable state</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">_</span> <span class="o">=</span> <span class="n">plot_CA_class</span><span class="p">([</span><span class="mi">50</span><span class="p">,</span> <span class="mi">108</span><span class="p">,</span> <span class="mi">173</span><span class="p">],</span> <span class="s2">&#34;Class Two&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/elementary-cellular-automata/output_24_0.png" alt="png"></p>
<h3 id="class-three">Class Three<a class="headerlink" href="#class-three" title="Link to this heading">#</a></h3>
<p>Cellular automata which appear to remain in a random state</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">_</span> <span class="o">=</span> <span class="n">plot_CA_class</span><span class="p">([</span><span class="mi">60</span><span class="p">,</span> <span class="mi">106</span><span class="p">,</span> <span class="mi">150</span><span class="p">],</span> <span class="s2">&#34;Class Three&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/elementary-cellular-automata/output_26_0.png" alt="png"></p>
<h3 id="class-four">Class Four<a class="headerlink" href="#class-four" title="Link to this heading">#</a></h3>
<p>Cellular automata which form areas of repetitive or stable states, but also form structures that interact with each other in complicated ways.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">_</span> <span class="o">=</span> <span class="n">plot_CA_class</span><span class="p">([</span><span class="mi">54</span><span class="p">,</span> <span class="mi">62</span><span class="p">,</span> <span class="mi">110</span><span class="p">],</span> <span class="s2">&#34;Class Four&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/elementary-cellular-automata/output_28_0.png" alt="png"></p>
<p>Amazingly, the interacting structures which emerge from rule 110 has been shown to be capable of <a href="https://en.wikipedia.org/wiki/Turing_machine">universal computation</a>.</p>
<p>In all the examples above a random initial state was used, but another interesting case is when a single 1 is initialized with all other values set to zero.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">initial</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="mi">300</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">initial</span><span class="p">[</span><span class="mi">300</span> <span class="o">//</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="n">CA_run</span><span class="p">(</span><span class="n">initial</span><span class="p">,</span> <span class="mi">150</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">matshow</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/elementary-cellular-automata/output_31_0.png" alt="png"></p>
<p>For certain rules, the emergent structures interact in chaotic and interesting ways.</p>
<p>I hope you enjoyed this brief look into the world of elementary cellular automata, and are inspired to make some pretty pictures of your own.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC Coding Phase 2 Blog 1]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_3/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_2/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 2" />
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_1/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/introductory-gsoc2020-post/?utm_source=atom_feed" rel="related" type="text/html" title="Sidharth Bansal joined as GSoC&#39;20 intern" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-rsef/?utm_source=atom_feed" rel="related" type="text/html" title="Elliott Sales de Andrade hired as Matplotlib Software Research Engineering Fellow" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-fractals/?utm_source=atom_feed" rel="related" type="text/html" title="Animate Your Own Fractals in Python with Matplotlib" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_3/</id>
            
            
            <published>2020-07-11T19:47:51+05:30</published>
            <updated>2020-07-11T19:47:51+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Progress Report for the first half of the Google Summer of Code 2020 Phase 2 for the Baseline Images Problem</blockquote><p>Google Summer of Code 2020&rsquo;s first evaluation is completed. I passed!!! Hurray! Now we are in the mid way of the second evaluation. This post discusses about the progress so far in the first two weeks of the second coding period from 30 June to 12 July 2020.</p>
<h2 id="completion-of-the-matplotlib_baseline_images-package">Completion of the matplotlib_baseline_images package<a class="headerlink" href="#completion-of-the-matplotlib_baseline_images-package" title="Link to this heading">#</a></h2>
<p>We successfully created the matplotlib_baseline_images package. It contains the matplotlib and the matplotlib toolkit baseline images. Symlinking is done for the baseline images, related changes for Travis, appvoyer, azure pipelines etc. are functional and tests/test_data is created as discussed in the previous blog. PR is reviewed and suggested work is done.</p>
<h2 id="modular-approach-towards-removal-of-matplotlib-baseline-images">Modular approach towards removal of matplotlib baseline images<a class="headerlink" href="#modular-approach-towards-removal-of-matplotlib-baseline-images" title="Link to this heading">#</a></h2>
<p>We have divide the work in two parts. The first part is the generation of the baseline images discussed below. The second part is the modification of the baseline images which happens when some baseline images gets modified due to <code>git push</code> or <code>git merge</code>. Modification of baseline images will be further divided into two sub tasks: addition of new baseline image and the deletion of the previous baseline image. This will be discussed in the second half of the second phase of the Google Summer of Code 2020.</p>
<h2 id="generation-of-the-matplotlib-baseline-images">Generation of the matplotlib baseline images<a class="headerlink" href="#generation-of-the-matplotlib-baseline-images" title="Link to this heading">#</a></h2>
<p>After the changes proposed in the <a href="https://github.com/matplotlib/matplotlib/pull/17557">previous PR</a>, the developer will have no baseline images on fresh install of matplotlib. The developer would need to install the sub-wheel matplotlib_baseline_images package to get started with the testing part of the mpl. Now, we have started removing the use of the matplotlib_baseline_images package. It will require two steps as discussed above.
The images can be generated by the image comparison tests. Once these images are generated for the first time, then they can be used as the baseline images for the later times for comparison. This is the main principle adopted. The images are first created in the <code>result_images</code> directory. Then they will be moved to the <code>lib/matplotlib/tests/baseline_images</code> directory. Later on, running the pytests will start the image comparison.</p>
<h2 id="created-commandline-flags-for-baseline-images-creation">Created commandline flags for baseline images creation<a class="headerlink" href="#created-commandline-flags-for-baseline-images-creation" title="Link to this heading">#</a></h2>
<p>I learned about the pytest hooks and fixtures. I build a command line flag <code>matplotlib_baseline_image_generation</code> which will create the baseline images in the <code>result_images</code> directory. The full command will be <code>python3 pytest --matplotlib_baseline_image_generation</code>. In order to do this, we have done changes in the <code>conftest.py</code> and also added markers to the <code>image_comparison</code> decorator.</p>
<h2 id="learning-more-about-the-git-and-virtual-environments">Learning more about the Git and virtual environments<a class="headerlink" href="#learning-more-about-the-git-and-virtual-environments" title="Link to this heading">#</a></h2>
<p>I came to know about the git worktree and the scenarios in which we can use it. I also know more about virtual environments and their need in different scenarios.</p>
<h2 id="future-goals">Future Goals<a class="headerlink" href="#future-goals" title="Link to this heading">#</a></h2>
<p>Once the generation of the baseline images is completed in the <a href="https://github.com/matplotlib/matplotlib/pull/17793">current PR</a>, we will move to the modification of the baseline images in the second half of the second coding phase.</p>
<h2 id="daily-meet-ups">Daily Meet-ups<a class="headerlink" href="#daily-meet-ups" title="Link to this heading">#</a></h2>
<p>Monday to Thursday meeting initiated at <a href="https://everytimezone.com/">11:00pm IST</a> via Zoom. Meeting notes are present at HackMD.</p>
<p>I am grateful to be part of such a great community. Project is really interesting and challenging :) Thanks Thomas, Antony and Hannah for helping me so far.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Animate Your Own Fractals in Python with Matplotlib]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/animated-fractals/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/animated-polar-plot/?utm_source=atom_feed" rel="related" type="text/html" title="Animated polar plot with oceanographic data" />
                <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="related" type="text/html" title="Emoji Mosaic Art" />
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib Cyberpunk Style" />
                <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib for Making Diagrams" />
            
                <id>https://blog.scientific-python.org/matplotlib/animated-fractals/</id>
            
            
            <published>2020-07-04T00:06:36+02:00</published>
            <updated>2020-07-04T00:06:36+02:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Discover the bizarre geometry of the fractals and learn how to make an animated visualization of these marvels using Python and the Matplotlib&rsquo;s Animation API.</blockquote><p>Imagine zooming an image over and over and never go out of finer details. It may sound bizarre but the mathematical
concept of <a href="https://en.wikipedia.org/wiki/Fractal">fractals</a> opens the realm towards this intricating infinity. This
strange geometry exhibits the same or similar patterns irrespectively of the scale. We can see one fractal example
in the image above.</p>
<p>The <em>fractals</em> may seem difficult to understand due to their peculiarity, but that&rsquo;s not the case. As Benoit Mandelbrot,
one of the founding fathers of the fractal geometry said in his legendary
<a href="https://www.ted.com/talks/benoit_mandelbrot_fractals_and_the_art_of_roughness?language=en">TED Talk</a>:</p>
<blockquote>
<p>A surprising aspect is that the rules of this geometry are extremely short. You crank the formulas several times and
at the end, you get things like this (pointing to a stunning plot)</p>
<p>&ndash; <cite>Benoit Mandelbrot</cite></p>
</blockquote>
<p>In this tutorial blog post, we will see how to construct fractals in Python and animate them using the amazing
<em>Matplotlib&rsquo;s</em> Animation API. First, we will demonstrate the convergence of the <em>Mandelbrot Set</em> with an
enticing animation. In the second part, we will analyze one interesting property of the <em>Julia Set</em>. Stay tuned!</p>
<h1 id="intuition">Intuition<a class="headerlink" href="#intuition" title="Link to this heading">#</a></h1>
<p>We all have a common sense of the concept of similarity. We say two objects are similar to each other if they share
some common patterns.</p>
<p>This notion is not only limited to a comparison of two different objects. We can also compare different parts of the
same object. For instance, a leaf. We know very well that the left side matches exactly the right side, i.e. the leaf
is symmetrical.</p>
<p>In mathematics, this phenomenon is known as <a href="https://en.wikipedia.org/wiki/Self-similarity">self-similarity</a>. It means
a given object is similar (completely or to some extent) to some smaller part of itself. One remarkable example is the
<a href="https://isquared.digital/visualizations/2020-06-15-koch-curve/">An orange Koch Snowflake. It has 6 bulges which themselves have 3 sub-bulges. These sub-bulges have another 3 sub-sub bulges. </a> as shown in the image below:</p>
<p><img src="/matplotlib/animated-fractals/snowflake.png" alt="Koch Snowflake"></p>
<p>We can infinitely magnify some part of it and the same pattern will repeat over and over again. This is how fractal
geometry is defined.</p>
<h1 id="animated-mandelbrot-set">Animated Mandelbrot Set<a class="headerlink" href="#animated-mandelbrot-set" title="Link to this heading">#</a></h1>
<p><a href="https://en.wikipedia.org/wiki/Mandelbrot_set">Mandelbrot Set</a> is defined over the set of <em>complex numbers</em>. It consists
of all complex numbers <strong>c</strong>, such that the sequence <strong>zᵢ₊ᵢ = zᵢ² + c, z₀ = 0</strong> is bounded. It means, after a certain
number of iterations the absolute value must not exceed a given limit. At first sight, it might
seem odd and simple, but in fact, it has some mind-blowing properties.</p>
<p>The <em>Python</em> implementation is quite straightforward, as given in the code snippet below:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">mandelbrot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">threshold</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Calculates whether the number c = x + i*y belongs to the
</span></span></span><span class="line"><span class="cl"><span class="s2">    Mandelbrot set. In order to belong, the sequence z[i + 1] = z[i]**2 + c
</span></span></span><span class="line"><span class="cl"><span class="s2">    must not diverge after &#39;threshold&#39; number of steps. The sequence diverges
</span></span></span><span class="line"><span class="cl"><span class="s2">    if the absolute value of z[i+1] is greater than 4.
</span></span></span><span class="line"><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="cl"><span class="s2">    :param float x: the x component of the initial complex number
</span></span></span><span class="line"><span class="cl"><span class="s2">    :param float y: the y component of the initial complex number
</span></span></span><span class="line"><span class="cl"><span class="s2">    :param int threshold: the number of iterations to considered it converged
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># initial conditions</span>
</span></span><span class="line"><span class="cl">    <span class="n">c</span> <span class="o">=</span> <span class="nb">complex</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="nb">complex</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">threshold</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">z</span> <span class="o">=</span> <span class="n">z</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">c</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">z</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mf">4.0</span><span class="p">:</span>  <span class="c1"># it diverged</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">i</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">threshold</span> <span class="o">-</span> <span class="mi">1</span>  <span class="c1"># it didn&#39;t diverge</span></span></span></code></pre>
</div>
<p>As we can see, we set the maximum number of iterations encoded in the variable <code>threshold</code>. If the magnitude of the
sequence at some iteration exceeds <strong>4</strong>, we consider it as diverged (<strong>c</strong> does not belong to the set) and return the
iteration number at which this occurred. If this never happens (<strong>c</strong> belongs to the set), we return the maximum
number of iterations.</p>
<p>We can use the information about the number of iterations before the sequence diverges. All we have to do
is to associate this number to a color relative to the maximum number of loops. Thus, for all complex numbers
<strong>c</strong> in some lattice of the complex plane, we can make a nice animation of the convergence process as a function
of the maximum allowed iterations.</p>
<p>One particular and interesting area is the <em>3x3</em> lattice starting at position -2 and -1.5 for the <em>real</em> and
<em>imaginary</em> axis respectively. We can observe the process of convergence as the number of allowed iterations increases.
This is easily achieved using the <em>Matplotlib&rsquo;s</em> Animation API, as shown with the following code:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.animation</span> <span class="k">as</span> <span class="nn">animation</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">x_start</span><span class="p">,</span> <span class="n">y_start</span> <span class="o">=</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.5</span>  <span class="c1"># an interesting region starts here</span>
</span></span><span class="line"><span class="cl"><span class="n">width</span><span class="p">,</span> <span class="n">height</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span>  <span class="c1"># for 3 units up and right</span>
</span></span><span class="line"><span class="cl"><span class="n">density_per_unit</span> <span class="o">=</span> <span class="mi">250</span>  <span class="c1"># how many pixles per unit</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># real and imaginary axis</span>
</span></span><span class="line"><span class="cl"><span class="n">re</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="n">x_start</span><span class="p">,</span> <span class="n">x_start</span> <span class="o">+</span> <span class="n">width</span><span class="p">,</span> <span class="n">width</span> <span class="o">*</span> <span class="n">density_per_unit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">im</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="n">y_start</span><span class="p">,</span> <span class="n">y_start</span> <span class="o">+</span> <span class="n">height</span><span class="p">,</span> <span class="n">height</span> <span class="o">*</span> <span class="n">density_per_unit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>  <span class="c1"># instantiate a figure to draw</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">axes</span><span class="p">()</span>  <span class="c1"># create an axes object</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">animate</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>  <span class="c1"># clear axes object</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xticks</span><span class="p">([],</span> <span class="p">[])</span>  <span class="c1"># clear x-axis ticks</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_yticks</span><span class="p">([],</span> <span class="p">[])</span>  <span class="c1"># clear y-axis ticks</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">X</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">empty</span><span class="p">((</span><span class="nb">len</span><span class="p">(</span><span class="n">re</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">im</span><span class="p">)))</span>  <span class="c1"># re-initialize the array-like image</span>
</span></span><span class="line"><span class="cl">    <span class="n">threshold</span> <span class="o">=</span> <span class="nb">round</span><span class="p">(</span><span class="mf">1.15</span> <span class="o">**</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>  <span class="c1"># calculate the current threshold</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># iterations for the current threshold</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">re</span><span class="p">)):</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">im</span><span class="p">)):</span>
</span></span><span class="line"><span class="cl">            <span class="n">X</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">mandelbrot</span><span class="p">(</span><span class="n">re</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">im</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">threshold</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># associate colors to the iterations with an interpolation</span>
</span></span><span class="line"><span class="cl">    <span class="n">img</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">X</span><span class="o">.</span><span class="n">T</span><span class="p">,</span> <span class="n">interpolation</span><span class="o">=</span><span class="s2">&#34;bicubic&#34;</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="s2">&#34;magma&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">[</span><span class="n">img</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">anim</span> <span class="o">=</span> <span class="n">animation</span><span class="o">.</span><span class="n">FuncAnimation</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">animate</span><span class="p">,</span> <span class="n">frames</span><span class="o">=</span><span class="mi">45</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">120</span><span class="p">,</span> <span class="n">blit</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">anim</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="s2">&#34;mandelbrot.gif&#34;</span><span class="p">,</span> <span class="n">writer</span><span class="o">=</span><span class="s2">&#34;imagemagick&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>We make animations in <em>Matplotlib</em> using the <code>FuncAnimation</code> function from the <em>Animation</em> API. We need to specify
the <code>figure</code> on which we draw a predefined number of consecutive <code>frames</code>. A predetermined <code>interval</code> expressed in
milliseconds defines the delay between the frames.</p>
<p>In this context, the <code>animate</code> function plays a central role, where the input argument is the frame number, starting
from 0. It means, in order to animate we always have to think in terms of frames. Hence, we use the frame number
to calculate the variable <code>threshold</code> which is the maximum number of allowed iterations.</p>
<p>To represent our lattice we instantiate two arrays <code>re</code> and <code>im</code>: the former for the values on the <em>real</em> axis
and the latter for the values on the <em>imaginary</em> axis. The number of elements in these two arrays is defined by
the variable <code>density_per_unit</code> which defines the number of samples per unit step. The higher it is, the better
quality we get, but at a cost of heavier computation.</p>
<p>Now, depending on the current <code>threshold</code>, for every complex number <strong>c</strong> in our lattice, we calculate the number of
iterations before the sequence <strong>zᵢ₊ᵢ = zᵢ² + c, z₀ = 0</strong> diverges. We save them in an initially empty matrix called <code>X</code>.
In the end, we <em>interpolate</em> the values in <code>X</code> and assign them a color drawn from a prearranged <em>colormap</em>.</p>
<p>After cranking the <code>animate</code> function multiple times we get a stunning animation as depicted below:</p>
<p><img src="/matplotlib/animated-fractals/mandelbrot.gif" alt="Mandelbrot set animation. The first few frames only show a few outlines of the Mandelbrot shape. The middle frames show a more defined shape. The last few frames show the characteristic Mandelbrot shape in a very clear way."></p>
<h1 id="animated-julia-set">Animated Julia Set<a class="headerlink" href="#animated-julia-set" title="Link to this heading">#</a></h1>
<p>The <a href="https://en.wikipedia.org/wiki/Julia_set">Julia Set</a> is quite similar to the <em>Mandelbrot Set</em>. Instead of setting
<strong>z₀ = 0</strong> and testing whether for some complex number <strong>c = x + i*y</strong> the sequence <strong>zᵢ₊ᵢ = zᵢ² + c</strong> is bounded, we
switch the roles a bit. We fix the value for <strong>c</strong>, we set an arbitrary initial condition <strong>z₀ = x + i*y</strong>, and we
observe the convergence of the sequence. The <em>Python</em> implementation is given below:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">julia_quadratic</span><span class="p">(</span><span class="n">zx</span><span class="p">,</span> <span class="n">zy</span><span class="p">,</span> <span class="n">cx</span><span class="p">,</span> <span class="n">cy</span><span class="p">,</span> <span class="n">threshold</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Calculates whether the number z[0] = zx + i*zy with a constant c = x + i*y
</span></span></span><span class="line"><span class="cl"><span class="s2">    belongs to the Julia set. In order to belong, the sequence
</span></span></span><span class="line"><span class="cl"><span class="s2">    z[i + 1] = z[i]**2 + c, must not diverge after &#39;threshold&#39; number of steps.
</span></span></span><span class="line"><span class="cl"><span class="s2">    The sequence diverges if the absolute value of z[i+1] is greater than 4.
</span></span></span><span class="line"><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="cl"><span class="s2">    :param float zx: the x component of z[0]
</span></span></span><span class="line"><span class="cl"><span class="s2">    :param float zy: the y component of z[0]
</span></span></span><span class="line"><span class="cl"><span class="s2">    :param float cx: the x component of the constant c
</span></span></span><span class="line"><span class="cl"><span class="s2">    :param float cy: the y component of the constant c
</span></span></span><span class="line"><span class="cl"><span class="s2">    :param int threshold: the number of iterations to considered it converged
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># initial conditions</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="nb">complex</span><span class="p">(</span><span class="n">zx</span><span class="p">,</span> <span class="n">zy</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">c</span> <span class="o">=</span> <span class="nb">complex</span><span class="p">(</span><span class="n">cx</span><span class="p">,</span> <span class="n">cy</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">threshold</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">z</span> <span class="o">=</span> <span class="n">z</span><span class="o">**</span><span class="mi">2</span> <span class="o">+</span> <span class="n">c</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">z</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mf">4.0</span><span class="p">:</span>  <span class="c1"># it diverged</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">i</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">threshold</span> <span class="o">-</span> <span class="mi">1</span>  <span class="c1"># it didn&#39;t diverge</span></span></span></code></pre>
</div>
<p>Obviously, the setup is quite similar as the <em>Mandelbrot Set</em> implementation. The maximum number of iterations is
denoted as <code>threshold</code>. If the magnitude of the sequence is never greater than <strong>4</strong>, the number <strong>z₀</strong> belongs to
the <em>Julia Set</em> and vice-versa.</p>
<p>The number <strong>c</strong> is giving us the freedom to analyze its impact on the convergence of the sequence, given that the
number of maximum iterations is fixed. One interesting range of values for <strong>c</strong> is for <strong>c = r cos α + i × r sin α</strong>
such that <strong>r=0.7885</strong> and <strong>α ∈ [0, 2π]</strong>.</p>
<p>The best possible way to make this analysis is to create an animated visualization as the number <strong>c</strong> changes.
This <a href="https://isquared.digital/blog/2020-02-08-interactive-dataviz/">ameliorates our visual perception</a> and
understanding of such abstract phenomena in a captivating manner. To do so, we use the Matplotlib&rsquo;s <em>Animation API</em>, as
demonstrated in the code below:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.animation</span> <span class="k">as</span> <span class="nn">animation</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">x_start</span><span class="p">,</span> <span class="n">y_start</span> <span class="o">=</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span>  <span class="c1"># an interesting region starts here</span>
</span></span><span class="line"><span class="cl"><span class="n">width</span><span class="p">,</span> <span class="n">height</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">4</span>  <span class="c1"># for 4 units up and right</span>
</span></span><span class="line"><span class="cl"><span class="n">density_per_unit</span> <span class="o">=</span> <span class="mi">200</span>  <span class="c1"># how many pixles per unit</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># real and imaginary axis</span>
</span></span><span class="line"><span class="cl"><span class="n">re</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="n">x_start</span><span class="p">,</span> <span class="n">x_start</span> <span class="o">+</span> <span class="n">width</span><span class="p">,</span> <span class="n">width</span> <span class="o">*</span> <span class="n">density_per_unit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">im</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="n">y_start</span><span class="p">,</span> <span class="n">y_start</span> <span class="o">+</span> <span class="n">height</span><span class="p">,</span> <span class="n">height</span> <span class="o">*</span> <span class="n">density_per_unit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">threshold</span> <span class="o">=</span> <span class="mi">20</span>  <span class="c1"># max allowed iterations</span>
</span></span><span class="line"><span class="cl"><span class="n">frames</span> <span class="o">=</span> <span class="mi">100</span>  <span class="c1"># number of frames in the animation</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># we represent c as c = r*cos(a) + i*r*sin(a) = r*e^{i*a}</span>
</span></span><span class="line"><span class="cl"><span class="n">r</span> <span class="o">=</span> <span class="mf">0.7885</span>
</span></span><span class="line"><span class="cl"><span class="n">a</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span><span class="p">,</span> <span class="n">frames</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>  <span class="c1"># instantiate a figure to draw</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">axes</span><span class="p">()</span>  <span class="c1"># create an axes object</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">animate</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>  <span class="c1"># clear axes object</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xticks</span><span class="p">([],</span> <span class="p">[])</span>  <span class="c1"># clear x-axis ticks</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_yticks</span><span class="p">([],</span> <span class="p">[])</span>  <span class="c1"># clear y-axis ticks</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">X</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">empty</span><span class="p">((</span><span class="nb">len</span><span class="p">(</span><span class="n">re</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">im</span><span class="p">)))</span>  <span class="c1"># the initial array-like image</span>
</span></span><span class="line"><span class="cl">    <span class="n">cx</span><span class="p">,</span> <span class="n">cy</span> <span class="o">=</span> <span class="n">r</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]),</span> <span class="n">r</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>  <span class="c1"># the initial c number</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># iterations for the given threshold</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">re</span><span class="p">)):</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">im</span><span class="p">)):</span>
</span></span><span class="line"><span class="cl">            <span class="n">X</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">julia_quadratic</span><span class="p">(</span><span class="n">re</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">im</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">cx</span><span class="p">,</span> <span class="n">cy</span><span class="p">,</span> <span class="n">threshold</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">img</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">X</span><span class="o">.</span><span class="n">T</span><span class="p">,</span> <span class="n">interpolation</span><span class="o">=</span><span class="s2">&#34;bicubic&#34;</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="s2">&#34;magma&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">[</span><span class="n">img</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">anim</span> <span class="o">=</span> <span class="n">animation</span><span class="o">.</span><span class="n">FuncAnimation</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">animate</span><span class="p">,</span> <span class="n">frames</span><span class="o">=</span><span class="n">frames</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">50</span><span class="p">,</span> <span class="n">blit</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">anim</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="s2">&#34;julia_set.gif&#34;</span><span class="p">,</span> <span class="n">writer</span><span class="o">=</span><span class="s2">&#34;imagemagick&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>The logic in the <code>animate</code> function is very similar to the previous example. We update the number <strong>c</strong> as a function
of the frame number. Based on that we estimate the convergence of all complex numbers in the defined lattice, given the
fixed <code>threshold</code> of allowed iterations. Same as before, we save the results in an initially empty matrix <code>X</code> and
associate them to a color relative to the maximum number of iterations. The resulting animation is illustrated below:</p>
<p><img src="/matplotlib/animated-fractals/julia_set.gif" alt="Julia Set Animation"></p>
<h1 id="summary">Summary<a class="headerlink" href="#summary" title="Link to this heading">#</a></h1>
<p>The fractals are really mind-gobbling structures as we saw during this blog. First, we gave a general intuition
of the fractal geometry. Then, we observed two types of fractals: the <em>Mandelbrot</em> and <em>Julia</em> sets. We implemented
them in Python and made interesting animated visualizations of their properties.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC Coding Phase 1 Blog 2]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_2/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_1/?utm_source=atom_feed" rel="related" type="text/html" title="GSoC Coding Phase 1 Blog 1" />
                <link href="https://blog.scientific-python.org/matplotlib/introductory-gsoc2020-post/?utm_source=atom_feed" rel="related" type="text/html" title="Sidharth Bansal joined as GSoC&#39;20 intern" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-rsef/?utm_source=atom_feed" rel="related" type="text/html" title="Elliott Sales de Andrade hired as Matplotlib Software Research Engineering Fellow" />
                <link href="https://blog.scientific-python.org/matplotlib/animated-polar-plot/?utm_source=atom_feed" rel="related" type="text/html" title="Animated polar plot with oceanographic data" />
                <link href="https://blog.scientific-python.org/matplotlib/pyplot-vs-object-oriented-interface/?utm_source=atom_feed" rel="related" type="text/html" title="Pyplot vs Object Oriented Interface" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_2/</id>
            
            
            <published>2020-06-24T16:47:51+05:30</published>
            <updated>2020-06-24T16:47:51+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Progress Report for the second half of the Google Summer of Code 2020 Phase 1 for the Baseline Images Problem</blockquote><p>Google Summer of Code 2020&rsquo;s first evaluation is about to complete. This post discusses about the progress so far in the last two weeks of the first coding period from 15 June to 30 June 2020.</p>
<h2 id="completion-of-the-demo-package">Completion of the demo package<a class="headerlink" href="#completion-of-the-demo-package" title="Link to this heading">#</a></h2>
<p>We successfully created the demo app and uploaded it to the test.pypi. It contains the main and the secondary package. The main package is analogous to the matplotlib and secondary package is analogous to the matplotlib_baseline_images package as discussed in the previous blog.</p>
<h2 id="learning-more-about-the-git-and-mpl-workflow">Learning more about the Git and mpl workflow<a class="headerlink" href="#learning-more-about-the-git-and-mpl-workflow" title="Link to this heading">#</a></h2>
<p>I came across another way to merge the master into the branch to resolve conflicts is by rebasing the master. I understood how to create modular commits inside a pull request for easy reviewal process and better understandability of the code.</p>
<h2 id="creation-of-the-matplotlib_baseline_images-package">Creation of the matplotlib_baseline_images package<a class="headerlink" href="#creation-of-the-matplotlib_baseline_images-package" title="Link to this heading">#</a></h2>
<p>Then, we implemented the similar changes to create the <code>matplotlib_baseline_images</code> package. Finally, we were successful in uploading it to the <a href="https://test.pypi.org/project/matplotlib.baseline-images/3.3.0rc1/#history">test.pypi</a>. This package is involved in the <code>sub-wheels</code> directory so that more packages can be added in the same directory, if needed in future. The <code>matplotlib_baseline_images</code> package contain baseline images for both <code>matplotlib</code> and <code>mpl_toolkits</code>.
Some changes were required in the main <code>matplotlib</code> package&rsquo;s setup.py so that it will not take information from the packages present in the <code>sub-wheels</code> directory.</p>
<h2 id="symlinking-the-baseline-images">Symlinking the baseline images<a class="headerlink" href="#symlinking-the-baseline-images" title="Link to this heading">#</a></h2>
<p>As baseline images are moved out of the <code>lib/matplotlib</code> and <code>lib/mpl_toolkits</code> directory. We symlinked the locations where they are used, namely in <code>lib/matplotlib/testing/decorator.py</code>, <code>tools/triage_tests.py</code>, <code>lib/matplotlib/tests/__init__.py</code> and <code>lib/mpl_toolkits/tests/__init__.py</code>.</p>
<h2 id="creation-of-the-teststest_data-directory">Creation of the tests/test_data directory<a class="headerlink" href="#creation-of-the-teststest_data-directory" title="Link to this heading">#</a></h2>
<p>There are some test data that is present in the <code>baseline_images</code> which doesn&rsquo;t need to be moved to the <code>matplotlib_baseline_images</code> package. So, that is stored under the <code>lib/matplotlib/tests/test_data</code> folder.</p>
<h2 id="understanding-travis-appvoyer-and-azure-pipelines">Understanding Travis, Appvoyer and Azure-pipelines<a class="headerlink" href="#understanding-travis-appvoyer-and-azure-pipelines" title="Link to this heading">#</a></h2>
<p>I came across the Continuous Integration tools used at mpl. We tried to install the <code>matplotlib</code> followed by <code>matplotlib_baseline_images</code> package in all three travis, appvoyer and azure-pipeline.</p>
<h2 id="future-goals">Future Goals<a class="headerlink" href="#future-goals" title="Link to this heading">#</a></h2>
<p>Once the <a href="https://github.com/matplotlib/matplotlib/pull/17557">current PR</a> is merged, we will move to the <a href="https://github.com/matplotlib/matplotlib/issues/16447">Proposal for the baseline images problem</a>.</p>
<h2 id="daily-meet-ups">Daily Meet-ups<a class="headerlink" href="#daily-meet-ups" title="Link to this heading">#</a></h2>
<p>Everyday meeting initiated at <a href="https://everytimezone.com/">11:00pm IST</a> via Zoom. Meeting notes are present at HackMD.</p>
<p>I am grateful to be part of such a great community. Project is really interesting and challenging :) Thanks Antony and Hannah for helping me so far.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Animated polar plot with oceanographic data]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/animated-polar-plot/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="related" type="text/html" title="Emoji Mosaic Art" />
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib Cyberpunk Style" />
                <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib for Making Diagrams" />
                <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="related" type="text/html" title="Create Ridgeplots in Matplotlib" />
            
                <id>https://blog.scientific-python.org/matplotlib/animated-polar-plot/</id>
            
            
            <published>2020-06-12T09:56:36+02:00</published>
            <updated>2020-06-12T09:56:36+02:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>This post describes how to animate some oceanographic measurements in a tweaked polar plot</blockquote><p>The <strong>ocean</strong> is a key component of the Earth climate system. It thus needs a continuous real-time monitoring to help scientists better understand its dynamic and predict its evolution. All around the world, oceanographers have managed to join their efforts and set up a <a href="https://www.goosocean.org">Global Ocean Observing System</a> among which <a href="http://www.argo.ucsd.edu/"><strong>Argo</strong></a> is a key component. Argo is a global network of nearly 4000 autonomous probes or floats measuring pressure, temperature and salinity from the surface to 2000m depth every 10 days. The localisation of these floats is nearly random between the 60th parallels (see live coverage <a href="http://collab.umr-lops.fr/app/divaa/">here</a>). All data are collected by satellite in real-time, processed by several data centers and finally merged in a single dataset (collecting more than 2 millions of vertical profiles data) made freely available to anyone.</p>
<p>In this particular case, we want to plot temperature (surface and 1000m deep) data measured by those floats, for the period 2010-2020 and for the Mediterranean sea. We want this plot to be circular and animated, now you start to get the title of this post: <strong>Animated polar plot</strong>.</p>
<p>First we need some data to work with. To retrieve our temperature values from Argo, we use <a href="https://argopy.readthedocs.io"><strong>Argopy</strong></a>, which is a Python library that aims to ease Argo data access, manipulation and visualization for standard users, as well as Argo experts and operators. Argopy returns <a href="http://xarray.pydata.org">xarray</a> dataset objects, which make our analysis much easier.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="nn">pd</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">argopy</span> <span class="kn">import</span> <span class="n">DataFetcher</span> <span class="k">as</span> <span class="n">ArgoDataFetcher</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">argo_loader</span> <span class="o">=</span> <span class="n">ArgoDataFetcher</span><span class="p">(</span><span class="n">cache</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Query surface and 1000m temp in Med sea with argopy</span>
</span></span><span class="line"><span class="cl"><span class="n">df1</span> <span class="o">=</span> <span class="n">argo_loader</span><span class="o">.</span><span class="n">region</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="o">-</span><span class="mf">1.2</span><span class="p">,</span> <span class="mf">29.0</span><span class="p">,</span> <span class="mf">28.0</span><span class="p">,</span> <span class="mf">46.0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">10.0</span><span class="p">,</span> <span class="s2">&#34;2009-12&#34;</span><span class="p">,</span> <span class="s2">&#34;2020-01&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span><span class="o">.</span><span class="n">to_xarray</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">df2</span> <span class="o">=</span> <span class="n">argo_loader</span><span class="o">.</span><span class="n">region</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="o">-</span><span class="mf">1.2</span><span class="p">,</span> <span class="mf">29.0</span><span class="p">,</span> <span class="mf">28.0</span><span class="p">,</span> <span class="mf">46.0</span><span class="p">,</span> <span class="mf">975.0</span><span class="p">,</span> <span class="mf">1025.0</span><span class="p">,</span> <span class="s2">&#34;2009-12&#34;</span><span class="p">,</span> <span class="s2">&#34;2020-01&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span><span class="o">.</span><span class="n">to_xarray</span><span class="p">()</span></span></span></code></pre>
</div>
<p>Here we create some arrays we&rsquo;ll use for plotting, we set up a date array and extract day of the year and year itself that will be useful. Then to build our temperature array, we use xarray very useful methods : <code>where()</code> and <code>mean()</code>. Then we build a pandas Dataframe, because it&rsquo;s prettier!</p>

<div class="highlight">
  <pre># Weekly date array
daterange = np.arange(&#34;2010-01-01&#34;, &#34;2020-01-03&#34;, dtype=&#34;datetime64[7D]&#34;)
dayoftheyear = pd.DatetimeIndex(
    np.array(daterange, dtype=&#34;datetime64[D]&#34;) &#43; 3
).dayofyear  # middle of the week
activeyear = pd.DatetimeIndex(
    np.array(daterange, dtype=&#34;datetime64[D]&#34;) &#43; 3
).year  # extract year

# Init final arrays
tsurf = np.zeros(len(daterange))
t1000 = np.zeros(len(daterange))

# Filling arrays
for i in range(len(daterange)):
    i1 = (df1[&#34;TIME&#34;] &gt;= daterange[i]) &amp; (df1[&#34;TIME&#34;] &lt; daterange[i] &#43; 7)
    i2 = (df2[&#34;TIME&#34;] &gt;= daterange[i]) &amp; (df2[&#34;TIME&#34;] &lt; daterange[i] &#43; 7)
    tsurf[i] = df1.where(i1, drop=True)[&#34;TEMP&#34;].mean().values
    t1000[i] = df2.where(i2, drop=True)[&#34;TEMP&#34;].mean().values

# Creating dataframe
d = {&#34;date&#34;: np.array(daterange, dtype=&#34;datetime64[D]&#34;), &#34;tsurf&#34;: tsurf, &#34;t1000&#34;: t1000}
ndf = pd.DataFrame(data=d)
ndf.head()</pre>
</div>

<p>This produces:</p>

<div class="highlight">
  <pre>        date  tsurf  t1000
0 2009-12-31    0.0    0.0
1 2010-01-07    0.0    0.0
2 2010-01-14    0.0    0.0
3 2010-01-21    0.0    0.0
4 2010-01-28    0.0    0.0</pre>
</div>

<p>Then it&rsquo;s time to plot, for that we first need to import what we need, and set some useful variables.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s2">&#34;xtick.major.pad&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;17&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">rcParams</span><span class="p">[</span><span class="s2">&#34;axes.axisbelow&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl"><span class="n">matplotlib</span><span class="o">.</span><span class="n">rc</span><span class="p">(</span><span class="s2">&#34;axes&#34;</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s2">&#34;w&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.lines</span> <span class="kn">import</span> <span class="n">Line2D</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.animation</span> <span class="kn">import</span> <span class="n">FuncAnimation</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">HTML</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">big_angle</span> <span class="o">=</span> <span class="mi">360</span> <span class="o">/</span> <span class="mi">12</span>  <span class="c1"># How we split our polar space</span>
</span></span><span class="line"><span class="cl"><span class="n">date_angle</span> <span class="o">=</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">((</span><span class="mi">360</span> <span class="o">/</span> <span class="mi">365</span><span class="p">)</span> <span class="o">*</span> <span class="n">dayoftheyear</span><span class="p">)</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span> <span class="o">/</span> <span class="mi">180</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>  <span class="c1"># For a day, a corresponding angle</span>
</span></span><span class="line"><span class="cl"><span class="c1"># inner and outer ring limit values</span>
</span></span><span class="line"><span class="cl"><span class="n">inner</span> <span class="o">=</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="n">outer</span> <span class="o">=</span> <span class="mi">30</span>
</span></span><span class="line"><span class="cl"><span class="c1"># setting our color values</span>
</span></span><span class="line"><span class="cl"><span class="n">ocean_color</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;#ff7f50&#34;</span><span class="p">,</span> <span class="s2">&#34;#004752&#34;</span><span class="p">]</span></span></span></code></pre>
</div>
<p>Now we want to make our axes like we want, for that we build a function <code>dress_axes</code> that will be called during the animation process. Here we plot some bars with an offset (combination of <code>bottom</code> and <code>ylim</code> after). Those bars are actually our background, and the offset allows us to plot a legend in the middle of the plot.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">dress_axes</span><span class="p">(</span><span class="n">ax</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="s2">&#34;w&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_theta_zero_location</span><span class="p">(</span><span class="s2">&#34;N&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_theta_direction</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Here is how we position the months labels</span>
</span></span><span class="line"><span class="cl">    <span class="n">middles</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="n">big_angle</span> <span class="o">/</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">360</span><span class="p">,</span> <span class="n">big_angle</span><span class="p">)</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span> <span class="o">/</span> <span class="mi">180</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xticks</span><span class="p">(</span><span class="n">middles</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xticklabels</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;January&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;February&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;March&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;April&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;May&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;June&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;July&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;August&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;September&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;October&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;November&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;December&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_yticks</span><span class="p">([</span><span class="mi">15</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">25</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_yticklabels</span><span class="p">([</span><span class="s2">&#34;15°C&#34;</span><span class="p">,</span> <span class="s2">&#34;20°C&#34;</span><span class="p">,</span> <span class="s2">&#34;25°C&#34;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Changing radial ticks angle</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_rlabel_position</span><span class="p">(</span><span class="mi">359</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="s2">&#34;both&#34;</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;w&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="s2">&#34;x&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="s2">&#34;y&#34;</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;w&#34;</span><span class="p">,</span> <span class="n">linestyle</span><span class="o">=</span><span class="s2">&#34;:&#34;</span><span class="p">,</span> <span class="n">linewidth</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Here is the bar plot that we use as background</span>
</span></span><span class="line"><span class="cl">    <span class="n">bars</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">bar</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">middles</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">outer</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">width</span><span class="o">=</span><span class="n">big_angle</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span> <span class="o">/</span> <span class="mi">180</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">bottom</span><span class="o">=</span><span class="n">inner</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="s2">&#34;lightgray&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">edgecolor</span><span class="o">=</span><span class="s2">&#34;w&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">zorder</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">plt</span><span class="o">.</span><span class="n">ylim</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span> <span class="n">outer</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Custom legend</span>
</span></span><span class="line"><span class="cl">    <span class="n">legend_elements</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="n">Line2D</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mi">0</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mi">0</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="n">marker</span><span class="o">=</span><span class="s2">&#34;o&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">color</span><span class="o">=</span><span class="s2">&#34;w&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">label</span><span class="o">=</span><span class="s2">&#34;Surface&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">markerfacecolor</span><span class="o">=</span><span class="n">ocean_color</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="n">markersize</span><span class="o">=</span><span class="mi">15</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">Line2D</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mi">0</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mi">0</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="n">marker</span><span class="o">=</span><span class="s2">&#34;o&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">color</span><span class="o">=</span><span class="s2">&#34;w&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">label</span><span class="o">=</span><span class="s2">&#34;1000m&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">markerfacecolor</span><span class="o">=</span><span class="n">ocean_color</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="n">markersize</span><span class="o">=</span><span class="mi">15</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">legend</span><span class="p">(</span><span class="n">handles</span><span class="o">=</span><span class="n">legend_elements</span><span class="p">,</span> <span class="n">loc</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">13</span><span class="p">,</span> <span class="n">frameon</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Main title for the figure</span>
</span></span><span class="line"><span class="cl">    <span class="n">plt</span><span class="o">.</span><span class="n">suptitle</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;Mediterranean temperature from Argo profiles&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">fontsize</span><span class="o">=</span><span class="mi">16</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">horizontalalignment</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span></span></span></code></pre>
</div>
<p>From there we can plot the frame of our plot.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="mi">111</span><span class="p">,</span> <span class="n">polar</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">dress_axes</span><span class="p">(</span><span class="n">ax</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/animated-polar-plot/axes_empty.png" alt="axesFrame"></p>
<p>Then it&rsquo;s finally time to plot our data. Since we want to animated the plot, we&rsquo;ll build a function that will be called in <code>FuncAnimation</code> later on. Since the state of the plot changes on every time stamp, we have to redress the axes for each frame, easy with our <code>dress_axes</code> function. Then we plot our temperature data using basic <code>plot()</code>: thin lines for historical measurements, thicker lines for the current year.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">draw_data</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Clear</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">cla</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Redressing axes</span>
</span></span><span class="line"><span class="cl">    <span class="n">dress_axes</span><span class="p">(</span><span class="n">ax</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Limit between thin lines and thick line, this is current date minus 51 weeks basically.</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># why 51 and not 52 ? That create a small gap before the current date, which is prettier</span>
</span></span><span class="line"><span class="cl">    <span class="n">i0</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">max</span><span class="p">([</span><span class="n">i</span> <span class="o">-</span> <span class="mi">51</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">date_angle</span><span class="p">[</span><span class="n">i0</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">ndf</span><span class="p">[</span><span class="s2">&#34;tsurf&#34;</span><span class="p">][</span><span class="n">i0</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;-&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="n">ocean_color</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">alpha</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">linewidth</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">date_angle</span><span class="p">[</span><span class="mi">0</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">ndf</span><span class="p">[</span><span class="s2">&#34;tsurf&#34;</span><span class="p">][</span><span class="mi">0</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;-&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="n">ocean_color</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">linewidth</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">date_angle</span><span class="p">[</span><span class="n">i0</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">ndf</span><span class="p">[</span><span class="s2">&#34;t1000&#34;</span><span class="p">][</span><span class="n">i0</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;-&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="n">ocean_color</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">alpha</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">linewidth</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">date_angle</span><span class="p">[</span><span class="mi">0</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">ndf</span><span class="p">[</span><span class="s2">&#34;t1000&#34;</span><span class="p">][</span><span class="mi">0</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;-&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="n">ocean_color</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">linewidth</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Plotting a line to spot the current date easily</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="n">date_angle</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">date_angle</span><span class="p">[</span><span class="n">i</span><span class="p">]],</span> <span class="p">[</span><span class="n">inner</span><span class="p">,</span> <span class="n">outer</span><span class="p">],</span> <span class="s2">&#34;k-&#34;</span><span class="p">,</span> <span class="n">linewidth</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Display the current year as a title, just beneath the suptitle</span>
</span></span><span class="line"><span class="cl">    <span class="n">plt</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">activeyear</span><span class="p">[</span><span class="n">i</span><span class="p">]),</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">16</span><span class="p">,</span> <span class="n">horizontalalignment</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Test it</span>
</span></span><span class="line"><span class="cl"><span class="n">draw_data</span><span class="p">(</span><span class="mi">322</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/animated-polar-plot/thumbnail.png" alt="oneplot"></p>
<p>Finally it&rsquo;s time to animate, using <code>FuncAnimation</code>. Then we save it as a mp4 file or we display it in our notebook with <code>HTML(anim.to_html5_video())</code>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">anim</span> <span class="o">=</span> <span class="n">FuncAnimation</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="p">,</span> <span class="n">draw_data</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">40</span><span class="p">,</span> <span class="n">frames</span><span class="o">=</span><span class="nb">len</span><span class="p">(</span><span class="n">daterange</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="kc">False</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># anim.save(&#39;ArgopyUseCase_MedTempAnimation.mp4&#39;)</span>
</span></span><span class="line"><span class="cl"><span class="n">HTML</span><span class="p">(</span><span class="n">anim</span><span class="o">.</span><span class="n">to_html5_video</span><span class="p">())</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/animated-polar-plot/animatedpolar.gif" alt="animation"></p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[GSoC Coding Phase 1 Blog 1]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_1/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/introductory-gsoc2020-post/?utm_source=atom_feed" rel="related" type="text/html" title="Sidharth Bansal joined as GSoC&#39;20 intern" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-rsef/?utm_source=atom_feed" rel="related" type="text/html" title="Elliott Sales de Andrade hired as Matplotlib Software Research Engineering Fellow" />
                <link href="https://blog.scientific-python.org/matplotlib/pyplot-vs-object-oriented-interface/?utm_source=atom_feed" rel="related" type="text/html" title="Pyplot vs Object Oriented Interface" />
                <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="related" type="text/html" title="Emoji Mosaic Art" />
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
            
                <id>https://blog.scientific-python.org/matplotlib/gsoc_coding_phase_blog_1/</id>
            
            
            <published>2020-06-09T16:47:51+05:30</published>
            <updated>2020-06-09T16:47:51+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Progress Report for the first half of the Google Summer of Code 2020 Phase 1 for the Baseline Images Problem</blockquote><p>I Sidharth Bansal, was waiting for the coding period to start from the March end so that I can make my hands dirty with the code. Finally, coding period has started. Two weeks have passed. This blog contains information about the progress so far from 1 June to 14 June 2020.</p>
<h2 id="movement-from-mpl-test-and-mpl-packages-to-mpl-and-mpl-baseline-images-packages">Movement from mpl-test and mpl packages to mpl and mpl-baseline-images packages<a class="headerlink" href="#movement-from-mpl-test-and-mpl-packages-to-mpl-and-mpl-baseline-images-packages" title="Link to this heading">#</a></h2>
<p>Initially, we thought of creating a <a href="https://github.com/matplotlib/matplotlib/pull/17434">mpl-test and mpl package</a>. Mpl-test package would contain the test suite and baseline images while the other package would contain parts of repository other than test and baseline-images related files and folders.
We changed our decision to creation of <a href="https://github.com/matplotlib/matplotlib/pull/17557">mpl and mpl-baseline-images packages</a> as we don&rsquo;t need to create separate package for entire test suite. Our main aim was to eliminate baseline_images from the repository. Mpl-baseline-images package will contain the data[/baseline images] and related information. The other package will contain files and folders other than baseline images.
We are now trying to create the following structure for the repository:</p>

<div class="highlight">
  <pre>mpl/
  setup.py
  lib/mpl/...
  lib/mpl/tests/...  [contains the tests .py files]
  baseline_images/
    setup.py
    data/...  [contains the image files]</pre>
</div>

<p>It will involve:</p>
<ul>
<li>Symlinking baseline images out.</li>
<li>Creating a wheel/sdist with just the baseline images; uploading it to testpypi (so that one can do <code>pip install mpl-baseline-images</code>).</li>
</ul>
<h2 id="following-prototype-modelling">Following prototype modelling<a class="headerlink" href="#following-prototype-modelling" title="Link to this heading">#</a></h2>
<p>I am creating a prototype first with two packages - main package and sub-wheel package. Once the demo app works well on <a href="https://test.pypi.org/">Test PyPi</a>, we can do similar changes to the main mpl repository.
The structure of demo app is analogous to the work needed for separation of baseline-images to a new package mpl-baseline-images as given below:</p>

<div class="highlight">
  <pre>testrepo/
  setup.py
  lib/testpkg/__init__.py
  baseline_images/setup.py
  baseline_images/testdata.txt</pre>
</div>

<p>This will also include related MANIFEST files and setup.cfg.template files. The setup.py will also contain logic for exclusion of baseline-images folder from the main mpl-package.</p>
<h2 id="following-enhancements-over-iterations">Following Enhancements over iterations<a class="headerlink" href="#following-enhancements-over-iterations" title="Link to this heading">#</a></h2>
<p>After the <a href="https://github.com/matplotlib/matplotlib/pull/17557">current PR</a> is merged, we will focus on eliminating the baseline-images from the mpl-baseline-images package. Then we will do similar changes for the Travis CI.</p>
<h2 id="bi-weekly-meet-ups-scheduled">Bi weekly meet-ups scheduled<a class="headerlink" href="#bi-weekly-meet-ups-scheduled" title="Link to this heading">#</a></h2>
<p>Every Tuesday and every Friday meeting is initiated at <a href="https://everytimezone.com/">8:30pm IST</a> via <a href="https://zoom.us/j/95996536871">Zoom</a>. Meeting notes are present at <a href="https://hackmd.io/pY25bSkCSRymk_7nX68xtw">HackMD</a>.</p>
<p>I am grateful to be part of such a great community. Project is really interesting and challenging :) Thanks Antony and Hannah for helping me so far.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Pyplot vs Object Oriented Interface]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/pyplot-vs-object-oriented-interface/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="related" type="text/html" title="Emoji Mosaic Art" />
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/introductory-gsoc2020-post/?utm_source=atom_feed" rel="related" type="text/html" title="Sidharth Bansal joined as GSoC&#39;20 intern" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib Cyberpunk Style" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-rsef/?utm_source=atom_feed" rel="related" type="text/html" title="Elliott Sales de Andrade hired as Matplotlib Software Research Engineering Fellow" />
            
                <id>https://blog.scientific-python.org/matplotlib/pyplot-vs-object-oriented-interface/</id>
            
            
            <published>2020-05-27T20:21:30+05:30</published>
            <updated>2020-05-27T20:21:30+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>This post describes the difference between the pyplot and object oriented interface to make plots.</blockquote><h2 id="generating-the-data-points">Generating the data points<a class="headerlink" href="#generating-the-data-points" title="Link to this heading">#</a></h2>
<p>To get acquainted with the basics of plotting with <code>matplotlib</code>, let&rsquo;s try plotting how much distance an object under free-fall travels with respect to time and also, its velocity at each time step.</p>
<p>If, you have ever studied physics, you can tell that is a classic case of Newton&rsquo;s equations of motion, where</p>
<p>$$ v = a \times t $$</p>
<p>$$ S = 0.5 \times a \times t^{2} $$</p>
<p>We will assume an initial velocity of zero.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">time</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">10.0</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">velocity</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros_like</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">distance</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros_like</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span></span></span></code></pre>
</div>
<p>We know that under free-fall, all objects move with the constant acceleration of $$g = 9.8~m/s^2$$</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">g</span> <span class="o">=</span> <span class="mf">9.8</span>  <span class="c1"># m/s^2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">velocity</span> <span class="o">=</span> <span class="n">g</span> <span class="o">*</span> <span class="n">time</span>
</span></span><span class="line"><span class="cl"><span class="n">distance</span> <span class="o">=</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="n">g</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">power</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span></span></span></code></pre>
</div>
<p>The above code gives us two <code>numpy</code> arrays populated with the distance and velocity data points.</p>
<h2 id="pyplot-vs-object-oriented-interface">Pyplot vs. Object-Oriented interface<a class="headerlink" href="#pyplot-vs-object-oriented-interface" title="Link to this heading">#</a></h2>
<p>When using <code>matplotlib</code> we have two approaches:</p>
<ol>
<li><code>pyplot</code> interface / functional interface.</li>
<li>Object-Oriented interface (OO).</li>
</ol>
<h3 id="pyplot-interface">Pyplot Interface<a class="headerlink" href="#pyplot-interface" title="Link to this heading">#</a></h3>
<p><code>matplotlib</code> on the surface is made to imitate MATLAB&rsquo;s method of generating plots, which is called <code>pyplot</code>. All the <code>pyplot</code> commands make changes and modify the same figure. This is a state-based interface, where the state (i.e., the figure) is preserved through various function calls (i.e., the methods that modify the figure). This interface allows us to quickly and easily generate plots. The state-based nature of the interface allows us to add elements and/or modify the plot as we need, when we need it.</p>
<p>This interface shares a lot of similarities in syntax and methodology with MATLAB. For example, if we want to plot a blue line where each data point is marked with a circle, we can use the string <code>'bo-'</code>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">7</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">distance</span><span class="p">,</span> <span class="s2">&#34;bo-&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s2">&#34;Time&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s2">&#34;Distance&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">legend</span><span class="p">([</span><span class="s2">&#34;Distance&#34;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span></span></span></code></pre>
</div>
<p>The plot shows how much distance was covered by the free-falling object with each passing second.</p>
<p><img src="/matplotlib/pyplot-vs-object-oriented-interface/figure/just-distance.png" alt="Fig. 1.1"></p>
<div class="image-caption">
<b>Fig. 1.1</b> The amount of distance travelled in each second is increasing, which is a direct result of increasing velocity due to the gravitational acceleration.
</div>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">7</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">velocity</span><span class="p">,</span> <span class="s2">&#34;go-&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s2">&#34;Time&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s2">&#34;Velocity&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">legend</span><span class="p">([</span><span class="s2">&#34;Velocity&#34;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span></span></span></code></pre>
</div>
<p>The plot below shows us how the velocity is increasing.</p>
<p><img src="/matplotlib/pyplot-vs-object-oriented-interface/figure/just-velocity.png" alt="Fig. 1.2"></p>
<div class="image-caption">
<b>Fig. 1.2</b> Velocity is increasing in fixed steps, due to a "constant" acceleration.
</div>
<p>Let&rsquo;s try to see what kind of plot we get when we plot both distance and velocity in the same plot.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">7</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">velocity</span><span class="p">,</span> <span class="s2">&#34;g-&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">distance</span><span class="p">,</span> <span class="s2">&#34;b-&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s2">&#34;Distance and Velocity&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s2">&#34;Time&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">legend</span><span class="p">([</span><span class="s2">&#34;Distance&#34;</span><span class="p">,</span> <span class="s2">&#34;Velocity&#34;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/pyplot-vs-object-oriented-interface/figure/distance-and-velocity-same-axes.png" alt="png"></p>
<p>Here, we run into some obvious and serious issues. We can see that since both the quantities share the same axis but have very different magnitudes, the graph looks disproportionate. What we need to do is separate the two quantities on two different axes. This is where the second approach to making plot comes into play.</p>
<p>Also, the <code>pyplot</code> approach doesn&rsquo;t really scale when we are required to make multiple plots or when we have to make intricate plots that require a lot of customisation. However, internally <code>matplotlib</code> has an Object-Oriented interface that can be accessed just as easily, which allows to reuse objects.</p>
<h3 id="object-oriented-interface">Object-Oriented Interface<a class="headerlink" href="#object-oriented-interface" title="Link to this heading">#</a></h3>
<p>When using the OO interface, it helps to know how the <code>matplotlib</code> structures its plots. The final plot that we see as the output is a &lsquo;Figure&rsquo; object. The <code>Figure</code> object is the top level container for all the other elements that make up the graphic image. These &ldquo;other&rdquo; elements are called <code>Artists</code>. The <code>Figure</code> object can be thought of as a canvas, upon which different artists act to create the final graphic image. This <code>Figure</code> can contain any number of various artists.</p>
<p><img src="/matplotlib/pyplot-vs-object-oriented-interface/figure/anatomy-of-a-figure.png" alt="png"></p>
<p>Things to note about the anatomy of a figure are:</p>
<ol>
<li>All of the items labelled in <em>blue</em> are <code>Artists</code>. <code>Artists</code> are basically all the elements that are rendered onto the figure. This can include text, patches (like arrows and shapes), etc. Thus, all the following <code>Figure</code>, <code>Axes</code> and <code>Axis</code> objects are also Artists.</li>
<li>Each plot that we see in a figure, is an <code>Axes</code> object. The <code>Axes</code> object holds the actual data that we are going to display. It will also contain X- and Y-axis labels, a title. Each <code>Axes</code> object will contain two or more <code>Axis</code> objects.</li>
<li>The <code>Axis</code> objects set the data limits. It also contains the ticks and ticks labels. <code>ticks</code> are the marks that we see on a axis.</li>
</ol>
<p>Understanding this hierarchy of <code>Figure</code>, <code>Artist</code>, <code>Axes</code> and <code>Axis</code> is immensely important, because it plays a crucial role in how me make an animation in <code>matplotlib</code>.</p>
<p>Now that we understand how plots are generated, we can easily solve the problem we faced earlier. To make Velocity and Distance plot to make more sense, we need to plot each data item against a separate axis, with a different scale. Thus, we will need one parent <code>Figure</code> object and two <code>Axes</code> objects.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax1</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s2">&#34;distance (m)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s2">&#34;time&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">distance</span><span class="p">,</span> <span class="s2">&#34;blue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax2</span> <span class="o">=</span> <span class="n">ax1</span><span class="o">.</span><span class="n">twinx</span><span class="p">()</span>  <span class="c1"># create another y-axis sharing a common x-axis</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax2</span><span class="o">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s2">&#34;velocity (m/s)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span><span class="o">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s2">&#34;time&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">velocity</span><span class="p">,</span> <span class="s2">&#34;green&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">set_size_inches</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">set_dpi</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/pyplot-vs-object-oriented-interface/figure/distance-and-velocity-different-axes-unfinished.png" alt="png"></p>
<p>This plot is still not very intuitive. We should add a grid and a legend. Perhaps, we can also change the color of the axis labels and tick labels to the color of the lines.</p>
<p>But, something very weird happens when we try to turn on the grid, which you can see <a href="https://github.com/whereistejas/whereistejas.github.io/blob/master/assets/jupyter-nb/double-pendulum-part-1-basics-of-plotting.ipynb">here</a> at Cell 8. The grid lines don&rsquo;t align with the tick labels on the both the Y-axes. We can see that tick values <code>matplotlib</code> is calculating on its own are not suitable to our needs and, thus, we will have to calculate them ourselves.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax1</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s2">&#34;distance (m)&#34;</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;blue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s2">&#34;time&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">distance</span><span class="p">,</span> <span class="s2">&#34;blue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="o">*</span><span class="n">ax1</span><span class="o">.</span><span class="n">get_ybound</span><span class="p">(),</span> <span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="s2">&#34;y&#34;</span><span class="p">,</span> <span class="n">labelcolor</span><span class="o">=</span><span class="s2">&#34;blue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">xaxis</span><span class="o">.</span><span class="n">grid</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="o">.</span><span class="n">yaxis</span><span class="o">.</span><span class="n">grid</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax2</span> <span class="o">=</span> <span class="n">ax1</span><span class="o">.</span><span class="n">twinx</span><span class="p">()</span>  <span class="c1"># create another y-axis sharing a common x-axis</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax2</span><span class="o">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s2">&#34;velocity (m/s)&#34;</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;green&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span><span class="o">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s2">&#34;time&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax2</span><span class="o">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="s2">&#34;y&#34;</span><span class="p">,</span> <span class="n">labelcolor</span><span class="o">=</span><span class="s2">&#34;green&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">time</span><span class="p">,</span> <span class="n">velocity</span><span class="p">,</span> <span class="s2">&#34;green&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span><span class="o">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="o">*</span><span class="n">ax2</span><span class="o">.</span><span class="n">get_ybound</span><span class="p">(),</span> <span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">set_size_inches</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">set_dpi</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">legend</span><span class="p">([</span><span class="s2">&#34;Distance&#34;</span><span class="p">,</span> <span class="s2">&#34;Velocity&#34;</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p>The command <code>ax1.set_yticks(np.linspace(*ax1.get_ybound(), 10))</code> calculates the tick values for us. Let&rsquo;s break this down to see what is happening:</p>
<ol>
<li>The <code>np.linspace</code> command will create a set of <code>n</code> no. of partitions between a specified upper and lower limit.</li>
<li>The method <code>ax1.get_ybound()</code> returns a list which contains the maximum and minimum limits for that particular axis (which in our case is the Y-axis).</li>
<li>In python, the operator <code>*</code> acts as an unpacking operator when prepended before a <code>list</code> or <code>tuple</code>. Thus, it will convert a list <code>[1, 2, 3, 4]</code> into separate values <code>1, 2, 3, 4</code>. This is an immensely powerful feature.</li>
<li>Thus, we are asking the <code>np.linspace</code> method to divide the interval between the maximum and minimum tick values into 10 equal parts.</li>
<li>We provide this array to the <code>set_yticks</code> method.</li>
</ol>
<p>The same process is repeated for the second axis.</p>
<p><img src="/matplotlib/pyplot-vs-object-oriented-interface/figure/distance-and-velocity-different-axes-finished.png" alt="png"></p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Link to this heading">#</a></h2>
<p>In this part, we covered some basics of <code>matplotlib</code> plotting, covering the basic two approaches of how to make plots. In the next part, we will cover how to make simple animations. If you like the content of this blog post, or you have any suggestions or comments, drop me an email or tweet or ping me on IRC. Nowadays, you will find me hanging around #matplotlib on Freenode. Thanks!</p>
<h2 id="after-thoughts">After-thoughts<a class="headerlink" href="#after-thoughts" title="Link to this heading">#</a></h2>
<p>This post is part of a series I&rsquo;m doing on my personal <a href="http://whereistejas.me">blog</a>. This series is basically going to be about how to animate stuff using python&rsquo;s <code>matplotlib</code> library. <code>matplotlib</code> has an excellent <a href="https://matplotlib.org/3.2.1/contents.html">documentation</a> where you can find a detailed documentation on each of the methods I have used in this blog post. Also, I will be publishing each part of this series in the form of a jupyter notebook, which can be found <a href="https://github.com/whereistejas/whereistejas.github.io/blob/master/assets/jupyter-nb/Part-1-basics-of-plotting.ipynb">here</a>.</p>
<p>The series will have three posts which will cover:</p>
<ol>
<li>Part 1 - How to make plots using <code>matplotlib</code>.</li>
<li>Part 2 - Basic animation using <code>FuncAnimation</code>.</li>
<li>Part 3 - Optimizations to make animations faster (blitting).</li>
</ol>
<p>I would like to say a few words about the methodology of these series:</p>
<ol>
<li>Each part will have a list of references at the end of the post, mostly leading to appropriate pages of the documentation and helpful blogs written by other people. <strong>THIS IS THE MOST IMPORTANT PART</strong>. The sooner you get used to reading the documentation, the better.</li>
<li>The code written here, is meant to show you how you can piece everything together. I will try my best to describe the nuances of my implementations and the tiny lessons I learned.</li>
</ol>
<h2 id="references">References<a class="headerlink" href="#references" title="Link to this heading">#</a></h2>
<ol>
<li><a href="https://youtu.be/bD05uGo_sVI">Python Generators (YouTube)</a></li>
<li><a href="https://medium.com/@kapil.mathur1987/matplotlib-an-introduction-to-its-object-oriented-interface-a318b1530aed">Matplotlib: An Introduction to its Object-Oriented Interface</a></li>
<li><a href="https://matplotlib.org/3.2.1/tutorials/introductory/lifecycle.html">Lifecycle of a Plot</a></li>
<li><a href="https://matplotlib.org/faq/usage_faq.html">Basic Concepts</a></li>
</ol>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Emoji Mosaic Art]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="related" type="text/html" title="Draw all graphs of N nodes" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib Cyberpunk Style" />
                <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib for Making Diagrams" />
                <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="related" type="text/html" title="Create Ridgeplots in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="related" type="text/html" title="Create a Tesla Cybertruck That Drives" />
            
                <id>https://blog.scientific-python.org/matplotlib/emoji-mosaic-art/</id>
            
            
            <published>2020-05-24T19:11:01+05:30</published>
            <updated>2020-05-24T19:11:01+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Applied image manipulation to create procedural art.</blockquote><p>A while back, I came across this cool <a href="https://github.com/willdady/emosaic">repository</a> to create emoji-art from images. I wanted to use it to transform my mundane Facebook profile picture to something more snazzy. The only trouble? It was written in Rust.</p>
<p>So instead of going through the process of installing Rust, I decided to take the easy route and spin up some code to do the same in Python using <a href="https://matplotlib.org/">matplotlib</a>.</p>
<p><del>Because that&rsquo;s what anyone sane would do, right?</del></p>
<p>In this post, I&rsquo;ll try to explain my process as we attempt to recreate similar mosaics as this one below. I&rsquo;ve aimed this post at people who&rsquo;ve worked with <em>some</em> sort of image data before; but really, anyone can follow along.</p>
<p><img src="/matplotlib/emoji-mosaic-art/warhol.png" alt="Emoji mosaic by Will Dady based on Andy Warhol’s Multiple Marilyns."></p>
<h2 id="packages">Packages<a class="headerlink" href="#packages" title="Link to this heading">#</a></h2>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">tqdm</span> <span class="kn">import</span> <span class="n">tqdm</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">scipy</span> <span class="kn">import</span> <span class="n">spatial</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib</span> <span class="kn">import</span> <span class="n">cm</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">scipy</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Matplotlib:</span><span class="si">{</span><span class="n">matplotlib</span><span class="o">.</span><span class="n">__version__</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Numpy:</span><span class="si">{</span><span class="n">np</span><span class="o">.</span><span class="n">__version__</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Scipy: </span><span class="si">{</span><span class="n">scipy</span><span class="o">.</span><span class="n">__version__</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## Matplotlib: &#39;3.2.1&#39;</span>
</span></span><span class="line"><span class="cl"><span class="c1">## Numpy: &#39;1.18.1&#39;</span>
</span></span><span class="line"><span class="cl"><span class="c1">## Scipy: &#39;1.4.1&#39;</span></span></span></code></pre>
</div>
<p>Let&rsquo;s read in our image:</p>

<div class="highlight">
  <pre>img = plt.imread(r&#34;naomi_32.png&#34;, 1)
dim = img.shape[0] ##we&#39;ll need this later
plt.imshow(img)</pre>
</div>

<p><img src="/matplotlib/emoji-mosaic-art/save_100.png" alt="Naomi Watts Cannes (2014) Licensed under Creative Commons attributed to Georges Biard"></p>
<p><strong>Note</strong>: <em>The image displayed above is 100x100 but we&rsquo;ll use a 32x32 from here on since that&rsquo;s gonna suffice all our needs.</em></p>
<p>So really, what <em>is</em> an image? To numpy and matplotlib (and for almost every image processing library out there), it is, essentially, just a matrix (say A), where every individual pixel (p) is an element of A. If it&rsquo;s a grayscale image, every pixel (p) is just a single number (or a scalar) - in the range [0,1] if float, or [0,255] if integer. If it&rsquo;s not grayscale - like in our case - every pixel is a vector of either dimension 3 - <strong>Red</strong> (R), <strong>Green</strong> (G), and <strong>Blue</strong> (B), or dimension 4 - RGBA (A stands for <strong>Alpha</strong>, which is basically transparency).</p>
<p>If anything is unclear so far, I&rsquo;d strongly suggest going through a post like <a href="https://matplotlib.org/3.1.1/tutorials/introductory/images.html">this</a> or <a href="http://scipy-lectures.org/advanced/image_processing/">this</a>. Knowing that an image can be represented as a matrix (or a <code>numpy array</code>) greatly helps us as almost every transformation of the image can be represented in terms of matrix maths.</p>
<p>To prove my point, let&rsquo;s look at <code>img</code> a little.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1">## Let&#39;s check the type of img</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">img</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># &lt;class &#39;numpy.ndarray&#39;&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## The shape of the array img</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">img</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># (32, 32, 4)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## The value of the first pixel of img</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">img</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="c1"># [128 144 117 255]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## Let&#39;s view the color of the first pixel</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">color</span> <span class="o">=</span> <span class="n">img</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">/</span> <span class="mf">255.0</span>  <span class="c1">##RGBA only accepts values in the 0-1 range</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">fill</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="n">color</span><span class="p">)</span></span></span></code></pre>
</div>
<p>That should give you a square filled with the color of the first pixel of <code>img</code>.</p>
<p><img src="/matplotlib/emoji-mosaic-art/first_pixel.png" alt="img[0][0]" title="The first pixel of the image we read in"></p>
<h2 id="methodology">Methodology<a class="headerlink" href="#methodology" title="Link to this heading">#</a></h2>
<p>We want to go from a plain image to an image full of emojis - or in other words, <strong>an image of images</strong>. Essentially, we&rsquo;re going to replace all pixels with emojis. However, to ensure that our new emoji-image looks like the original image and not just random smiley faces, the trick is to make sure that <em>every pixel is replaced my an emoji which has similar color to that pixel</em>. That&rsquo;s what gives the result the look of a mosaic.</p>
<p>&lsquo;Similar&rsquo; really just means that the <strong>mean</strong> (median is also worth trying) color of the emoji should be close to the pixel it replaces.</p>
<p>So how do you find the mean color of an entire image? Easy. We just take all the RGBA arrays and average the Rs together, and then the Gs together, and then the Bs together, and then the As together (the As, by the way, are just all 1 in our case, so the mean is also going to be 1). Here&rsquo;s that idea expressed formally:</p>
<p>\[ (r, g, b){\mu}=\left(\frac{\left(r{1}+r_{2}+\ldots+r_{N}\right)}{N}, \frac{\left(g_{1}+g_{2}+\ldots+g_{N}\right)}{N}, \frac{\left(b_{1}+b_{2}+\ldots+b_{N}\right)}{N}\right) \]</p>
<p>The resulting color would be single array of RGBA values: \[ [r_{\mu}, g_{\mu}, b_{\mu}, 1] \]</p>
<p>So now our steps become somewhat like this:</p>
<p><strong>Part I</strong> - Get emoji matches</p>
<ol>
<li>Find a bunch of emojis.</li>
<li>Find the mean of the emojis.</li>
<li>For each pixel in the image, find the emoji closest to it (wrt color), and replace pixel with that emoji (say, E).</li>
</ol>
<p><strong>Part II</strong> - Reshape emojis to image</p>
<ol>
<li>Reshape the flattened array of all Es back to the shape of our image.</li>
<li>Concatenate all emojis into a single array (reduce dimensions).</li>
</ol>
<p>That&rsquo;s pretty much it!</p>
<h3 id="step-i1---our-emoji-bank">Step I.1 - Our Emoji bank<a class="headerlink" href="#step-i1---our-emoji-bank" title="Link to this heading">#</a></h3>
<p>I took care of this for you beforehand with a bit of BeautifulSoup and requests magic. Our emoji collection is a numpy array of shape <code>1506, 16, 16, 4</code> - that&rsquo;s 1506 emojis with each being a 16x16 array of RGBA values. You can find it <a href="https://github.com/sharmaabhishekk/emoji-mosaic-mpl">here</a>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">emoji_array</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s2">&#34;emojis_16.npy&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">emoji_array</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">## 1506, 16, 16, 4</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">##plt.imshow(emoji_array[0]) ##to view the first emoji</span></span></span></code></pre>
</div>
<h3 id="step-i2---calculate-the-mean-rgba-value-of-all-emojis">Step I.2 - Calculate the mean RGBA value of all emojis.<a class="headerlink" href="#step-i2---calculate-the-mean-rgba-value-of-all-emojis" title="Link to this heading">#</a></h3>
<p>We&rsquo;ve seen the formula above; here&rsquo;s the numpy code for it. We&rsquo;re gonna iterate over all all the 1506 emojis and create an array <code>emoji_mean_array</code> out of them.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">emoji_mean_array</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span><span class="n">ar</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span> <span class="k">for</span> <span class="n">ar</span> <span class="ow">in</span> <span class="n">emoji_array</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>  <span class="c1">##`np.median(ar, axis=(0,1))` for median instead of mean</span></span></span></code></pre>
</div>
<h3 id="step-i3---finding-closest-emoji-match-for-all-pixels">Step I.3 - finding closest emoji match for all pixels<a class="headerlink" href="#step-i3---finding-closest-emoji-match-for-all-pixels" title="Link to this heading">#</a></h3>
<p>The easiest way to do that would be use Scipy&rsquo;s <strong><code>KDTree</code></strong> to create a <code>tree</code> object of all average RGBA values we calculated in #2. This enables us to perform fast lookup for every pixel using the <code>query</code> method. Here&rsquo;s how the code for that looks -</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">tree</span> <span class="o">=</span> <span class="n">spatial</span><span class="o">.</span><span class="n">KDTree</span><span class="p">(</span><span class="n">emoji_mean_array</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">indices</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">flattened_img</span> <span class="o">=</span> <span class="n">img</span><span class="o">.</span><span class="n">reshape</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">img</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>  <span class="c1">##shape = [1024, 16, 16, 4]</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">pixel</span> <span class="ow">in</span> <span class="n">tqdm</span><span class="p">(</span><span class="n">flattened_img</span><span class="p">,</span> <span class="n">desc</span><span class="o">=</span><span class="s2">&#34;Matching emojis&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">_</span><span class="p">,</span> <span class="n">index</span> <span class="o">=</span> <span class="n">tree</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">pixel</span><span class="p">)</span>  <span class="c1">##returns distance and index of closest match.</span>
</span></span><span class="line"><span class="cl">    <span class="n">indices</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">index</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">emoji_matches</span> <span class="o">=</span> <span class="n">emoji_array</span><span class="p">[</span><span class="n">indices</span><span class="p">]</span>  <span class="c1">##our emoji_matches</span></span></span></code></pre>
</div>
<h3 id="step-ii1">Step II.1<a class="headerlink" href="#step-ii1" title="Link to this heading">#</a></h3>
<p>The final step is to reshape the array a little more to enable us to plot it using the imshow function. As you can see above, to loop over the pixels we had to flatten the image out into the <code>flattened_img</code>. Now we have to sort of un-flatten it back; to make sure it&rsquo;s back in the form of an image. Fortunately, using numpy&rsquo;s <code>reshape</code> function makes this easy.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">resized_ar</span> <span class="o">=</span> <span class="n">emoji_matches</span><span class="o">.</span><span class="n">reshape</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">dim</span><span class="p">,</span> <span class="n">dim</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>  <span class="c1">##dim is what we got earlier when we read in the image</span></span></span></code></pre>
</div>
<h3 id="step-ii2">Step II.2<a class="headerlink" href="#step-ii2" title="Link to this heading">#</a></h3>
<p>The last bit is the trickiest. The problem with the output we&rsquo;ve got so far is that it&rsquo;s too nested. Or in simpler terms, what we have is a image where every individual pixel is itself an image. That&rsquo;s all fine but it&rsquo;s not valid input for imshow and if we try to pass it in, it tells us exactly that.</p>

<div class="highlight">
  <pre>TypeError: Invalid shape (32, 32, 16, 16, 4) for image data</pre>
</div>

<p>To grasp our problem intuitively, think about it this way. What we have right now are lots of images like these:</p>
<p><img src="/matplotlib/emoji-mosaic-art/chopped_face.png" alt="“Chopped raccoon img”" title="Image from Scipy under BSD License"></p>
<p>What we want is to merge them all together. Like so:</p>
<p><img src="/matplotlib/emoji-mosaic-art/rejoined_face.png" alt="“Rejoined raccoon img”"></p>
<p>To think about it slightly more technically, what we have right now is a <em>five</em> dimensional array. What we need is to rehshape it in such a way that it&rsquo;s - at maximum - <em>three</em> dimensional. However, it&rsquo;s not as easy as a simple <code>np.reshape</code> (I&rsquo;d suggest you go ahead and try that anyway).</p>
<p>Don&rsquo;t worry though, we have Stack Overflow to the rescue! This excellent <a href="https://stackoverflow.com/questions/52730668/concatenating-multiple-images-into-one/52733370#52733370">answer</a> does exactly that. You don&rsquo;t have to go through it, I have copied the relevant code in here.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">np_block_2D</span><span class="p">(</span><span class="n">chops</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Converts list of chopped images to one single image&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">block</span><span class="p">([[[</span><span class="n">x</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">row</span><span class="p">]</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">chops</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">final_img</span> <span class="o">=</span> <span class="n">np_block_2D</span><span class="p">(</span><span class="n">resized_ar</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">final_img</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">## (512, 512, 4)</span></span></span></code></pre>
</div>
<p>The shape looks correct enough. Let&rsquo;s try to plot it.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">final_img</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/emoji-mosaic-art/final_image.png" alt="“Emoji Mosaic final_img”"></p>
<p><strong>Et Voilà</strong></p>
<p>Of course, the result looks a little <em>meh</em> but that&rsquo;s because we only used 32x32 emojis. Here&rsquo;s what the same code would do with 10000 emojis (100x100).</p>
<p><img src="/matplotlib/emoji-mosaic-art/final_image_100.png" alt="“Emoji Mosaic full_size”"></p>
<p>Better?</p>
<p>Now, let&rsquo;s try and create nine of these emoji-images and grid them together.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">canvas</span><span class="p">(</span><span class="n">gray_scale_img</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="cl"><span class="s2">    Plot a 3x3 matrix of the images using different colormaps
</span></span></span><span class="line"><span class="cl"><span class="s2">        param gray_scale_img: a square gray_scale_image
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="p">,</span> <span class="n">axes</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="n">nrows</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">ncols</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">13</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">axes</span> <span class="o">=</span> <span class="n">axes</span><span class="o">.</span><span class="n">flatten</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">cmaps</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;BuPu_r&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;bone&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;CMRmap&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;magma&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;afmhot&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;ocean&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;inferno&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;PuRd_r&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;gist_gray&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">cmap</span><span class="p">,</span> <span class="n">ax</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">cmaps</span><span class="p">,</span> <span class="n">axes</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">cmapper</span> <span class="o">=</span> <span class="n">cm</span><span class="o">.</span><span class="n">get_cmap</span><span class="p">(</span><span class="n">cmap</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">rgba_image</span> <span class="o">=</span> <span class="n">cmapper</span><span class="p">(</span><span class="n">gray_scale_img</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">single_plot</span><span class="p">(</span><span class="n">rgba_image</span><span class="p">,</span> <span class="n">ax</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># ax.imshow(rgba_image) ##try this if you just want to plot the plain image in different color spaces, comment the single_plot call above</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">set_axis_off</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">plt</span><span class="o">.</span><span class="n">subplots_adjust</span><span class="p">(</span><span class="n">hspace</span><span class="o">=</span><span class="mf">0.0</span><span class="p">,</span> <span class="n">wspace</span><span class="o">=-</span><span class="mf">0.2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">fig</span><span class="p">,</span> <span class="n">axes</span></span></span></code></pre>
</div>
<p>The code does mostly the same stuff as before. To get the different colours, I used a simple hack. I first converted the image to grayscale and then used 9 different colormaps on it. Then I used the RGB values returned by the colormap to get the absolute values for our new input image. After that, the only part left is to just feed the new input image through the pipeline we&rsquo;ve discussed so far and that gives us our emoji-image.</p>
<p>Here&rsquo;s what that looks like:</p>
<p><img src="/matplotlib/emoji-mosaic-art/final_3x3_tile.png" alt="“Emoji Mosaic 3x3_grid”"></p>
<p><em>Pretty</em></p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Link to this heading">#</a></h2>
<p>Some final thoughts to wrap this up.</p>
<ul>
<li>
<p>I&rsquo;m not sure if my way to get different colours using different cmaps is what people usually do. I&rsquo;m almost certain there&rsquo;s a better way and if you know one, please submit a PR to the repo (link below).</p>
</li>
<li>
<p>Iterating over every pixel is not really the best idea. We got away with it since it&rsquo;s just 1024 (32x32) pixels but for images with higher resolution, we&rsquo;d have to either iterate over grids of images at once (say a 3x3 or 2x2 window) or resize the image itself to a more workable shape. I prefer the latter since that way we can also just resize it to a square shape in the same call which also has the additional advantage of fitting in nicely in our 3x3 mosaic. I&rsquo;ll leave the readers to work that out themselves using numpy (and, no, please don&rsquo;t use <code>cv2.resize</code>).</p>
</li>
<li>
<p>The <code>KDTree</code> was not part of my initial code. Initially, I&rsquo;d just looped over every emoji for every pixel and then calculated the Euclidean distance (using <code>np.linalg.norm(a-b)</code>). As you can probably imagine, the nested loop in there slowed down the code tremendously - even a 32x32 emoji-image took around 10 minutes to run - right now the same code takes ~19 seconds. Guess that&rsquo;s the power of vectorization for you all.</p>
</li>
<li>
<p>It&rsquo;s worth messing around with median instead of mean to get the RGBA values of the emojis. Most emojis are circular in shape and hence there&rsquo;s a lot of space left outside the area of the circular region which sort of waters down the average color in turn watering down the end result. Considering the median might sort out this problem for some images which aren&rsquo;t very rich.</p>
</li>
<li>
<p>While I&rsquo;ve tried to go in a linear manner with (what I hope was) a good mix of explanation and code, I&rsquo;d strongly suggest looking at the full code in the repository <a href="https://github.com/sharmaabhishekk/emoji-mosaic-mpl">here</a> in case you feel like I sprung anything on you.</p>
</li>
</ul>
<hr>
<p>I hope you enjoyed this post and learned something from it. If you have any feedback, criticism, questions, please feel free to DM me on <a href="https://twitter.com/abhisheksh_98">Twitter</a> or email me (preferably the former since I&rsquo;m almost always on there). Thank you, and take care!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="art" label="art" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Draw all graphs of N nodes]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib Cyberpunk Style" />
                <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib for Making Diagrams" />
                <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="related" type="text/html" title="Create Ridgeplots in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="related" type="text/html" title="Create a Tesla Cybertruck That Drives" />
                <link href="https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/?utm_source=atom_feed" rel="related" type="text/html" title="An Inquiry Into Matplotlib&#39;s Figures" />
            
                <id>https://blog.scientific-python.org/matplotlib/draw-all-graphs-of-n-nodes/</id>
            
            
            <published>2020-05-07T09:05:32+01:00</published>
            <updated>2020-05-07T09:05:32+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>A fun project about drawing all possible differently-looking (not isomorphic) graphs of N nodes.</blockquote><p>The other day I was homeschooling my kids, and they asked me: &ldquo;Daddy, can you draw us all possible non-isomorphic graphs of 3 nodes&rdquo;? Or maybe I asked them that? Either way, we happily drew all possible graphs of 3 nodes, but already for 4 nodes it got hard, and for 5 nodes - <a href="https://www.graphclasses.org/smallgraphs.html#nodes5">plain impossible</a>!</p>
<p>So I thought: let me try to write a brute-force program to do it! I spent a few hours sketching some smart dynamic programming solution to generate these graphs, and went nowhere, as apparently the <a href="http://www.cs.columbia.edu/~cs4205/files/CM9.pdf">problem is quite hard</a>. I gave up, and decided to go with a naive approach:</p>
<ol>
<li>Generate all graphs of N nodes, even if some of them look the same (are isomorphic). For \(N\) nodes, there are \(\frac{N(N-1)}{2}\) potential edges to connect these nodes, so it&rsquo;s like generating a bunch of binary numbers. Simple!</li>
<li>Write a program to tell if two graphs are isomorphic, then remove all duplicates, unworthy of being presented in the final picture.</li>
</ol>
<p>This strategy seemed more reasonable, but writing a &ldquo;graph-comparator&rdquo; still felt like a cumbersome task, and more importantly, this part would itself be slow, as I&rsquo;d still have to go through a whole tree of options for every graph comparison. So after some more head-scratching, I decided to simplify it even further, and use the fact that these days the memory is cheap:</p>
<ol>
<li>Generate all possible graphs (some of them totally isomorphic, meaning that they would look as a repetition if plotted on a figure)</li>
<li>For each graph, generate its &ldquo;description&rdquo; (like an <a href="https://en.wikipedia.org/wiki/Adjacency_matrix">adjacency matrix</a>, of an edge list), and check if a graph with this description is already on the list. If yes, skip it, we got its portrait already!</li>
<li>If however the graph is unique, include it in the picture, and also generate all possible &ldquo;descriptions&rdquo; of it, up to node permutation, and add them to the hash table. To make sure no other graph of this particular shape would ever be included in our pretty picture again.</li>
</ol>
<p>For the first task, I went with the edge list, which made the task identical to <a href="https://www.geeksforgeeks.org/generate-all-the-binary-strings-of-n-bits/">generating all binary numbers</a> of length \(\frac{N(N-1)}{2}\) with a recursive function, except instead of writing zeroes you skip edges, and instead of writing ones, you include them. Below is the function that does the trick, and has an additional bonus of listing all edges in a neat orderly way. For every edge \(i \rightarrow j\) we can be sure that \(i\) is lower than \(j\), and also that edges are sorted as words in a dictionary. Which is good, as it restricts the set of possible descriptions a bit, which will simplify our life later.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Make a graph recursively, by either including, or skipping each edge.
</span></span></span><span class="line"><span class="cl"><span class="s2">    Edges are given in lexicographical order by construction.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">out</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">i</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>  <span class="c1"># First call</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">=</span> <span class="p">[[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span> <span class="o">+</span> <span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="mi">1</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">    <span class="k">elif</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">+=</span> <span class="p">[[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span> <span class="o">+</span> <span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">+=</span> <span class="p">[</span><span class="n">r</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">    <span class="k">elif</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">=</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="o">=</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="o">=</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span> <span class="o">=</span> <span class="p">[[]]</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">out</span></span></span></code></pre>
</div>
<p>If you run this function for a small number of nodes (say, \(N=3\)), you can see how it generates all possible graph topologies, but that some of the descriptions would actually lead to identical pictures, if drawn (graphs 2 and 3 in the list below).</p>

<div class="highlight">
  <pre>[(0, 1), (0, 2), (1, 2)]
[(0, 1), (0, 2)]
[(0, 1), (1, 2)]
[(0, 1)]</pre>
</div>

<p>Also, while building a graph from edges means that we&rsquo;ll never get lonely unconnected points, we can get graphs that are smaller than \(n\) nodes (the last graph in the list above), or graphs that have unconnected parts. It is impossible for \(n=3\), but starting with \(n=4\) we would get things like <code>[(0,1), (2,3)]</code>, which is technically a graph, but you cannot exactly wear it as a piece of jewelry, as it would fall apart. So at this point I decided to only visualize fully connected graphs of exactly \(n\) vertices.</p>
<p>To continue with the plan, we now need to make a function that for every graph would generate a family of its &ldquo;alternative representations&rdquo; (given the constraints of our generator), to make sure duplicates would not slip under the radar. First we need a permutation function, to permute the nodes (you could also use a built-in function in <code>numpy</code>, but coding this one from scratch is always fun, isn&rsquo;t it?). Here&rsquo;s the permutation generator:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">perm</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;All permutations of n elements.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">s</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">perm</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">s</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">[[]]</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">[[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">p</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">s</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">perm</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">([</span><span class="n">k</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">s</span> <span class="k">if</span> <span class="n">k</span> <span class="o">!=</span> <span class="n">i</span><span class="p">]))]</span></span></span></code></pre>
</div>
<p>Now, for any given graph description, we can permute its nodes, sort the \(i,j\) within each edge, sort the edges themselves, remove duplicate alt-descriptions, and remember the list of potential impostors:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">permute</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Create a set of all possible isomorphic codes for a graph,
</span></span></span><span class="line"><span class="cl"><span class="s2">    as nice hashable tuples. All edges are i&lt;j, and sorted lexicographically.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">ps</span> <span class="o">=</span> <span class="n">perm</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">out</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([])</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">ps</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">out</span><span class="o">.</span><span class="n">add</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="nb">tuple</span><span class="p">(</span><span class="nb">sorted</span><span class="p">([(</span><span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="k">if</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="k">else</span> <span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">p</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">g</span><span class="p">]))</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="n">out</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Say, for an input description of <code>[(0, 1), (0, 2)]</code>, the function above returns three &ldquo;synonyms&rdquo;:</p>

<div class="highlight">
  <pre>((0, 1), (1, 2))
((0, 1), (0, 2))
((0, 2), (1, 2))</pre>
</div>

<p>I suspect there should be a neater way to code that, to avoid using the <code>list → set → list</code> pipeline to get rid of duplicates, but hey, it works!</p>
<p>At this point, the only thing that&rsquo;s missing is the function to check whether the graph comes in one piece, which happens to be a famous and neat algorithm called the &ldquo;<a href="https://en.wikipedia.org/wiki/Disjoint-set_data_structure">Union-Find</a>&rdquo;. I won&rsquo;t describe it here in detail, but in short, it goes though all edges and connects nodes to each other in a special way; then counts how many separate connected components (like, chunks of the graph) remain in the end. If all nodes are in one chunk, we like it. If not, I don&rsquo;t want to see it in my pictures!</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">connected</span><span class="p">(</span><span class="n">g</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Check if the graph is fully connected, with Union-Find.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">nodes</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">g</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">e</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="n">roots</span> <span class="o">=</span> <span class="p">{</span><span class="n">node</span><span class="p">:</span> <span class="n">node</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">nodes</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">_root</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">node</span> <span class="o">==</span> <span class="n">roots</span><span class="p">[</span><span class="n">node</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">depth</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="n">_root</span><span class="p">(</span><span class="n">roots</span><span class="p">[</span><span class="n">node</span><span class="p">],</span> <span class="n">depth</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">g</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">ri</span><span class="p">,</span> <span class="n">di</span> <span class="o">=</span> <span class="n">_root</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">rj</span><span class="p">,</span> <span class="n">dj</span> <span class="o">=</span> <span class="n">_root</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">ri</span> <span class="o">==</span> <span class="n">rj</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">di</span> <span class="o">&lt;=</span> <span class="n">dj</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">roots</span><span class="p">[</span><span class="n">ri</span><span class="p">]</span> <span class="o">=</span> <span class="n">rj</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">roots</span><span class="p">[</span><span class="n">rj</span><span class="p">]</span> <span class="o">=</span> <span class="n">ri</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">([</span><span class="n">_root</span><span class="p">(</span><span class="n">node</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">nodes</span><span class="p">]))</span> <span class="o">==</span> <span class="mi">1</span></span></span></code></pre>
</div>
<p>Now we can finally generate the &ldquo;overkill&rdquo; list of graphs, filter it, and plot the pics:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">filter</span><span class="p">(</span><span class="n">gs</span><span class="p">,</span> <span class="n">target_nv</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Filter all improper graphs: those with not enough nodes,
</span></span></span><span class="line"><span class="cl"><span class="s2">    those not fully connected, and those isomorphic to previously considered.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">mem</span> <span class="o">=</span> <span class="nb">set</span><span class="p">({})</span>
</span></span><span class="line"><span class="cl">    <span class="n">gs2</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">gs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">nv</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">g</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">e</span><span class="p">]))</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">nv</span> <span class="o">!=</span> <span class="n">target_nv</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="ow">not</span> <span class="n">connected</span><span class="p">(</span><span class="n">g</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">g</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">mem</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">gs2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">mem</span> <span class="o">|=</span> <span class="nb">set</span><span class="p">(</span><span class="n">permute</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">target_nv</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">gs2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Main body</span>
</span></span><span class="line"><span class="cl"><span class="n">NV</span> <span class="o">=</span> <span class="mi">6</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">make_graphs</span><span class="p">(</span><span class="n">NV</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="n">gs</span><span class="p">,</span> <span class="n">NV</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plot_graphs</span><span class="p">(</span><span class="n">gs</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">dotsize</span><span class="o">=</span><span class="mi">20</span><span class="p">)</span></span></span></code></pre>
</div>
<p>For plotting the graphs I wrote a small wrapper for the MatPlotLib-based NetworkX visualizer, splitting the figure into lots of tiny little facets using Matplotlib <code>subplot</code> command. &ldquo;Kamada-Kawai&rdquo; layout below is a <a href="https://en.wikipedia.org/wiki/Force-directed_graph_drawing">popular and fast version of a spring-based layout</a>, that makes the graphs look really nice.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">plot_graphs</span><span class="p">(</span><span class="n">graphs</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">dotsize</span><span class="o">=</span><span class="mi">20</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Utility to plot a lot of graphs from an array of graphs.
</span></span></span><span class="line"><span class="cl"><span class="s2">    Each graphs is a list of edges; each edge is a tuple.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">graphs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="n">figsize</span><span class="p">,</span> <span class="n">figsize</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">patch</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="s2">&#34;white&#34;</span><span class="p">)</span>  <span class="c1"># To make copying possible (white background)</span>
</span></span><span class="line"><span class="cl">    <span class="n">k</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">plt</span><span class="o">.</span><span class="n">subplot</span><span class="p">(</span><span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">g</span> <span class="o">=</span> <span class="n">nx</span><span class="o">.</span><span class="n">Graph</span><span class="p">()</span>  <span class="c1"># Generate a Networkx object</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">graphs</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">            <span class="n">g</span><span class="o">.</span><span class="n">add_edge</span><span class="p">(</span><span class="n">e</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">e</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">        <span class="n">nx</span><span class="o">.</span><span class="n">draw_kamada_kawai</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">node_size</span><span class="o">=</span><span class="n">dotsize</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;.&#34;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Here are the results. To build the anticipation, let&rsquo;s start with something trivial: all graphs of 3 nodes:</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/3nodes.png" alt="Two non isomorphic graphs with 3 nodes, the first graph connects all 3 nodes and creates a triangle. The second graph is a path graph with 3 nodes connected as a single path."></p>
<p>All graphs of 4 nodes:</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/4nodes.png" alt="All six possible non isomorphic graphs with 4 nodes. The first graph is a complete graph with all 4 nodes connected to each other. The second one is a complete graph with one edge removed. The third graph is a triangle graph with one node attached with one of the nodes in the graph. The fourth graph is a star graph, with one central node connected to the other 3 nodes. The fifth one is a graph where the edges form a square. The sixth one is a path graph which connects all 4 nodes as a single path."></p>
<p>All graphs of 5 nodes:</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/5nodes.png" alt="All 21 possibilities of non isomorphic graphs with 5 nodes. The different graphs show multiple possible structures from a complete graph of 5 nodes to a path graph of 5 nodes. Other structures present in this collection of graphs show a pentagon shaped graph, a star graph and others."></p>
<p>Generating figures above is of course all instantaneous on a decent computer, but for 6 nodes (below) it takes a few seconds:</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/6nodes.png" alt="All 112 possibilities of non isomorphic graphs with 6 nodes. The different graphs show multiple possible structures from a complete graph of 6 nodes to a path graph of 6 nodes. Other structures present in this collection of graphs show a hexagon shaped graph, a star graph, two complete graphs with 4 nodes stacked on top of each other with the two complete 4 graphs sharing an edge and 107 other structures!"></p>
<p>For 7 nodes (below) it takes about 5-10 minutes. It&rsquo;s easy to see why: the brute-force approach generates all \(2^{\frac{n(n-1)}{2}}\) possible graphs, which means that the number of operations grows exponentially! Every increase of \(n\) by one, gives us \(n-1\) new edges to consider, which means that the time to run the program increases by \(~2^{n-1}\). For \(n=7\) it brought me from seconds to minutes, for \(n=8\) it would have shifted me from minutes to hours, and for \(n=9\), from hours, to months of computation. Isn&rsquo;t it fun? We are all specialists in exponential growth these days, so here you are :)</p>
<p><img src="/matplotlib/draw-all-graphs-of-n-nodes/7nodes.png" alt="ALL 853 possibilities of non isomorphic graphs with 7 nodes. The different graphs show multiple possible structures from a complete graph of 7 nodes to a path graph of 7 nodes. Other structures present in this collection show many star and kite-shaped graphs."></p>
<p>The code is available as a <a href="https://github.com/khakhalin/Sketches/blob/master/classic/generate_all_graphs.ipynb">Jupyter Notebook on my GitHub</a>. I hope you enjoyed the pictures, and the read! Which of those charms above would bring most luck? Which ones seem best for divination? Let me know what you think! :)</p>
<p>Contact me via <a href="https://twitter.com/ampanmdagaba">Twitter</a> or <a href="https://github.com/khakhalin">Github</a>.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="graphs" label="graphs" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Sidharth Bansal joined as GSoC'20 intern]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/introductory-gsoc2020-post/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-rsef/?utm_source=atom_feed" rel="related" type="text/html" title="Elliott Sales de Andrade hired as Matplotlib Software Research Engineering Fellow" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib Cyberpunk Style" />
                <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib for Making Diagrams" />
                <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="related" type="text/html" title="Create Ridgeplots in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="related" type="text/html" title="Create a Tesla Cybertruck That Drives" />
            
                <id>https://blog.scientific-python.org/matplotlib/introductory-gsoc2020-post/</id>
            
            
            <published>2020-05-06T21:47:36+05:30</published>
            <updated>2020-05-06T21:47:36+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Introductory post about Sidharth Bansal, Google Summer of Code 2020 Intern for Baseline Image Problem Project under Numfocus</blockquote><p>When I, Sidharth Bansal, heard I got selected in Google Summer of Code(GSOC) 2020 with Matplotlib under Numfocus, I was jumping and dancing. In this post, I talk about my past experiences, how I got selected for GSOC with Matplotlib, and my project details.
I am grateful to the community :)</p>
<h2 id="about-me">About me:<a class="headerlink" href="#about-me" title="Link to this heading">#</a></h2>
<p>I am currently pursuing a Bachelor’s in Technology in Software Engineering at Delhi Technological University, Delhi, India. I started my journey of open source with Public Lab, an open-source organization as a full-stack Ruby on Rails web developer. I initially did the Google Summer of Code there. I built a Multi-Party Authentication System which involves authentication of the user through multiple websites linked like mapknitter.org and spectralworkbench.org with OmniAuth providers like Facebook, twitter, google, and Github. I also worked on a Multi-Tag Subscription project there. It involved tag/category subscription by the user so that users will be notified of subsequent posts in the category they subscribe to earlier. I have also mentored there as for Google Code-In and GSoC last year. I also worked there as a freelancer.</p>
<p>Apart from this, I also successfully completed an internship in the Google Payments team at Google, India this year as a Software Engineering Intern. I built a PAN Collection Flow there. PAN(Taxation Number) information is collected from the user if the total amount claimed by the user through Scratch cards in the current financial year exceeds PAN_LIMIT. Triggered PAN UI at the time of scratching the reward. Enabled Paisa-Offers to uplift their limit to grant Scratch Cards after crossing PAN_LIMIT. Used different technologies like Java, Guice, Android, Spanner Queues, Protocol Buffers, JUnit, etc.</p>
<p>I also have a keen interest in Machine Learning and Natural Language Processing and have done a couple of projects at my university. I have researched on <code>Query Expansion using fuzzy logic</code>. I will be publishing it in some time. It involves the fuzzification of the traditional wordnet for query expansion.</p>
<p>Our paper <code>Experimental Comparison &amp; Scientometric Inspection of Research for Word Embeddings</code> got accepted in ESCI Journal and Springer LNN past week. It explains the ongoing trends in universal embeddings and compares them.</p>
<h2 id="getting-started-with-matplotlib">Getting started with matplotlib<a class="headerlink" href="#getting-started-with-matplotlib" title="Link to this heading">#</a></h2>
<p>I chose matplotlib as it is an organization with so much cool stuff relating to plotting. I have always wanted to work on such things. People are really friendly, always eager to help!</p>
<h2 id="taking-baby-steps">Taking Baby steps:<a class="headerlink" href="#taking-baby-steps" title="Link to this heading">#</a></h2>
<p>The first step is getting involved with the community. I started using the Gitter channel to know about the maintainers. I started learning the different pieces which tie up for the baseline image problem. I started with learning the system architecture of matplotlib. Then I installed the matplotlib, learned the cool tech stack related to matplotlib like sphinx, python, pypi etc.</p>
<h2 id="keep-on-contributing-and-keep-on-learning">Keep on contributing and keep on learning:<a class="headerlink" href="#keep-on-contributing-and-keep-on-learning" title="Link to this heading">#</a></h2>
<p>Learning is a continuous task. Taking guidance from mentors about the various use case scenarios involved in the GSoC project helped me to gain a lot of insights. I solved a couple of small issues. I learned about the code-review process followed here, sphinx documentation, how releases work. I did <a href="https://github.com/matplotlib/matplotlib/pulls?q=is%3Apr&#43;author%3ASidharthBansal&#43;is%3Aclosed">some PRs</a>. It was a great learning experience.</p>
<h2 id="about-the-project">About the Project:<a class="headerlink" href="#about-the-project" title="Link to this heading">#</a></h2>
<p><a href="https://github.com/matplotlib/matplotlib/issues/16447">The project</a> is about the generation of baseline images instead of downloading them. The baseline images are problematic because they cause the repo size to grow rather quickly by adding more baseline images. Also, the baseline images force matplotlib contributors to pin to a somewhat old version of FreeType because nearly every release of FreeType causes tiny rasterization changes that would entail regenerating all baseline images. Thus, it causes even more repository size growth.
The idea is not to store the baseline images at all in the Github repo. It involves dividing the matplotlib package into two separate packages - mpl-test and mpl-notest. Mpl-test will have test suite and related information. The functionality of mpl plotting library will be present in mpl-notest. We will then create the logic for generating and grabbing the latest release. Some caching will be done too. We will then implement an analogous strategy to the CI.</p>
<p><strong>Mentor</strong> <a href="https://github.com/anntzer">Antony Lee</a></p>
<p>Thanks a lot for reading….having a great time coding with great people at Matplotlib. I will be right back with my work progress in subsequent posts.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="gsoc" label="GSoC" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Matplotlib Cyberpunk Style]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib for Making Diagrams" />
                <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="related" type="text/html" title="Create Ridgeplots in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="related" type="text/html" title="Create a Tesla Cybertruck That Drives" />
                <link href="https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/?utm_source=atom_feed" rel="related" type="text/html" title="An Inquiry Into Matplotlib&#39;s Figures" />
                <link href="https://blog.scientific-python.org/matplotlib/custom-3d-engine/?utm_source=atom_feed" rel="related" type="text/html" title="Custom 3D engine in Matplotlib" />
            
                <id>https://blog.scientific-python.org/matplotlib/matplotlib-cyberpunk-style/</id>
            
            
            <published>2020-03-27T20:26:07+01:00</published>
            <updated>2020-03-27T20:26:07+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Futuristic neon glow for your next data visualization</blockquote><p><img src="/matplotlib/matplotlib-cyberpunk-style/figures/5.png" alt="A line graph styled with a dark background and neon glowing lines in the style of Cyberpunk."></p>
<h2 id="1---the-basis">1 - The Basis<a class="headerlink" href="#1---the-basis" title="Link to this heading">#</a></h2>
<p>Let&rsquo;s make up some numbers, put them in a Pandas dataframe and plot them:</p>
<pre><code>import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'A': [1, 3, 9, 5, 2, 1, 1],
                   'B': [4, 5, 5, 7, 9, 8, 6]})

df.plot(marker='o')
plt.show()
</code></pre>
<p><img src="/matplotlib/matplotlib-cyberpunk-style/figures/1.png" alt="A simple chart consisted of two lines, one blue line, and one orange line. The lines are on a white background."></p>
<h2 id="2---the-darkness">2 - The Darkness<a class="headerlink" href="#2---the-darkness" title="Link to this heading">#</a></h2>
<p>Not bad, but somewhat ordinary. Let&rsquo;s customize it by using Seaborn&rsquo;s dark style, as well as changing background and font colors:</p>
<pre><code>plt.style.use(&quot;seaborn-dark&quot;)

for param in ['figure.facecolor', 'axes.facecolor', 'savefig.facecolor']:
    plt.rcParams[param] = '#212946'  # bluish dark grey

for param in ['text.color', 'axes.labelcolor', 'xtick.color', 'ytick.color']:
    plt.rcParams[param] = '0.9'  # very light grey

ax.grid(color='#2A3459')  # bluish dark grey, but slightly lighter than background
</code></pre>
<p><img src="/matplotlib/matplotlib-cyberpunk-style/figures/2.png" alt="A simple chart with a dark background consisted of two lines: A is the blue line and B is the orange line."></p>
<h2 id="3---the-light">3 - The Light<a class="headerlink" href="#3---the-light" title="Link to this heading">#</a></h2>
<p>It looks more interesting now, but we need our colors to shine more against the dark background:</p>
<pre><code>fig, ax = plt.subplots()
colors = [
    '#08F7FE',  # teal/cyan
    '#FE53BB',  # pink
    '#F5D300',  # yellow
    '#00ff41', # matrix green
]
df.plot(marker='o', ax=ax, color=colors)
</code></pre>
<p><img src="/matplotlib/matplotlib-cyberpunk-style/figures/3.png" alt="A simple chart with a dark background consisted of two lines: A is the blue line and B is the purple line."></p>
<h2 id="4---the-glow">4 - The Glow<a class="headerlink" href="#4---the-glow" title="Link to this heading">#</a></h2>
<p>Now, how to get that neon look? To make it shine, we <em>redraw the lines multiple times</em>, with low alpha value and slightly increasing linewidth. The overlap creates the glow effect.</p>
<pre><code>n_lines = 10
diff_linewidth = 1.05
alpha_value = 0.03

for n in range(1, n_lines+1):

    df.plot(marker='o',
            linewidth=2+(diff_linewidth*n),
            alpha=alpha_value,
            legend=False,
            ax=ax,
            color=colors)
</code></pre>
<p><img src="/matplotlib/matplotlib-cyberpunk-style/figures/4.png" alt="A simple chart with a dark background consisted of two lines: A is the blue line and B is the purple line.  However, they have a neon look and are both glowing."></p>
<h2 id="5---the-finish">5 - The Finish<a class="headerlink" href="#5---the-finish" title="Link to this heading">#</a></h2>
<p>For some more fine tuning, we color the area below the line (via <code>ax.fill_between</code>) and adjust the axis limits.</p>
<p>Here&rsquo;s the full code:</p>
<pre><code>import pandas as pd
import matplotlib.pyplot as plt


plt.style.use(&quot;dark_background&quot;)

for param in ['text.color', 'axes.labelcolor', 'xtick.color', 'ytick.color']:
    plt.rcParams[param] = '0.9'  # very light grey

for param in ['figure.facecolor', 'axes.facecolor', 'savefig.facecolor']:
    plt.rcParams[param] = '#212946'  # bluish dark grey

colors = [
    '#08F7FE',  # teal/cyan
    '#FE53BB',  # pink
    '#F5D300',  # yellow
    '#00ff41',  # matrix green
]


df = pd.DataFrame({'A': [1, 3, 9, 5, 2, 1, 1],
                   'B': [4, 5, 5, 7, 9, 8, 6]})

fig, ax = plt.subplots()

df.plot(marker='o', color=colors, ax=ax)

# Redraw the data with low alpha and slightly increased linewidth:
n_shades = 10
diff_linewidth = 1.05
alpha_value = 0.3 / n_shades

for n in range(1, n_shades+1):

    df.plot(marker='o',
            linewidth=2+(diff_linewidth*n),
            alpha=alpha_value,
            legend=False,
            ax=ax,
            color=colors)

# Color the areas below the lines:
for column, color in zip(df, colors):
    ax.fill_between(x=df.index,
                    y1=df[column].values,
                    y2=[0] * len(df),
                    color=color,
                    alpha=0.1)

ax.grid(color='#2A3459')

ax.set_xlim([ax.get_xlim()[0] - 0.2, ax.get_xlim()[1] + 0.2])  # to not have the markers cut off
ax.set_ylim(0)

plt.show()
</code></pre>
<p><img src="/matplotlib/matplotlib-cyberpunk-style/figures/5.png" alt="A simple chart with a dark background consisted of two lines: A is the blue line and B is the purple line. However they are neon, both glow, and the area below them glows as well."></p>
<p>If this helps you or if you have constructive criticism, I&rsquo;d be happy to hear about it! Please contact me via <a href="https://dhaitz.github.io">here</a> or <a href="https://twitter.com/d_haitz">here</a>. Thanks!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Elliott Sales de Andrade hired as Matplotlib Software Research Engineering Fellow]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/matplotlib-rsef/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib for Making Diagrams" />
                <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="related" type="text/html" title="Create Ridgeplots in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="related" type="text/html" title="Create a Tesla Cybertruck That Drives" />
                <link href="https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/?utm_source=atom_feed" rel="related" type="text/html" title="An Inquiry Into Matplotlib&#39;s Figures" />
                <link href="https://blog.scientific-python.org/matplotlib/custom-3d-engine/?utm_source=atom_feed" rel="related" type="text/html" title="Custom 3D engine in Matplotlib" />
            
                <id>https://blog.scientific-python.org/matplotlib/matplotlib-rsef/</id>
            
            
            <published>2020-03-20T15:51:00-04:00</published>
            <updated>2020-03-20T15:51:00-04:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>We have hired Elliott Sales de Andrade as the Matplotlib Software Research Engineering Fellow supported by the Chan Zuckerberg Initiative Essential Open Source Software for Science</blockquote><p>As has been discussed in detail in Nadia Eghbal&rsquo;s <a href="https://www.fordfoundation.org/work/learning/research-reports/roads-and-bridges-the-unseen-labor-behind-our-digital-infrastructure/">Roads and Bridges</a>, the CZI EOSS <a href="https://chanzuckerberg.com/rfa/essential-open-source-software-for-science/">program
announcement</a>, and in the NumFocus <a href="https://numfocus.org/programs/sustainability">sustainability program goals</a>, much of the critical software that science and industry are built on
is maintained by a primarily volunteer community. While this has worked, it is not sustainable in the long term for the health of many
projects or their contributors.</p>
<p>We are happy to announce that we have hired Elliott Sales de Andrade (<a href="https://github.com/QuLogic">QuLogic</a>)
as the <a href="https://github.com/matplotlib/CZI_2019-07_mpl">Matplotlib Software Research Engineering
Fellow</a> supported by
the <a href="https://chanzuckerberg.com/eoss/proposals/matplotlib-foundation-of-scientific-visualization-in-python/">Chan Zuckerberg Initiative Essential Open Source Software for
Science</a>
effective March 1, 2020!</p>
<p>Elliott has been contributing to a broad variety of Free and Open
Source projects for several years. He is an active Matplotlib
contributor and has had commit rights since October 2015. In addition
to working on Matplotlib, Elliott has contributed to a wide range of
projects in the Scientific Python software stack, both downstream and
upstream of Matplotlib, including
<a href="https://scitools.org.uk/cartopy/">Cartopy</a>,
<a href="https://obspy.org/">ObsPy</a>, and <a href="https://numpy.org/">NumPy</a>. Outside
of Python, Elliott is a developer on the <a href="https://pidgin.im/">Pidgin
project</a> and a packager for <a href="https://getfedora.org/">Fedora
Linux</a>. In his work on Matplotlib, he is interested in advancing
science through reproducible workflows and more accessible libraries.</p>
<p>We are already seeing a reduction in the backlog of open issues and
pull requests, which we hope will make the library easier to
contribute to and maintain long term. We also benefit from Elliott
having the bandwidth to maintain a library wide view of all the
on-going work and open bugs. Hiring Elliott as an RSEF is the
start of ensuring that Matplotlib is sustainable in the long term.</p>
<p>Looking forward to all the good work we are going to do this year!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="news" label="News" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Matplotlib for Making Diagrams]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="related" type="text/html" title="Create Ridgeplots in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="related" type="text/html" title="Create a Tesla Cybertruck That Drives" />
                <link href="https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/?utm_source=atom_feed" rel="related" type="text/html" title="An Inquiry Into Matplotlib&#39;s Figures" />
                <link href="https://blog.scientific-python.org/matplotlib/custom-3d-engine/?utm_source=atom_feed" rel="related" type="text/html" title="Custom 3D engine in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="related" type="text/html" title="Creating the Warming Stripes in Matplotlib" />
            
                <id>https://blog.scientific-python.org/matplotlib/mpl-for-making-diagrams/</id>
            
            
            <published>2020-02-19T12:57:07-05:00</published>
            <updated>2020-02-19T12:57:07-05:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>How to use Matplotlib to make diagrams.</blockquote><h1 id="matplotlib-for-diagrams">Matplotlib for diagrams<a class="headerlink" href="#matplotlib-for-diagrams" title="Link to this heading">#</a></h1>
<p>This is my first post for the Matplotlib blog so I wanted to lead
with an example of what I most love about it:
How much control Matplotlib gives you.
I like to use it as a programmable drawing tool that happens
to be good at plotting data.</p>
<p>The default layout for Matplotlib works great for a lot of things,
but sometimes you want to exert
more control. Sometimes you want to treat your figure window as
a blank canvas and create diagrams
to communicate your ideas. Here, we will walk through the process
for setting this up. Most of these tricks are detailed in
<a href="https://e2eml.school/matplotlib_framing.html">this cheat sheet for laying out plots</a>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span></span></span></code></pre>
</div>
<p>The first step is to choose the size of your canvas.</p>
<p>(Just a heads up, I love the metaphor
of the canvas, so that&rsquo;s how I am using the term here.
The Canvas object is a very specific
thing in the Matplotlib code base. That&rsquo;s not what I&rsquo;m referring to.)</p>
<p>I&rsquo;m planning to make a diagram that is 16 centimeters wide
and 9 centimeters high.
This will fit comfortably on a piece of A4 or US Letter paper
and will be almost twice as wide as it is high.
It also scales up nicely to fit on a wide-format slide presentation.</p>
<p>The <code>plt.figure()</code> function accepts a <code>figsize</code> argument,
a tuple of <code>(width, height)</code> in <strong>inches</strong>.
To convert from centimeters, we&rsquo;ll divide by 2.54.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig_width</span> <span class="o">=</span> <span class="mi">16</span>  <span class="c1"># cm</span>
</span></span><span class="line"><span class="cl"><span class="n">fig_height</span> <span class="o">=</span> <span class="mi">9</span>  <span class="c1"># cm</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="n">fig_width</span> <span class="o">/</span> <span class="mf">2.54</span><span class="p">,</span> <span class="n">fig_height</span> <span class="o">/</span> <span class="mf">2.54</span><span class="p">))</span></span></span></code></pre>
</div>
<p>The next step is to add an Axes object that we can draw on.
By default, Matplotlib will size and place the Axes to leave
a little border and room for x- and y-axis labels. However, we don&rsquo;t
want that this time around. We want our Axes to extend right up
to the edge of the Figure.</p>
<p>The <code>add_axes()</code> function lets us specify exactly where to place
our new Axes and how big to make it. It accepts a tuple of the format
<code>(left, bottom, width, height)</code>. The coordinate frame of the Figure
is always (0, 0) at the bottom left corner and (1, 1) at the upper right,
no matter what size of Figure you are working with. Positions, widths,
and heights all become fractions of the total width and height of the Figure.</p>
<p>To fill the Figure with our Axes entirely, we specify a left position of 0,
a bottom position of 0, a width of 1, and a height of 1.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span></span></span></code></pre>
</div>
<p>To make our diagram creation easier, we can set the axis limits so that
one unit in the figure equals one centimeter. This grants us
an intuitive way to control the size of objects in the diagram.
A circle with a radius of 2 will be drawn as a circle (not an ellipse)
in the final image and have a radius of 2 cm.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">fig_width</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">fig_height</span><span class="p">)</span></span></span></code></pre>
</div>
<p>We can also do away with the automatically generated ticks
and tick labels with this pair of calls.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">bottom</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">top</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">left</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">labelbottom</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">labeltop</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">labelleft</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">labelright</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span></span></span></code></pre>
</div>
<p>At this point we have a big blank space of exactly the right size and shape.
Now we can begin building our diagram. The foundation of the image will be
the background color. White is fine, but sometimes it&rsquo;s fun to mix it up.
<a href="https://e2eml.school/matplotlib_lines.html#color">Here are some ideas</a>
to get you started.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="s2">&#34;antiquewhite&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>We can also add a border to the diagram to visually set it apart.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;top&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="s2">&#34;midnightblue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;bottom&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="s2">&#34;midnightblue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;left&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="s2">&#34;midnightblue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;right&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="s2">&#34;midnightblue&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;top&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;bottom&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;left&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;right&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Now we have a foundation and background in place
and we&rsquo;re finally ready to start drawing.
You have complete freedom to
<a href="https://e2eml.school/matplotlib_lines.html">draw curves and shapes</a>,
<a href="https://e2eml.school/matplotlib_points.html">place points</a>,
and <a href="https://e2eml.school/matplotlib_text.html">add text</a>
of any variety within our 16 x 9 garden walls.</p>
<p>Then when you&rsquo;re done, the last step is to save the figure out as a
<code>.png</code> file. In this format it can be imported to and added to whatever
document or presentation you&rsquo;re working on</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">savefig</span><span class="p">(</span><span class="s2">&#34;blank_diagram.png&#34;</span><span class="p">,</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">300</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/mpl-for-making-diagrams/blank_diagram.png" alt="Blank diagram example."></p>
<p>If you&rsquo;re making a collection of diagrams,
you can make a convenient template for your blank canvas.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">blank_diagram</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig_width</span><span class="o">=</span><span class="mi">16</span><span class="p">,</span> <span class="n">fig_height</span><span class="o">=</span><span class="mi">9</span><span class="p">,</span> <span class="n">bg_color</span><span class="o">=</span><span class="s2">&#34;antiquewhite&#34;</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;midnightblue&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="n">fig_width</span> <span class="o">/</span> <span class="mf">2.54</span><span class="p">,</span> <span class="n">fig_height</span> <span class="o">/</span> <span class="mf">2.54</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">((</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">fig_width</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">fig_height</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="n">bg_color</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">bottom</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">top</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">left</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">labelbottom</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">labeltop</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">labelleft</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">labelright</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;top&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="n">color</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;bottom&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="n">color</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;left&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="n">color</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;right&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_color</span><span class="p">(</span><span class="n">color</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;top&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;bottom&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;left&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">spines</span><span class="p">[</span><span class="s2">&#34;right&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">fig</span><span class="p">,</span> <span class="n">ax</span></span></span></code></pre>
</div>
<p>Then you can take that canvas and add arbitrary text, shapes, and lines.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">blank_diagram</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">x0</span> <span class="ow">in</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="n">x0</span><span class="p">,</span> <span class="n">x0</span> <span class="o">+</span> <span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">9</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">savefig</span><span class="p">(</span><span class="s2">&#34;stripes.png&#34;</span><span class="p">,</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">300</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/mpl-for-making-diagrams/stripes.png" alt="White rectangle with black stripes."></p>
<p>Or more intricately:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">blank_diagram</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">centers</span> <span class="o">=</span> <span class="p">[(</span><span class="mf">3.5</span><span class="p">,</span> <span class="mf">6.5</span><span class="p">),</span> <span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mf">6.5</span><span class="p">),</span> <span class="p">(</span><span class="mf">12.5</span><span class="p">,</span> <span class="mf">6.5</span><span class="p">),</span> <span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mf">2.5</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl"><span class="n">radii</span> <span class="o">=</span> <span class="mf">1.5</span>
</span></span><span class="line"><span class="cl"><span class="n">texts</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s2">&#34;My roommate&#34;</span><span class="p">,</span> <span class="s2">&#34;is a Philistine&#34;</span><span class="p">,</span> <span class="s2">&#34;and a boor&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s2">&#34;My roommate&#34;</span><span class="p">,</span> <span class="s2">&#34;ate the last&#34;</span><span class="p">,</span> <span class="s2">&#34;of the&#34;</span><span class="p">,</span> <span class="s2">&#34;cold cereal&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s2">&#34;I am really&#34;</span><span class="p">,</span> <span class="s2">&#34;really hungy&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s2">&#34;I&#39;m annoyed&#34;</span><span class="p">,</span> <span class="s2">&#34;at my roommate&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Draw circles with text in the center</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">center</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">centers</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">center</span>
</span></span><span class="line"><span class="cl">    <span class="n">theta</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">x</span> <span class="o">+</span> <span class="n">radii</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">theta</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">y</span> <span class="o">+</span> <span class="n">radii</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">theta</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="s2">&#34;midnightblue&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="n">x</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">y</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">texts</span><span class="p">[</span><span class="n">i</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">horizontalalignment</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">verticalalignment</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="s2">&#34;midnightblue&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Draw arrows connecting them</span>
</span></span><span class="line"><span class="cl"><span class="c1"># https://e2eml.school/matplotlib_text.html#annotate</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">centers</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">radii</span><span class="p">,</span> <span class="n">centers</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">centers</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">radii</span><span class="p">,</span> <span class="n">centers</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="n">arrowprops</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">arrowstyle</span><span class="o">=</span><span class="s2">&#34;-|&gt;&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">centers</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">radii</span><span class="p">,</span> <span class="n">centers</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">centers</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">radii</span><span class="p">,</span> <span class="n">centers</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="n">arrowprops</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">arrowstyle</span><span class="o">=</span><span class="s2">&#34;-|&gt;&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">centers</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mf">0.7</span> <span class="o">*</span> <span class="n">radii</span><span class="p">,</span> <span class="n">centers</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.7</span> <span class="o">*</span> <span class="n">radii</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">centers</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.7</span> <span class="o">*</span> <span class="n">radii</span><span class="p">,</span> <span class="n">centers</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mf">0.7</span> <span class="o">*</span> <span class="n">radii</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="n">arrowprops</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">arrowstyle</span><span class="o">=</span><span class="s2">&#34;-|&gt;&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">annotate</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">centers</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.7</span> <span class="o">*</span> <span class="n">radii</span><span class="p">,</span> <span class="n">centers</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mf">0.7</span> <span class="o">*</span> <span class="n">radii</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="n">centers</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="mf">0.7</span> <span class="o">*</span> <span class="n">radii</span><span class="p">,</span> <span class="n">centers</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mf">0.7</span> <span class="o">*</span> <span class="n">radii</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="n">arrowprops</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">arrowstyle</span><span class="o">=</span><span class="s2">&#34;-|&gt;&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">savefig</span><span class="p">(</span><span class="s2">&#34;causal.png&#34;</span><span class="p">,</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">300</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/mpl-for-making-diagrams/causal.png" alt="A joke flow chart. The top level goes from left to right, and then both left and right edges lead to the bottom level. The top level is: 1. My roommate is a Philistine and a boor. 2. My roommate ate the last of the cold cereal. 3. I am really really hungry. The bottom level is: I’m annoyed at my roommate."></p>
<p>Once you get started on this path, you can start making
extravagantly annotated plots. It can elevate your data
presentations to true storytelling.</p>
<p>Happy diagram building!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Create Ridgeplots in Matplotlib]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="related" type="text/html" title="Create a Tesla Cybertruck That Drives" />
                <link href="https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/?utm_source=atom_feed" rel="related" type="text/html" title="An Inquiry Into Matplotlib&#39;s Figures" />
                <link href="https://blog.scientific-python.org/matplotlib/custom-3d-engine/?utm_source=atom_feed" rel="related" type="text/html" title="Custom 3D engine in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="related" type="text/html" title="Creating the Warming Stripes in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-in-data-driven-seo/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib in Data Driven SEO" />
            
                <id>https://blog.scientific-python.org/matplotlib/create-ridgeplots-in-matplotlib/</id>
            
            
            <published>2020-02-15T09:50:16+01:00</published>
            <updated>2020-02-15T09:50:16+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>This post details how to leverage gridspec to create ridgeplots in Matplotlib</blockquote><h1 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Link to this heading">#</a></h1>
<p>This post will outline how we can leverage <a href="https://matplotlib.org/3.1.3/api/_as_gen/matplotlib.gridspec.GridSpec.html">gridspec</a> to create ridgeplots in Matplotlib. While this is a relatively straightforward tutorial, some experience working with sklearn would be beneficial. Naturally it being a <em>vast</em> undertaking, this will not be an sklearn tutorial, those interested can read through the docs <a href="https://scikit-learn.org/stable/user_guide.html">here</a>. However, I will use its <code>KernelDensity</code> module from <code>sklearn.neighbors</code>.</p>
<!--
# Contents
  - [Packages](#packages)
  - [Data](#data)
  - [GridSpec](gs1)
  - [Kernel Density Estimation](#kde)
  - [Overlapping Axes Objects](#gs2)
  - [Complete Snippet](#snippet)
 -->
<h3 id="packages">Packages <a id="packages"></a><a class="headerlink" href="#packages" title="Link to this heading">#</a></h3>

<div class="highlight">
  <pre>import pandas as pd
import numpy as np
from sklearn.neighbors import KernelDensity

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.gridspec as grid_spec</pre>
</div>

<h3 id="data">Data <a id="data"></a><a class="headerlink" href="#data" title="Link to this heading">#</a></h3>
<p>I&rsquo;ll be using some mock data I created. You can grab the dataset from GitHub <a href="https://github.com/petermckeever/mock-data/blob/master/datasets/mock-european-test-results.csv">here</a> if you want to play along. The data looks at aptitude test scores broken down by country, age, and sex.</p>

<div class="highlight">
  <pre>data = pd.read_csv(&#34;mock-european-test-results.csv&#34;)</pre>
</div>

<table>
  <thead>
      <tr>
          <th>country</th>
          <th>age</th>
          <th>sex</th>
          <th>score</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Italy</td>
          <td>21</td>
          <td>female</td>
          <td>0.77</td>
      </tr>
      <tr>
          <td>Spain</td>
          <td>20</td>
          <td>female</td>
          <td>0.87</td>
      </tr>
      <tr>
          <td>Italy</td>
          <td>24</td>
          <td>female</td>
          <td>0.39</td>
      </tr>
      <tr>
          <td>United Kingdom</td>
          <td>20</td>
          <td>female</td>
          <td>0.70</td>
      </tr>
      <tr>
          <td>Germany</td>
          <td>20</td>
          <td>male</td>
          <td>0.25</td>
      </tr>
      <tr>
          <td>&hellip;</td>
          <td></td>
          <td></td>
          <td></td>
      </tr>
  </tbody>
</table>
<h3 id="gridspec">GridSpec <a id="gs1"></a><a class="headerlink" href="#gridspec" title="Link to this heading">#</a></h3>
<p>GridSpec is a Matplotlib module that allows us easy creation of subplots. We can control the number of subplots, the positions, the height, width, and spacing between each. As a basic example, let&rsquo;s create a quick template. The key parameters we&rsquo;ll be focusing on are <code>nrows</code>, <code>ncols</code>, and <code>width_ratios</code>.</p>
<p><code>nrows</code>and <code>ncols</code> divide our figure into areas we can add axes to. <code>width_ratios</code>controls the width of each of our columns. If we create something like <code>GridSpec(2,2,width_ratios=[2,1])</code>, we are subsetting our figure into 2 rows, 2 columns, and setting our width ratio to 2:1, i.e., that the first column will take up two times the width of the figure.</p>
<p>What&rsquo;s great about GridSpec is that now we have created those subsets, we are not <em>bound</em> to them, as we will see below.</p>
<p><strong>Note</strong>: I am using my own theme, so plots will look different. Creating custom themes is outside the scope of this tutorial (but I may write one in the future).</p>

<div class="highlight">
  <pre>gs = (grid_spec.GridSpec(2,2,width_ratios=[2,1]))

fig = plt.figure(figsize=(8,6))

ax = fig.add_subplot(gs[0:1,0])
ax1 = fig.add_subplot(gs[1:,0])
ax2 = fig.add_subplot(gs[0:,1:])

ax_objs = [ax,ax1,ax2]
n = [&#34;&#34;,1,2]

i = 0
for ax_obj in ax_objs:
    ax_obj.text(0.5,0.5,&#34;ax{}&#34;.format(n[i]),
                ha=&#34;center&#34;,color=&#34;red&#34;,
                fontweight=&#34;bold&#34;,size=20)
    i &#43;= 1

plt.show()</pre>
</div>

<p><img src="/matplotlib/create-ridgeplots-in-matplotlib/basic_template.png" alt="This is a chart with 3 subplot labeled ax, ax1, and ax2. It was created using GridSpec."></p>
<p>I won&rsquo;t get into more detail about what everything does here. If you are interested in learning more about figures, axes, and gridspec, Akash Palrecha has <a href="../an-inquiry-into-matplotlib-figures/">written a very nice guide here</a>.</p>
<h3 id="kernel-density-estimation">Kernel Density Estimation <a id="kde"></a><a class="headerlink" href="#kernel-density-estimation" title="Link to this heading">#</a></h3>
<p>We have a couple of options here. The easiest by far is to stick with the pipes built into pandas. All that&rsquo;s needed is to select the column and add <code>plot.kde</code>. This defaults to a Scott bandwidth method, but you can choose a Silverman method, or add your own. Let&rsquo;s use GridSpec again to plot the distribution for each country. First we&rsquo;ll grab the unique country names and create a list of colors.</p>

<div class="highlight">
  <pre>countries = [x for x in np.unique(data.country)]
colors = [&#39;#0000ff&#39;, &#39;#3300cc&#39;, &#39;#660099&#39;, &#39;#990066&#39;, &#39;#cc0033&#39;, &#39;#ff0000&#39;]</pre>
</div>

<p>Next we&rsquo;ll loop through each country and color to plot our data. Unlike the above we will not explicitly declare how many rows we want to plot. The reason for this is to make our code more dynamic. If we set a specific number of rows and specific number of axes objects, we&rsquo;re creating inefficient code. This is a bit of an aside, but when creating visualizations, you should always aim to reduce and reuse. By reduce, we specifically mean lessening the number of variables we are declaring and the unnecessary code associated with that. We are plotting data for six countries, what happens if we get data for 20 countries? That&rsquo;s a lot of additional code. Related, by not explicitly declaring those variables we make our code adaptable and ready to be scripted to automatically create new plots when new data of the same kind becomes available.</p>

<div class="highlight">
  <pre>gs = (grid_spec.GridSpec(len(countries),1))

fig = plt.figure(figsize=(8,6))

i = 0

#creating empty list
ax_objs = []

for country in countries:
    # creating new axes object and appending to ax_objs
    ax_objs.append(fig.add_subplot(gs[i:i&#43;1, 0:]))

    # plotting the distribution
    plot = (data[data.country == country]
            .score.plot.kde(ax=ax_objs[-1],color=&#34;#f0f0f0&#34;, lw=0.5)
           )

    # grabbing x and y data from the kde plot
    x = plot.get_children()[0]._x
    y = plot.get_children()[0]._y

    # filling the space beneath the distribution
    ax_objs[-1].fill_between(x,y,color=colors[i])

    # setting uniform x and y lims
    ax_objs[-1].set_xlim(0, 1)
    ax_objs[-1].set_ylim(0,2.2)

    i &#43;= 1

plt.tight_layout()
plt.show()</pre>
</div>

<p><img src="/matplotlib/create-ridgeplots-in-matplotlib/grid_spec_distro.png" alt="6 kernel density estimate (KDE) charts, each with different shades ranging from blue to blood red."></p>
<p>We&rsquo;re not quite at ridge plots yet, but let&rsquo;s look at what&rsquo;s going on here. You&rsquo;ll notice instead of setting an explicit number of rows, we&rsquo;ve set it to the length of our countries list - <code>gs = (grid_spec.GridSpec(len(countries),1))</code>. This gives us flexibility for future plotting with the ability to plot more or less countries without needing to adjust the code.</p>
<p>Just after the for loop we create each axes object: <code>ax_objs.append(fig.add_subplot(gs[i:i+1, 0:]))</code>. Before the loop we declared <code>i = 0</code>. Here we are saying create axes object from row 0 to 1, the next time the loop runs it creates an axes object from row 1 to 2, then 2 to 3, 3 to 4, and so on.</p>
<p>Following this we can use <code>ax_objs[-1]</code> to access the last created axes object to use as our plotting area.</p>
<p>Next, we create the kde plot. We declare this as a variable so we can retrieve the x and y values to use in the <code>fill_between</code> that follows.</p>
<h3 id="overlapping-axes-objects">Overlapping Axes Objects <a id="gs2"></a><a class="headerlink" href="#overlapping-axes-objects" title="Link to this heading">#</a></h3>
<p>Once again using GridSpec, we can adjust the spacing between each of the subplots. We can do this by adding one line outside of the loop before <code>plt.tight_layout()</code>The exact value will depend on your distribution so feel free to play around with the exact value:</p>

<div class="highlight">
  <pre>gs.update(hspace= -0.5)</pre>
</div>

<p><img src="/matplotlib/create-ridgeplots-in-matplotlib/grid_spec_distro_overlap_1.png" alt="6 kernel density estimate (KDE) charts, each with different shades ranging from blue to blood red. However, the y axis object are overlapping."></p>
<p>Now our axes objects are overlapping! Great-ish. Each axes object is hiding the one layered below it. We <em>could</em> just add <code>ax_objs[-1].axis(&quot;off&quot;)</code> to our for loop, but if we do that we will lose our xticklabels. Instead we will create a variable to access the background of each axes object, and we will loop through each line of the border (spine) to turn them off. As we <em>only</em> need the xticklabels for the final plot, we will add an if statement to handle that. We will also add in our country labels here. In our for loop we add:</p>

<div class="highlight">
  <pre># make background transparent
rect = ax_objs[-1].patch
rect.set_alpha(0)

# remove borders, axis ticks, and labels
ax_objs[-1].set_yticklabels([])
ax_objs[-1].set_ylabel(&#39;&#39;)

if i == len(countries)-1:
    pass
else:
    ax_objs[-1].set_xticklabels([])

spines = [&#34;top&#34;,&#34;right&#34;,&#34;left&#34;,&#34;bottom&#34;]
for s in spines:
    ax_objs[-1].spines[s].set_visible(False)

country = country.replace(&#34; &#34;,&#34;\n&#34;)
ax_objs[-1].text(-0.02,0,country,fontweight=&#34;bold&#34;,fontsize=14,ha=&#34;center&#34;)</pre>
</div>

<p><img src="/matplotlib/create-ridgeplots-in-matplotlib/grid_spec_distro_overlap_2.png" alt="6 kernel density estimate (KDE) charts each representing 6 countries. France is blue, Germany is dark blue, Ireland is purple, Italy is a lighter shade of purple, Spain is red, and the United Kingdom is blood red.  The x-axis shows the distribution of children in each county listed."></p>
<p>As an alternative to the above, we can use the <code>KernelDensity</code> module from <code>sklearn.neighbors</code> to create our distribution. This gives us a bit more control over our bandwidth. The method here is taken from Jake VanderPlas&rsquo;s fantastic <em>Python Data Science Handbook</em>, you can read his full excerpt <a href="https://jakevdp.github.io/PythonDataScienceHandbook/05.13-kernel-density-estimation.html">here</a>. We can reuse most of the above code, but need to make a couple of changes. Rather than repeat myself, I&rsquo;ll add the full snippet here and you can see the changes and minor additions (added title, label to xaxis).</p>
<h3 id="complete-plot-snippet">Complete Plot Snippet <a id="snippet"></a><a class="headerlink" href="#complete-plot-snippet" title="Link to this heading">#</a></h3>

<div class="highlight">
  <pre>countries = [x for x in np.unique(data.country)]
colors = [&#39;#0000ff&#39;, &#39;#3300cc&#39;, &#39;#660099&#39;, &#39;#990066&#39;, &#39;#cc0033&#39;, &#39;#ff0000&#39;]

gs = grid_spec.GridSpec(len(countries),1)
fig = plt.figure(figsize=(16,9))

i = 0

ax_objs = []
for country in countries:
    country = countries[i]
    x = np.array(data[data.country == country].score)
    x_d = np.linspace(0,1, 1000)

    kde = KernelDensity(bandwidth=0.03, kernel=&#39;gaussian&#39;)
    kde.fit(x[:, None])

    logprob = kde.score_samples(x_d[:, None])

    # creating new axes object
    ax_objs.append(fig.add_subplot(gs[i:i&#43;1, 0:]))

    # plotting the distribution
    ax_objs[-1].plot(x_d, np.exp(logprob),color=&#34;#f0f0f0&#34;,lw=1)
    ax_objs[-1].fill_between(x_d, np.exp(logprob), alpha=1,color=colors[i])


    # setting uniform x and y lims
    ax_objs[-1].set_xlim(0,1)
    ax_objs[-1].set_ylim(0,2.5)

    # make background transparent
    rect = ax_objs[-1].patch
    rect.set_alpha(0)

    # remove borders, axis ticks, and labels
    ax_objs[-1].set_yticklabels([])

    if i == len(countries)-1:
        ax_objs[-1].set_xlabel(&#34;Test Score&#34;, fontsize=16,fontweight=&#34;bold&#34;)
    else:
        ax_objs[-1].set_xticklabels([])

    spines = [&#34;top&#34;,&#34;right&#34;,&#34;left&#34;,&#34;bottom&#34;]
    for s in spines:
        ax_objs[-1].spines[s].set_visible(False)

    adj_country = country.replace(&#34; &#34;,&#34;\n&#34;)
    ax_objs[-1].text(-0.02,0,adj_country,fontweight=&#34;bold&#34;,fontsize=14,ha=&#34;right&#34;)


    i &#43;= 1

gs.update(hspace=-0.7)

fig.text(0.07,0.85,&#34;Distribution of Aptitude Test Results from 18 – 24 year-olds&#34;,fontsize=20)

plt.tight_layout()
plt.show()</pre>
</div>

<p><img src="/matplotlib/create-ridgeplots-in-matplotlib/grid_spec_distro_overlap_3.png" alt="6 kernel density estimate (KDE) charts each representing 6 countries. France is blue, Germany is dark blue, Ireland is purple, Italy is a lighter shade of purple, Spain is red, and the United Kingdom is blood red.  The x-axis shows the distribution of aptitude test results from 18 to 24 years old in each county listed."></p>
<p>I&rsquo;ll finish this off with a little project to put the above code into practice. The data provided also contains information on whether the test taker was male or female. Using the above code as a template, see how you get on creating something like this:</p>
<p><img src="/matplotlib/create-ridgeplots-in-matplotlib/split_ridges.png" alt="Each of two sets of six kernel density estimate (KDE) charts shows six different countries. France is blue, Germany is dark blue, Ireland is purple, Italy is a lighter shade of purple, Spain is red, and the United Kingdom is blood red. The x-axis displays the distribution of 18 to 24 year olds’ aptitude test scores in each county presented. The distribution of the results of the aptitude test among boys aged 18 to 24 in each county is shown on one of the two 6-kennel charts, while the distribution of females is shown on the other."></p>
<p>For those more ambitious, this could be turned into a split violin plot with males on one side and females on the other. Is there a way to combine the ridge and violin plot?</p>
<p>I&rsquo;d love to see what people come back with so if you do create something, send it to me on twitter <a href="http://twitter.com/petermckeever">here</a>!</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Create a Tesla Cybertruck That Drives]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/?utm_source=atom_feed" rel="related" type="text/html" title="An Inquiry Into Matplotlib&#39;s Figures" />
                <link href="https://blog.scientific-python.org/matplotlib/custom-3d-engine/?utm_source=atom_feed" rel="related" type="text/html" title="Custom 3D engine in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="related" type="text/html" title="Creating the Warming Stripes in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-in-data-driven-seo/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib in Data Driven SEO" />
                <link href="https://blog.scientific-python.org/matplotlib/using-matplotlib-to-advocate-for-postdocs/?utm_source=atom_feed" rel="related" type="text/html" title="Using Matplotlib to Advocate for Postdocs" />
            
                <id>https://blog.scientific-python.org/matplotlib/create-a-tesla-cybertruck-that-drives/</id>
            
            
            <published>2020-01-12T13:35:34-05:00</published>
            <updated>2020-01-12T13:35:34-05:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Learn how to create a Tesla Cybertruck with Matplotlib that drives via animation.</blockquote><p>My name is <a href="https://wwww.twitter.com/tedpetrou">Ted Petrou</a>, founder of <a href="https://www.dunderdata.com">Dunder Data</a>, and in this tutorial you will learn how to create the new <a href="https://www.tesla.com/cybertruck">Tesla Cybertruck</a> using Matplotlib. I was inspired by the image below which was originally created by <a href="https://twitter.com/lynnandtonic/status/1197989912970067969?lang=en">Lynn Fisher</a> (without Matplotlib).</p>
<p>Before going into detail, let&rsquo;s jump to the results. Here is the completed recreation of the Tesla Cybertruck that drives off the screen.</p>
<video width="700" height="500" controls>
  <source src="tesla_animate.mp4" type="video/mp4">
</video>
<h2 id="tutorial">Tutorial<a class="headerlink" href="#tutorial" title="Link to this heading">#</a></h2>
<p>A tutorial now follows containing all the steps that creates a Tesla Cybertruck that drives. It covers the following topics:</p>
<ul>
<li>Figure and Axes setup</li>
<li>Adding shapes</li>
<li>Color gradients</li>
<li>Animation</li>
</ul>
<p>Understanding these topics should give you enough to start animating your own figures in Matplotlib. This tutorial is not suited for those with no Matplotlib experience. You need to understand the relationship between the Figure and Axes and how to use the object-oriented interface of Matplotlib.</p>
<h3 id="figure-and-axes-setup">Figure and Axes setup<a class="headerlink" href="#figure-and-axes-setup" title="Link to this heading">#</a></h3>
<p>We first create a Matplotlib Figure without any Axes (the plotting surface). The function <code>create_axes</code> adds an Axes to the Figure, sets the x-limits to be twice the y-limits (to match the ratio of the figure dimensions (16 x 8)), fills in the background with two different dark colors using <code>fill_between</code>, and adds grid lines to make it easier to plot the objects in the exact place you desire. Set the <code>draft</code> parameter to <code>False</code> when you want to remove the grid lines, tick marks, and tick labels.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">Figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_axes</span><span class="p">(</span><span class="n">draft</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">fill_between</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="n">y1</span><span class="o">=</span><span class="mf">0.36</span><span class="p">,</span> <span class="n">y2</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">fill_between</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="n">y1</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">y2</span><span class="o">=</span><span class="mf">0.36</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#101115&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">draft</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">axis</span><span class="p">(</span><span class="s2">&#34;off&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">create_axes</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/create-a-tesla-cybertruck-that-drives/output_4_0.png" alt="png"></p>
<h3 id="shapes-in-matplotlib">Shapes in Matplotlib<a class="headerlink" href="#shapes-in-matplotlib" title="Link to this heading">#</a></h3>
<p>Most of the Cybertruck is composed of shapes (patches in Matplotlib terminology) - circles, rectangles, and polygons. These shapes are available in the patches Matplotlib module. After importing, we instantiate single instances of these patches and then call the <code>add_patch</code> method to add the patch to the Axes.</p>
<p>For the Cybertruck, I used three patches, <code>Polygon</code>, <code>Rectangle</code>, and <code>Circle</code>. They each have different parameters available in their constructor. I first constructed the body of the car as four polygons. Two other polygons were used for the rims. Each polygon is provided a list of x, y coordinates where the corner points are located. Matplotlib connects all the points in the order given and fills it in with the provided color.</p>
<p>Notice how the Axes is retrieved as the first line of the function. This is used throughout the tutorial.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.patches</span> <span class="kn">import</span> <span class="n">Polygon</span><span class="p">,</span> <span class="n">Rectangle</span><span class="p">,</span> <span class="n">Circle</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_body</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">top</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">([[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mf">0.66</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.6</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">]],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#DCDCDC&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">windows</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">0.74</span><span class="p">,</span> <span class="mf">0.54</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mf">0.64</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.26</span><span class="p">,</span> <span class="mf">0.6</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.262</span><span class="p">,</span> <span class="mf">0.57</span><span class="p">]],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">windows_bottom</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">0.8</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mf">0.635</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.255</span><span class="p">,</span> <span class="mf">0.597</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.255</span><span class="p">,</span> <span class="mf">0.585</span><span class="p">]],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#474747&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">base</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.445</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.67</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.78</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.84</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.3</span><span class="p">,</span> <span class="mf">0.423</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.36</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.44</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.52</span><span class="p">,</span> <span class="mf">0.43</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.58</span><span class="p">,</span> <span class="mf">0.44</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.6</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#1E2329&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_rim</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.445</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.67</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.78</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.84</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.824</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.77</span><span class="p">,</span> <span class="mf">0.49</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.674</span><span class="p">,</span> <span class="mf">0.49</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">0.633</span><span class="p">,</span> <span class="mf">0.445</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#373E48&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_rim</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.3</span><span class="p">,</span> <span class="mf">0.423</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.36</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.44</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.52</span><span class="p">,</span> <span class="mf">0.43</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.504</span><span class="p">,</span> <span class="mf">0.43</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.436</span><span class="p">,</span> <span class="mf">0.498</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.364</span><span class="p">,</span> <span class="mf">0.498</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="mf">1.312</span><span class="p">,</span> <span class="mf">0.423</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#4D586A&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">top</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">windows</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">windows_bottom</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">left_rim</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">right_rim</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">create_body</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/create-a-tesla-cybertruck-that-drives/output_6_0.png" alt="png"></p>
<h4 id="tires">Tires<a class="headerlink" href="#tires" title="Link to this heading">#</a></h4>
<p>I used three <code>Circle</code> patches for each of the tires. You must provide the center and radius. For the innermost circles (the &ldquo;spokes&rdquo;), I&rsquo;ve set the <code>zorder</code> to 99. The <code>zorder</code> determines the order of how plotting objects are layered on top of each other. The higher the number, the higher up on the stack of layers the object will be plotted. During the next step, we will draw some rectangles through the tires and they need to be plotted underneath these spokes.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_tires</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_tire</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">0.724</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.075</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#202328&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_tire</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">1.404</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.075</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#202328&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_inner_tire</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">0.724</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.052</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#15191C&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_inner_tire</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">1.404</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.052</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#15191C&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_spoke</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">0.724</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.019</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#202328&#34;</span><span class="p">,</span> <span class="n">zorder</span><span class="o">=</span><span class="mi">99</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_spoke</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">1.404</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.019</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#202328&#34;</span><span class="p">,</span> <span class="n">zorder</span><span class="o">=</span><span class="mi">99</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_inner_spoke</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">0.724</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.011</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#131418&#34;</span><span class="p">,</span> <span class="n">zorder</span><span class="o">=</span><span class="mi">99</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_inner_spoke</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">1.404</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.011</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#131418&#34;</span><span class="p">,</span> <span class="n">zorder</span><span class="o">=</span><span class="mi">99</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">left_tire</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">right_tire</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">left_inner_tire</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">right_inner_tire</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">left_spoke</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">right_spoke</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">left_inner_spoke</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">right_inner_spoke</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">create_tires</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/create-a-tesla-cybertruck-that-drives/output_8_0.png" alt="png"></p>
<h4 id="axles">Axles<a class="headerlink" href="#axles" title="Link to this heading">#</a></h4>
<p>I used the <code>Rectangle</code> patch to represent the two &lsquo;axles&rsquo; (this isn&rsquo;t the correct term, but you&rsquo;ll see what I mean) going through the tires. You must provide a coordinate for the lower left corner, a width, and a height. You can also provide it an angle (in degrees) to control its orientation. Notice that they go under the spokes plotted from above. This is due to their lower <code>zorder</code>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_axles</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_left_axle</span> <span class="o">=</span> <span class="n">Rectangle</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="mf">0.687</span><span class="p">,</span> <span class="mf">0.427</span><span class="p">),</span> <span class="n">width</span><span class="o">=</span><span class="mf">0.104</span><span class="p">,</span> <span class="n">height</span><span class="o">=</span><span class="mf">0.005</span><span class="p">,</span> <span class="n">angle</span><span class="o">=</span><span class="mi">315</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#202328&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">left_right_axle</span> <span class="o">=</span> <span class="n">Rectangle</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="mf">0.761</span><span class="p">,</span> <span class="mf">0.427</span><span class="p">),</span> <span class="n">width</span><span class="o">=</span><span class="mf">0.104</span><span class="p">,</span> <span class="n">height</span><span class="o">=</span><span class="mf">0.005</span><span class="p">,</span> <span class="n">angle</span><span class="o">=</span><span class="mi">225</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#202328&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_left_axle</span> <span class="o">=</span> <span class="n">Rectangle</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="mf">1.367</span><span class="p">,</span> <span class="mf">0.427</span><span class="p">),</span> <span class="n">width</span><span class="o">=</span><span class="mf">0.104</span><span class="p">,</span> <span class="n">height</span><span class="o">=</span><span class="mf">0.005</span><span class="p">,</span> <span class="n">angle</span><span class="o">=</span><span class="mi">315</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#202328&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">right_right_axle</span> <span class="o">=</span> <span class="n">Rectangle</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="mf">1.441</span><span class="p">,</span> <span class="mf">0.427</span><span class="p">),</span> <span class="n">width</span><span class="o">=</span><span class="mf">0.104</span><span class="p">,</span> <span class="n">height</span><span class="o">=</span><span class="mf">0.005</span><span class="p">,</span> <span class="n">angle</span><span class="o">=</span><span class="mi">225</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#202328&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">left_left_axle</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">left_right_axle</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">right_left_axle</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">right_right_axle</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">create_axles</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/create-a-tesla-cybertruck-that-drives/output_10_0.png" alt="png"></p>
<h4 id="other-details">Other details<a class="headerlink" href="#other-details" title="Link to this heading">#</a></h4>
<p>The front bumper, head light, tail light, door and window lines are added below. I used regular Matplotlib lines for some of these. Those lines are not patches and get added directly to the Axes without any other additional method.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_other_details</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># other details</span>
</span></span><span class="line"><span class="cl">    <span class="n">front</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.597</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.589</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.589</span><span class="p">,</span> <span class="mf">0.445</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.445</span><span class="p">]],</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#26272d&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">front_bottom</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.438</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.58</span><span class="p">,</span> <span class="mf">0.438</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.58</span><span class="p">,</span> <span class="mf">0.423</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.423</span><span class="p">]],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#26272d&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">head_light</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.597</span><span class="p">,</span> <span class="mf">0.51</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.589</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.589</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.62</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">]],</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span><span class="o">=</span><span class="s2">&#34;aqua&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">step</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">0.84</span><span class="p">,</span> <span class="mf">0.39</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.84</span><span class="p">,</span> <span class="mf">0.394</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.3</span><span class="p">,</span> <span class="mf">0.397</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.3</span><span class="p">,</span> <span class="mf">0.393</span><span class="p">]],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;#1E2329&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># doors</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">0.84</span><span class="p">,</span> <span class="mf">0.84</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.523</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">1.02</span><span class="p">,</span> <span class="mf">1.04</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.53</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">1.26</span><span class="p">,</span> <span class="mf">1.26</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.54</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">0.84</span><span class="p">,</span> <span class="mf">0.85</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.523</span><span class="p">,</span> <span class="mf">0.547</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">1.04</span><span class="p">,</span> <span class="mf">1.04</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.53</span><span class="p">,</span> <span class="mf">0.557</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">1.26</span><span class="p">,</span> <span class="mf">1.26</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.54</span><span class="p">,</span> <span class="mf">0.57</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># window lines</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">0.87</span><span class="p">,</span> <span class="mf">0.88</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.56</span><span class="p">,</span> <span class="mf">0.59</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">([</span><span class="mf">1.03</span><span class="p">,</span> <span class="mf">1.04</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.56</span><span class="p">,</span> <span class="mf">0.63</span><span class="p">],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;black&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># tail light</span>
</span></span><span class="line"><span class="cl">    <span class="n">tail_light</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">1.6</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.007</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;red&#34;</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.6</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">tail_light_center</span> <span class="o">=</span> <span class="n">Circle</span><span class="p">((</span><span class="mf">1.6</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">),</span> <span class="n">radius</span><span class="o">=</span><span class="mf">0.003</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;yellow&#34;</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.6</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">tail_light_up</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">1.597</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.6</span><span class="p">,</span> <span class="mf">0.6</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.603</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">]],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;red&#34;</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.4</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">tail_light_right</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">1.6</span><span class="p">,</span> <span class="mf">0.563</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.64</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.6</span><span class="p">,</span> <span class="mf">0.557</span><span class="p">]],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;red&#34;</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.4</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">tail_light_down</span> <span class="o">=</span> <span class="n">Polygon</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[[</span><span class="mf">1.597</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.6</span><span class="p">,</span> <span class="mf">0.52</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.603</span><span class="p">,</span> <span class="mf">0.56</span><span class="p">]],</span> <span class="n">color</span><span class="o">=</span><span class="s2">&#34;red&#34;</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.4</span>
</span></span><span class="line"><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">front</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">front_bottom</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">head_light</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">step</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">tail_light</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">tail_light_center</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">tail_light_up</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">tail_light_right</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">tail_light_down</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">create_other_details</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/create-a-tesla-cybertruck-that-drives/output_12_0.png" alt="png"></p>
<h4 id="color-gradients-for-the-head-light-beam">Color gradients for the head light beam<a class="headerlink" href="#color-gradients-for-the-head-light-beam" title="Link to this heading">#</a></h4>
<p>The head light beam has a distinct color gradient that dissipates into the night sky. This is challenging to complete. I found an <a href="https://wwww.twitter.com/tedpetrou">excellent answer on Stack Overflow from user Joe Kington</a> on how to do this. We begin by using the <code>imshow</code> function which creates images from 3-dimensional arrays. Our image will simply be a rectangle of colors.</p>
<p>We create a 1 x 100 x 4 array that represents 1 row by 100 columns of points of RGBA (red, green, blue, alpha) values. Every point is given the same red, green, and blue values of (0, 1, 1) which represents the color &lsquo;aqua&rsquo;. The alpha value represents opacity and ranges between 0 and 1 with 0 being completely transparent (invisible) and 1 being opaque. We would like the opacity to decrease as the light extends further from the head light (that is further to the left). The NumPy <code>linspace</code> function is used to create an array of 100 numbers increasing linearly from 0 to 1. This array will be set as the alpha values.</p>
<p>The <code>extent</code> parameter defines the rectangular region where the image will be shown. The four values correspond to xmin, xmax, ymin, and ymax. The 100 alpha values will be mapped to this region beginning from the left. The array of alphas begins at 0, which means that the very left of this rectangular region will be transparent. The opacity will increase moving to the right-side of the rectangle where it eventually reaches 1.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.colors</span> <span class="k">as</span> <span class="nn">mcolors</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_headlight_beam</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">empty</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">rgb</span> <span class="o">=</span> <span class="n">mcolors</span><span class="o">.</span><span class="n">colorConverter</span><span class="o">.</span><span class="n">to_rgb</span><span class="p">(</span><span class="s2">&#34;aqua&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">alphas</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span><span class="p">[:,</span> <span class="p">:,</span> <span class="p">:</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb</span>
</span></span><span class="line"><span class="cl">    <span class="n">z</span><span class="p">[:,</span> <span class="p">:,</span> <span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">alphas</span>
</span></span><span class="line"><span class="cl">    <span class="n">im</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="n">extent</span><span class="o">=</span><span class="p">[</span><span class="mf">0.3</span><span class="p">,</span> <span class="mf">0.589</span><span class="p">,</span> <span class="mf">0.501</span><span class="p">,</span> <span class="mf">0.505</span><span class="p">],</span> <span class="n">zorder</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">create_headlight_beam</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/create-a-tesla-cybertruck-that-drives/output_14_0.png" alt="png"></p>
<h4 id="headlight-cloud">Headlight Cloud<a class="headerlink" href="#headlight-cloud" title="Link to this heading">#</a></h4>
<p>The cloud of points surrounding the headlight beam is even more challenging to complete. This time, a 100 x 100 grid of points was used to control the opacity. The opacity is directly proportional to the vertical distance from the center beam. Additionally, if a point was outside of the diagonal of the rectangle defined by <code>extent</code>, its opacity was set to 0.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">create_headlight_cloud</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">z2</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">empty</span><span class="p">((</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">rgb</span> <span class="o">=</span> <span class="n">mcolors</span><span class="o">.</span><span class="n">colorConverter</span><span class="o">.</span><span class="n">to_rgb</span><span class="p">(</span><span class="s2">&#34;aqua&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">z2</span><span class="p">[:,</span> <span class="p">:,</span> <span class="p">:</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">rgb</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">j</span><span class="p">,</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">100</span><span class="p">)):</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">abs</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="o">-</span><span class="mf">0.2</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">,</span> <span class="mi">100</span><span class="p">))):</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">x</span> <span class="o">*</span> <span class="mf">0.2</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">z2</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">-</span> <span class="p">(</span><span class="n">y</span> <span class="o">+</span> <span class="mf">0.8</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">z2</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="n">im2</span> <span class="o">=</span> <span class="n">ax</span><span class="o">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">z2</span><span class="p">,</span> <span class="n">extent</span><span class="o">=</span><span class="p">[</span><span class="mf">0.3</span><span class="p">,</span> <span class="mf">0.65</span><span class="p">,</span> <span class="mf">0.45</span><span class="p">,</span> <span class="mf">0.55</span><span class="p">],</span> <span class="n">zorder</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">create_headlight_cloud</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/create-a-tesla-cybertruck-that-drives/output_16_0.png" alt="png"></p>
<h3 id="creating-a-function-to-draw-the-car">Creating a Function to Draw the Car<a class="headerlink" href="#creating-a-function-to-draw-the-car" title="Link to this heading">#</a></h3>
<p>All of our work from above can be placed in a single function that draws the car. This will be used when initializing our animation. Notice, that the first line of the function clears the Figure, which removes our Axes. If we don&rsquo;t clear the Figure, then we will keep adding more and more Axes each time this function is called. Since this is our final product, we set <code>draft</code> to <code>False</code>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">draw_car</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">create_axes</span><span class="p">(</span><span class="n">draft</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">create_body</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">create_tires</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">create_axles</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">create_other_details</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">create_headlight_beam</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="n">create_headlight_beam</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">draw_car</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/create-a-tesla-cybertruck-that-drives/output_18_0.png" alt="png"></p>
<h2 id="animation">Animation<a class="headerlink" href="#animation" title="Link to this heading">#</a></h2>
<p>Animation in Matplotlib is fairly straightforward. You must create a function that updates the position of the objects in your figure for each frame. This function is called repeatedly for each frame.</p>
<p>In the <code>update</code> function below, we loop through each patch, line, and image in our Axes and reduce the x-value of each plotted object by .015. This has the effect of moving the truck to the left. The trickiest part was changing the x and y values for the rectangular tire &lsquo;axles&rsquo; so that it appeared that the tires were rotating. Some basic trigonometry helps calculate this.</p>
<p>Implicitly, Matplotlib passes the update function the frame number as an integer as the first argument. We accept this input as the parameter <code>frame_number</code>. We only use it in one place, and that is to do nothing during the first frame.</p>
<p>Finally, the <code>FuncAnimation</code> class from the animation module is used to construct the animation. We provide it our original Figure, the function to update the Figure (<code>update</code>), a function to initialize the Figure (<code>draw_car</code>), the total number of frames, and any extra arguments used during update (<code>fargs</code>).</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.animation</span> <span class="kn">import</span> <span class="n">FuncAnimation</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="n">frame_number</span><span class="p">,</span> <span class="n">x_delta</span><span class="p">,</span> <span class="n">radius</span><span class="p">,</span> <span class="n">angle</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">frame_number</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">patch</span> <span class="ow">in</span> <span class="n">ax</span><span class="o">.</span><span class="n">patches</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">patch</span><span class="p">,</span> <span class="n">Polygon</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="n">arr</span> <span class="o">=</span> <span class="n">patch</span><span class="o">.</span><span class="n">get_xy</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="n">arr</span><span class="p">[:,</span> <span class="mi">0</span><span class="p">]</span> <span class="o">-=</span> <span class="n">x_delta</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">patch</span><span class="p">,</span> <span class="n">Circle</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">patch</span><span class="o">.</span><span class="n">get_center</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="n">patch</span><span class="o">.</span><span class="n">set_center</span><span class="p">((</span><span class="n">x</span> <span class="o">-</span> <span class="n">x_delta</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">patch</span><span class="p">,</span> <span class="n">Rectangle</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="n">xd_old</span> <span class="o">=</span> <span class="o">-</span><span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">pi</span> <span class="o">*</span> <span class="n">patch</span><span class="o">.</span><span class="n">angle</span> <span class="o">/</span> <span class="mi">180</span><span class="p">)</span> <span class="o">*</span> <span class="n">radius</span>
</span></span><span class="line"><span class="cl">            <span class="n">yd_old</span> <span class="o">=</span> <span class="o">-</span><span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">pi</span> <span class="o">*</span> <span class="n">patch</span><span class="o">.</span><span class="n">angle</span> <span class="o">/</span> <span class="mi">180</span><span class="p">)</span> <span class="o">*</span> <span class="n">radius</span>
</span></span><span class="line"><span class="cl">            <span class="n">patch</span><span class="o">.</span><span class="n">angle</span> <span class="o">+=</span> <span class="n">angle</span>
</span></span><span class="line"><span class="cl">            <span class="n">xd</span> <span class="o">=</span> <span class="o">-</span><span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">pi</span> <span class="o">*</span> <span class="n">patch</span><span class="o">.</span><span class="n">angle</span> <span class="o">/</span> <span class="mi">180</span><span class="p">)</span> <span class="o">*</span> <span class="n">radius</span>
</span></span><span class="line"><span class="cl">            <span class="n">yd</span> <span class="o">=</span> <span class="o">-</span><span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">pi</span> <span class="o">*</span> <span class="n">patch</span><span class="o">.</span><span class="n">angle</span> <span class="o">/</span> <span class="mi">180</span><span class="p">)</span> <span class="o">*</span> <span class="n">radius</span>
</span></span><span class="line"><span class="cl">            <span class="n">x</span> <span class="o">=</span> <span class="n">patch</span><span class="o">.</span><span class="n">get_x</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="n">y</span> <span class="o">=</span> <span class="n">patch</span><span class="o">.</span><span class="n">get_y</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="n">x_new</span> <span class="o">=</span> <span class="n">x</span> <span class="o">-</span> <span class="n">x_delta</span> <span class="o">+</span> <span class="n">xd</span> <span class="o">-</span> <span class="n">xd_old</span>
</span></span><span class="line"><span class="cl">            <span class="n">y_new</span> <span class="o">=</span> <span class="n">y</span> <span class="o">+</span> <span class="n">yd</span> <span class="o">-</span> <span class="n">yd_old</span>
</span></span><span class="line"><span class="cl">            <span class="n">patch</span><span class="o">.</span><span class="n">set_x</span><span class="p">(</span><span class="n">x_new</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">patch</span><span class="o">.</span><span class="n">set_y</span><span class="p">(</span><span class="n">y_new</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">ax</span><span class="o">.</span><span class="n">lines</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">xdata</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">get_xdata</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">line</span><span class="o">.</span><span class="n">set_xdata</span><span class="p">(</span><span class="n">xdata</span> <span class="o">-</span> <span class="n">x_delta</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">image</span> <span class="ow">in</span> <span class="n">ax</span><span class="o">.</span><span class="n">images</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">extent</span> <span class="o">=</span> <span class="n">image</span><span class="o">.</span><span class="n">get_extent</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">extent</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-=</span> <span class="n">x_delta</span>
</span></span><span class="line"><span class="cl">        <span class="n">extent</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-=</span> <span class="n">x_delta</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">animation</span> <span class="o">=</span> <span class="n">FuncAnimation</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="p">,</span> <span class="n">update</span><span class="p">,</span> <span class="n">init_func</span><span class="o">=</span><span class="n">draw_car</span><span class="p">,</span> <span class="n">frames</span><span class="o">=</span><span class="mi">110</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">fargs</span><span class="o">=</span><span class="p">(</span><span class="mf">0.015</span><span class="p">,</span> <span class="mf">0.052</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre>
</div>
<h3 id="save-animation">Save animation<a class="headerlink" href="#save-animation" title="Link to this heading">#</a></h3>
<p>Finally, we can save the animation as an mp4 file (you must have ffmpeg installed for this to work). We set the frames-per-second (<code>fps</code>) to 30. From above, the total number of frames is 110 (enough to move the truck off the screen) so the video will last nearly four seconds (110 / 30).</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">animation</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="s2">&#34;tesla_animate.mp4&#34;</span><span class="p">,</span> <span class="n">fps</span><span class="o">=</span><span class="mi">30</span><span class="p">,</span> <span class="n">bitrate</span><span class="o">=</span><span class="mi">3000</span><span class="p">)</span></span></span></code></pre>
</div>
<video width="700" height="500" controls>
  <source src="tesla_animate.mp4" type="video/mp4">
</video>
<h2 id="continue-animating">Continue Animating<a class="headerlink" href="#continue-animating" title="Link to this heading">#</a></h2>
<p>I encourage you to add more components to your Cybertruck animation to personalize the creation. I suggest encapsulating each addition with a function as done in this tutorial.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[An Inquiry Into Matplotlib's Figures]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/custom-3d-engine/?utm_source=atom_feed" rel="related" type="text/html" title="Custom 3D engine in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="related" type="text/html" title="Creating the Warming Stripes in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-in-data-driven-seo/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib in Data Driven SEO" />
                <link href="https://blog.scientific-python.org/matplotlib/using-matplotlib-to-advocate-for-postdocs/?utm_source=atom_feed" rel="related" type="text/html" title="Using Matplotlib to Advocate for Postdocs" />
            
                <id>https://blog.scientific-python.org/matplotlib/an-inquiry-into-matplotlib-figures/</id>
            
            
            <published>2019-12-24T11:25:42+05:30</published>
            <updated>2019-12-24T11:25:42+05:30</updated>
            
            
            <content type="html"><![CDATA[<blockquote>This guide dives deep into the inner workings of Matplotlib&rsquo;s Figures, Axes, subplots and the very amazing GridSpec!</blockquote><h1 id="preliminaries">Preliminaries<a class="headerlink" href="#preliminaries" title="Link to this heading">#</a></h1>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib</span> <span class="k">as</span> <span class="nn">mpl</span></span></span></code></pre>
</div>
<blockquote>
<p>A Top-Down runnable Jupyter Notebook with the exact contents of this blog can be found <a href="https://gist.github.com/akashpalrecha/4652e98c9b2f3f1961637be001dc0239">here</a></p>
</blockquote>
<blockquote>
<p>An interactive version of this guide can be accessed on <a href="https://colab.research.google.com/drive/1SOgWPI9HckTQ0zm47Ma-gYCTucMccTxg">Google Colab</a></p>
</blockquote>
<h1 id="a-word-before-we-get-started">A word before we get started&hellip;<a class="headerlink" href="#a-word-before-we-get-started" title="Link to this heading">#</a></h1>
<hr>
<p>Although a beginner can follow along with this guide, it is primarily meant for people who have at least a basic knowledge of how Matplotlib&rsquo;s plotting functionality works.</p>
<p>Essentially, if you know how to take 2 NumPy arrays and plot them (using an appropriate type of graph) on 2 different axes in a single figure and give it basic styling, you&rsquo;re good to go for the purposes of this guide.</p>
<p>If you feel you need some introduction to basic Matplotlib plotting, here&rsquo;s a great guide that can help you get a feel for <a href="https://matplotlib.org/devdocs/gallery/subplots_axes_and_figures/subplots_demo.html">introductory plotting using Matplotlib</a></p>
<p>From here on, I will be assuming that you have gained sufficient knowledge to follow along this guide.</p>
<p>Also, in order to save everyone&rsquo;s time, I will keep my explanations short, terse and very much to the point, and sometimes leave it for the reader to interpret things (because that&rsquo;s what I&rsquo;ve done throughout this guide for myself anyway).</p>
<p>The primary driver in this whole exercise will be code and not text, and I encourage you to spin up a Jupyter notebook and type in and try out everything yourself to make the best use of this resource.</p>
<h2 id="what-this-guide-is-and-what-it-is-not">What this guide <em>is</em> and what it is <em>not</em>:<a class="headerlink" href="#what-this-guide-is-and-what-it-is-not" title="Link to this heading">#</a></h2>
<p>This is not a guide about how to beautifully plot different kinds of data using Matplotlib, the internet is more than full of such tutorials by people who can explain it way better than I can.</p>
<p>This article attempts to explain the workings of some of the foundations of any plot you create using Matplotlib.
We will mostly refrain from focusing on what data we are plotting and instead focus on the anatomy of our plots.</p>
<h1 id="setting-up">Setting up<a class="headerlink" href="#setting-up" title="Link to this heading">#</a></h1>
<p>Matplotlib has many styles available, we can see the available options using:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">style</span><span class="o">.</span><span class="n">available</span></span></span></code></pre>
</div>
<pre><code>['seaborn-dark',
 'seaborn-darkgrid',
 'seaborn-ticks',
 'fivethirtyeight',
 'seaborn-whitegrid',
 'classic',
 '_classic_test',
 'fast',
 'seaborn-talk',
 'seaborn-dark-palette',
 'seaborn-bright',
 'seaborn-pastel',
 'grayscale',
 'seaborn-notebook',
 'ggplot',
 'seaborn-colorblind',
 'seaborn-muted',
 'seaborn',
 'Solarize_Light2',
 'seaborn-paper',
 'bmh',
 'tableau-colorblind10',
 'seaborn-white',
 'dark_background',
 'seaborn-poster',
 'seaborn-deep']
</code></pre>
<p>We shall use <code>seaborn</code>. This is done like so:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">style</span><span class="o">.</span><span class="n">use</span><span class="p">(</span><span class="s2">&#34;seaborn&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Let&rsquo;s get started!</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># Creating some fake data for plotting</span>
</span></span><span class="line"><span class="cl"><span class="n">xs</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">400</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ys</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">xs</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">xc</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">600</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">yc</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">cos</span><span class="p">(</span><span class="n">xc</span><span class="o">**</span><span class="mi">2</span><span class="p">)</span></span></span></code></pre>
</div>
<h1 id="exploration">Exploration<a class="headerlink" href="#exploration" title="Link to this heading">#</a></h1>
<p>The usual way to create a plot using Matplotlib goes somewhat like this:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># `Fig` is short for Figure. `ax` is short for Axes.</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">ys</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">ys</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xc</span><span class="p">,</span> <span class="n">yc</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xc</span><span class="p">,</span> <span class="n">yc</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">suptitle</span><span class="p">(</span><span class="s2">&#34;Basic plotting using Matplotlib&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_14_0.png" alt="png"></p>
<p>Our goal today is to take apart the previous snippet of code and understand all of the underlying building blocks well enough so that we can use them separately and in a much more powerful way.</p>
<p>If you&rsquo;re a beginner like I was before writing this guide, let me assure you: this is all very simple stuff.</p>
<p>Going into <a href="https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots.html?highlight=subplots#matplotlib.pyplot.subplots"><code>plt.subplots</code></a> documentation (hit <code>Shift+Tab+Tab</code> in a Jupyter notebook) reveals some of the other Matplotlib internals that it uses in order to give us the <code>Figure</code> and it&rsquo;s <code>Axes</code>.</p>
<p>These include :<br></p>
<ol>
<li><code>plt.subplot</code></li>
<li><code>plt.figure</code></li>
<li><code>mpl.figure.Figure</code></li>
<li><code>mpl.figure.Figure.add_subplot</code></li>
<li><code>mpl.gridspec.GridSpec</code></li>
<li><code>mpl.axes.Axes</code></li>
</ol>
<p>Let&rsquo;s try and figure out what these functions / classes do.</p>
<h1 id="what-is-a-figure-and-what-are-axes">What is a <code>Figure</code>? And what are <code>Axes</code>?<a class="headerlink" href="#what-is-a-figure-and-what-are-axes" title="Link to this heading">#</a></h1>
<p>A <a href="https://matplotlib.org/api/_as_gen/matplotlib.pyplot.figure.html?highlight=figure#matplotlib.pyplot.figure"><code>Figure</code></a> in Matplotlib is simply your main (imaginary) canvas. This is where you will be doing all your plotting / drawing / putting images and what not. This is the central object with which you will always be interacting. A figure has a size defined for it at the time of creation.</p>
<p>You can define a figure like so (both statements are equivalent):</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">figure</span><span class="o">.</span><span class="n">Figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># OR</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span></span></span></code></pre>
</div>
<p>Notice the word <em>imaginary</em> above. What this means is that a Figure by itself does not have any place for you to plot. You need to attach/add an <a href="https://matplotlib.org/api/axes_api.html?highlight=matplotlib.axes.axes#matplotlib.axes.Axes"><code>Axes</code></a> to it to do any kind of plotting. You can put as many <code>Axes</code> objects as you want inside of any <code>Figure</code> you have created.</p>
<p>An <code>Axes</code>:</p>
<ol>
<li>Has a space (like a blank Page) where you can draw/plot data.</li>
<li>A parent <code>Figure</code></li>
<li>Has properties stating where it will be placed inside it&rsquo;s parent <code>Figure</code>.</li>
<li>Has methods to draw/plot different kinds of data in different ways and add custom styles.</li>
</ol>
<p>You can create an <code>Axes</code> like so (both statements are equivalent):</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax1</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">axes</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">],</span> <span class="n">facecolor</span><span class="o">=</span><span class="s2">&#34;red&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># OR</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">,</span> <span class="mf">0.8</span><span class="p">],</span> <span class="n">facecolor</span><span class="o">=</span><span class="s2">&#34;red&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1">#</span></span></span></code></pre>
</div>
<p>The first parameter <code>fig</code> is simply a pointer to the parent <code>Figure</code> to which an Axes will belong.<br>
The second parameter <code>rect</code> has four numbers : <code>[left_position, bottom_position, height, width]</code> to define the position of the <code>Axes</code> inside the <code>Figure</code> and the height and width <em>with respect to the <code>Figure</code></em>. All these numbers are expressed in percentages.</p>
<p>A <code>Figure</code> simply holds a given number of <code>Axes</code> at any point of time</p>
<p>We will go into some of these design decisions in a few moments'</p>
<h1 id="recreating-pltsubplots-with-basic-matplotlib-functionality">Recreating <code>plt.subplots</code> with basic Matplotlib functionality<a class="headerlink" href="#recreating-pltsubplots-with-basic-matplotlib-functionality" title="Link to this heading">#</a></h1>
<p>We will try and recreate the below plot using Matplotlib primitives as a way to understand them better. We&rsquo;ll try and be a slightly creative by deviating a bit though.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">suptitle</span><span class="p">(</span><span class="s2">&#34;2x2 Grid&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<pre><code>Text(0.5, 0.98, '2x2 Grid')
</code></pre>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_20_1.png" alt="png"></p>
<h1 id="lets-create-our-first-plot-using-matplotlib-primitives">Let&rsquo;s create our first plot using Matplotlib primitives:<a class="headerlink" href="#lets-create-our-first-plot-using-matplotlib-primitives" title="Link to this heading">#</a></h1>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># We first need a figure, an imaginary canvas to put things on</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">Figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Let&#39;s start with two Axes with an arbitrary position and size</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mf">0.3</span><span class="p">,</span> <span class="mf">0.3</span><span class="p">,</span> <span class="mf">0.4</span><span class="p">,</span> <span class="mf">0.4</span><span class="p">],</span> <span class="n">facecolor</span><span class="o">=</span><span class="s2">&#34;red&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="n">facecolor</span><span class="o">=</span><span class="s2">&#34;blue&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Now you need to add the <code>Axes</code> to <code>fig</code>. You should stop right here and think about why would there be a need to do this when <code>fig</code> is already a parent of <code>ax1</code> and <code>ax2</code>? Let&rsquo;s do this anyway and we&rsquo;ll go into the details afterwards.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">(</span><span class="n">ax2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">(</span><span class="n">ax1</span><span class="p">)</span></span></span></code></pre>
</div>
<pre><code>&lt;matplotlib.axes._axes.Axes at 0x1211dead0&gt;
</code></pre>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># As you can see the Axes are exactly where we specified.</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_25_0.png" alt="png"></p>
<p>That means you can do this now:</p>
<blockquote>
<p>Remark: Notice the <code>ax.reverse()</code> call in the snippet below. If I hadn&rsquo;t done that, the biggest plot would be placed in the end on top of every other plot and you would just see a single, blank &lsquo;cyan&rsquo; colored plot.</p>
</blockquote>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">sizes</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mf">0.02</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">50</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">color</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">sizes</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="mi">255</span><span class="p">)))[</span><span class="mi">2</span><span class="p">:]</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">color</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">color</span> <span class="o">=</span> <span class="s2">&#34;0&#34;</span> <span class="o">+</span> <span class="n">color</span>
</span></span><span class="line"><span class="cl">    <span class="n">color</span> <span class="o">=</span> <span class="s2">&#34;#99&#34;</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">color</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">plt</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">sizes</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">sizes</span><span class="p">[</span><span class="n">i</span><span class="p">]],</span> <span class="n">facecolor</span><span class="o">=</span><span class="n">color</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">axes</span> <span class="ow">in</span> <span class="n">ax</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">(</span><span class="n">axes</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_27_0.png" alt="png"></p>
<p>The above example demonstrates why it is important to decouple the process of creation of an <code>Axes</code> and actually putting it onto a <code>Figure</code>.</p>
<p>Also, you can remove an <code>Axes</code> from the canvas area of a <code>Figure</code> like so:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">delaxes</span><span class="p">(</span><span class="n">ax</span><span class="p">)</span></span></span></code></pre>
</div>
<p>This can be useful when you want to compare the same primary data (GDP) to several secondary data sources (education, spending, etc.) one by one (you&rsquo;ll need to add and delete each graph from the Figure in succession)<br>
I also encourage you to look into the documentation for <code>Figure</code> and <code>Axes</code> and glance over the several methods available to them. This will help you know what parts of the wheel you do not need to rebuild when you&rsquo;re working with these objects the next time.</p>
<h2 id="recreating-our-subplots-literally-from-scratch">Recreating our subplots literally from scratch<a class="headerlink" href="#recreating-our-subplots-literally-from-scratch" title="Link to this heading">#</a></h2>
<p>This should now make sense. We can now create our original <code>plt.subplots(2, 2)</code> example using the knowledge we have thus gained so far.<br>
(Although, this is definitely not the most convenient way to do this)</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">figure</span><span class="o">.</span><span class="n">Figure</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">suptitle</span><span class="p">(</span><span class="s2">&#34;Recreating plt.subplots(2, 2)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax1</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">axes</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">axes</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax3</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">axes</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mf">0.5</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax4</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">axes</span><span class="o">.</span><span class="n">Axes</span><span class="p">(</span><span class="n">fig</span><span class="o">=</span><span class="n">fig</span><span class="p">,</span> <span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">,</span> <span class="mf">0.42</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">(</span><span class="n">ax1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">(</span><span class="n">ax2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">(</span><span class="n">ax3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">(</span><span class="n">ax4</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_30_0.png" alt="png"></p>
<h2 id="using-gridspecgridspec">Using <code>gridspec.GridSpec</code><a class="headerlink" href="#using-gridspecgridspec" title="Link to this heading">#</a></h2>
<p>Docs : <a href="https://matplotlib.org/api/_as_gen/matplotlib.gridspec.GridSpec.html#matplotlib.gridspec.GridSpec">https://matplotlib.org/api/_as_gen/matplotlib.gridspec.GridSpec.html#matplotlib.gridspec.GridSpec</a></p>
<p><code>GridSpec</code> objects allow us more intuitive control over how our plot is exactly divided into subplots and what the size of each <code>Axes</code> is.<br>
You can essentially decide a <strong>Grid</strong> which all your <code>Axes</code> will conform to when laying themselves over.<br>
Once you define a grid, or <code>GridSpec</code> so to say, you can use that object to <em>generate</em> new <code>Axes</code> conforming to the grid which you can then add to your <code>Figure</code></p>
<p>Lets see how all of this works in code:</p>
<p>You can define a <code>GridSpec</code> object like so (both statements are equivalent):</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">gridspec</span><span class="o">.</span><span class="n">GridSpec</span><span class="p">(</span><span class="n">nrows</span><span class="p">,</span> <span class="n">ncols</span><span class="p">,</span> <span class="n">width_ratios</span><span class="p">,</span> <span class="n">height_ratios</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># OR</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">GridSpec</span><span class="p">(</span><span class="n">nrows</span><span class="p">,</span> <span class="n">ncols</span><span class="p">,</span> <span class="n">width_ratios</span><span class="p">,</span> <span class="n">height_ratios</span><span class="p">)</span></span></span></code></pre>
</div>
<p>More specifically:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">GridSpec</span><span class="p">(</span><span class="n">nrows</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">ncols</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">width_ratios</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="n">height_ratios</span><span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span></span></span></code></pre>
</div>
<p><code>nrows</code> and <code>ncols</code> are pretty self explanatory. <code>width_ratios</code> determines the relative width of each column. <code>height_ratios</code> follows along the same lines.
The whole <code>grid</code> will always distribute itself using all the space available to it inside of a figure (things change up a bit when you have multiple <code>GridSpec</code> objects for a single figure, but that&rsquo;s for you to explore!). And inside of a <code>grid</code>, all the Axes will conform to the sizes and ratios defined already</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Taken from https://matplotlib.org/gallery/userdemo/demo_gridspec03.html#sphx-glr-gallery-userdemo-demo-gridspec03-py
</span></span></span><span class="line"><span class="cl"><span class="s2">    takes a figure and puts an &#39;axN&#39; label in the center of each Axes
</span></span></span><span class="line"><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">ax</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="s2">&#34;ax</span><span class="si">%d</span><span class="s2">&#34;</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="n">va</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s2">&#34;center&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">ax</span><span class="o">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">labelbottom</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">labelleft</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span></span></span></code></pre>
</div>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># We will try and vary axis sizes here just to see what happens</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">gridspec</span><span class="o">.</span><span class="n">GridSpec</span><span class="p">(</span><span class="n">nrows</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">ncols</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">width_ratios</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="n">height_ratios</span><span class="o">=</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span></span></span></code></pre>
</div>
<pre><code>&lt;Figure size 576x396 with 0 Axes&gt;
</code></pre>
<p>You can pass <code>GridSpec</code> objects to a <code>Figure</code> to create subplots in your desired sizes and proportions like so :<br>
Notice how the sizes of the <code>Axes</code> relates to the ratios we defined when creating the Grid.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span><span class="p">,</span> <span class="n">ax2</span><span class="p">,</span> <span class="n">ax3</span><span class="p">,</span> <span class="n">ax4</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">3</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_36_0.png" alt="png"></p>
<p>Doing the same thing in a simpler way</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">add_gs_to_fig</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">gs</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Adds all `SubplotSpec`s in `gs` to `fig`&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">gs</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">g</span><span class="p">)</span></span></span></code></pre>
</div>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">add_gs_to_fig</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">gs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_39_0.png" alt="png"></p>
<p>That means you can now do this:<br>
(Notice how the <code>Axes</code> sizes increase from top-left to bottom-right)</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">14</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">length</span> <span class="o">=</span> <span class="mi">6</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">GridSpec</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">nrows</span><span class="o">=</span><span class="n">length</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">ncols</span><span class="o">=</span><span class="n">length</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">width_ratios</span><span class="o">=</span><span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)),</span>
</span></span><span class="line"><span class="cl">    <span class="n">height_ratios</span><span class="o">=</span><span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)),</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">add_gs_to_fig</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">gs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">ax</span> <span class="ow">in</span> <span class="n">fig</span><span class="o">.</span><span class="n">axes</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">ys</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_41_0.png" alt="png"></p>
<h2 id="a-very-unexpected-observation-which-gives-us-yet-more-clarity-and-power">A very unexpected observation: (which gives us yet more clarity, and Power)<a class="headerlink" href="#a-very-unexpected-observation-which-gives-us-yet-more-clarity-and-power" title="Link to this heading">#</a></h2>
<p>Notice how after each print operation, different addresses get printed for each <code>gs</code> object.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">gs</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span></span></span></code></pre>
</div>
<pre><code>(&lt;matplotlib.gridspec.SubplotSpec at 0x1282a9e50&gt;,
 &lt;matplotlib.gridspec.SubplotSpec at 0x12942add0&gt;,
 &lt;matplotlib.gridspec.SubplotSpec at 0x12942a750&gt;,
 &lt;matplotlib.gridspec.SubplotSpec at 0x12a727e10&gt;)
</code></pre>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">gs</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span></span></span></code></pre>
</div>
<pre><code>(&lt;matplotlib.gridspec.SubplotSpec at 0x127d5c6d0&gt;,
 &lt;matplotlib.gridspec.SubplotSpec at 0x12b6d0b10&gt;,
 &lt;matplotlib.gridspec.SubplotSpec at 0x129fc6390&gt;,
 &lt;matplotlib.gridspec.SubplotSpec at 0x129fc6a50&gt;)
</code></pre>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span></span></span></code></pre>
</div>
<pre><code>&lt;matplotlib.gridspec.SubplotSpec object at 0x12951a610&gt; &lt;matplotlib.gridspec.SubplotSpec object at 0x12951a890&gt; &lt;matplotlib.gridspec.SubplotSpec object at 0x12951ac10&gt; &lt;matplotlib.gridspec.SubplotSpec object at 0x12951a150&gt;
</code></pre>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">gs</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span></span></span></code></pre>
</div>
<pre><code>&lt;matplotlib.gridspec.SubplotSpec object at 0x128fad4d0&gt; &lt;matplotlib.gridspec.SubplotSpec object at 0x1291ebbd0&gt; &lt;matplotlib.gridspec.SubplotSpec object at 0x1294f9850&gt; &lt;matplotlib.gridspec.SubplotSpec object at 0x128106250&gt;
</code></pre>
<p><strong>Lets understand why this happens:</strong></p>
<p><em>Notice how a group of <code>gs</code> objects indexed into at the same time also produces just one object instead of multiple objects</em></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">gs</span><span class="p">[:,</span> <span class="p">:],</span> <span class="n">gs</span><span class="p">[:,</span> <span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="c1"># both output just one object each</span></span></span></code></pre>
</div>
<pre><code>(&lt;matplotlib.gridspec.SubplotSpec at 0x128116e50&gt;,
 &lt;matplotlib.gridspec.SubplotSpec at 0x128299290&gt;)
</code></pre>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># Lets try another `gs` object, this time a little more crowded</span>
</span></span><span class="line"><span class="cl"><span class="c1"># I chose the ratios randomly</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">gridspec</span><span class="o">.</span><span class="n">GridSpec</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">nrows</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">ncols</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">width_ratios</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="n">height_ratios</span><span class="o">=</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre>
</div>
<p><em>All these operations print just one object. What is going on here?</em></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">gs</span><span class="p">[:,</span> <span class="mi">0</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">1</span><span class="p">:,</span> <span class="p">:</span><span class="mi">2</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">gs</span><span class="p">[:,</span> <span class="p">:])</span></span></span></code></pre>
</div>
<pre><code>&lt;matplotlib.gridspec.SubplotSpec object at 0x12a075fd0&gt;
&lt;matplotlib.gridspec.SubplotSpec object at 0x128cf0990&gt;
&lt;matplotlib.gridspec.SubplotSpec object at 0x12a075fd0&gt;
</code></pre>
<p>Let&rsquo;s try and add subplots to our <code>Figure</code> to <code>see</code> what&rsquo;s going on.<br>
We&rsquo;ll do a few different permutations to get an exact idea.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">ax1</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[:</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax3</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[:,</span> <span class="mi">1</span><span class="p">:])</span>
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_54_0.png" alt="png"></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ax1 = fig.add_subplot(gs[:2, 0])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax2</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax3</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[:,</span> <span class="mi">1</span><span class="p">:])</span>
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_55_0.png" alt="png"></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ax1 = fig.add_subplot(gs[:2, 0])</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ax2 = fig.add_subplot(gs[2, 0])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax3</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[:,</span> <span class="mi">1</span><span class="p">:])</span>
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_56_0.png" alt="png"></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ax1 = fig.add_subplot(gs[:2, 0])</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ax2 = fig.add_subplot(gs[2, 0])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax3</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[:,</span> <span class="mi">1</span><span class="p">:])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Notice the line below : You can overlay Axes using `GridSpec` too</span>
</span></span><span class="line"><span class="cl"><span class="n">ax4</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="mi">2</span><span class="p">:,</span> <span class="mi">1</span><span class="p">:])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax4</span><span class="o">.</span><span class="n">set_facecolor</span><span class="p">(</span><span class="s2">&#34;orange&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_57_0.png" alt="png"></p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">add_gs_to_fig</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">gs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_58_0.png" alt="png"></p>
<p>Here&rsquo;s a bullet point summary of what this means:</p>
<ol>
<li><code>gs</code> can be used as a sort of a <code>factory</code> for different kinds of <code>Axes</code>.</li>
<li>You give this <code>factory</code> an order by indexing into particular areas of the <code>Grid</code>. It gives back a single <code>SubplotSpec</code> (check <code>type(gs[0]</code>) object that helps you create an <code>Axes</code> which has all of the area you indexed into combined into one unit.</li>
<li>Your <code>height</code> and <code>width</code> ratios for the indexed portion will determine the size of the <code>Axes</code> that gets generated.</li>
<li><code>Axes</code> will maintain relative proportions according to your <code>height</code> and <code>width</code> ratios always.</li>
<li>For all these reasons, I like <code>GridSpec</code>!</li>
</ol>
<p>This ability to create different grid variations that <code>GridSpec</code> provides is probably the reason for that anomaly we saw a while ago (printing different Addresses).</p>
<p>It creates new objects every time you index into it because it will be very troublesome to store all permutations of <code>SubplotSpec</code> objects into one group in memory (try and count permutations for a <code>GridSpec</code> of 10x10 and you&rsquo;ll know why)</p>
<hr>
<h2 id="now-lets-finally-create-pltsubplots22-once-again-using-gridspec">Now let&rsquo;s finally create <code>plt.subplots(2,2)</code> once again using GridSpec<a class="headerlink" href="#now-lets-finally-create-pltsubplots22-once-again-using-gridspec" title="Link to this heading">#</a></h2>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">gs</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">.</span><span class="n">gridspec</span><span class="o">.</span><span class="n">GridSpec</span><span class="p">(</span><span class="n">nrows</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">ncols</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">add_gs_to_fig</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">gs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">annotate_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">suptitle</span><span class="p">(</span><span class="s2">&#34;We&#39;re done!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;yayy&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<pre><code>yayy
</code></pre>
<p><img src="/matplotlib/an-inquiry-into-matplotlib-figures/output_61_1.png" alt="png"></p>
<h1 id="what-you-should-try">What you should try:<a class="headerlink" href="#what-you-should-try" title="Link to this heading">#</a></h1>
<hr>
<p>Here&rsquo;s a few things I think you should go ahead and explore:</p>
<ol>
<li>Multiple <code>GridSpec</code> objects for the Same Figure.</li>
<li>Deleting and adding <code>Axes</code> effectively and meaningfully.</li>
<li>All the methods available for <code>mpl.figure.Figure</code> and <code>mpl.axes.Axes</code> allowing us to manipulate their properties.</li>
<li>Kaggle Learn&rsquo;s Data visualization course is a great place to learn effective plotting using Python</li>
<li>Armed with knowledge, you will be able to use other plotting libraries such as <code>seaborn</code>, <code>plotly</code>, <code>pandas</code> and <code>altair</code> with much more flexibility (you can pass an <code>Axes</code> object to all their plotting functions). I encourage you to explore these libraries too.</li>
</ol>
<p>This is the first time I&rsquo;ve written any technical guide for the internet, it may not be as clean as tutorials generally are. But, I&rsquo;m open to all the constructive criticism that you may have for me (drop me an email on <a href="mailto:akashpalrecha@gmail.com">akashpalrecha@gmail.com</a>)</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Custom 3D engine in Matplotlib]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/custom-3d-engine/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="related" type="text/html" title="Creating the Warming Stripes in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/matplotlib-in-data-driven-seo/?utm_source=atom_feed" rel="related" type="text/html" title="Matplotlib in Data Driven SEO" />
                <link href="https://blog.scientific-python.org/matplotlib/using-matplotlib-to-advocate-for-postdocs/?utm_source=atom_feed" rel="related" type="text/html" title="Using Matplotlib to Advocate for Postdocs" />
            
                <id>https://blog.scientific-python.org/matplotlib/custom-3d-engine/</id>
            
            
            <published>2019-12-18T09:05:32+01:00</published>
            <updated>2019-12-18T09:05:32+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>3D rendering is really easy once you&rsquo;ve understood a few concepts. To demonstrate that, we&rsquo;ll design a simple custom 3D engine that with 60 lines of Python and one Matplotlib call. That is, we&rsquo;ll render the bunny without using the 3D axis.</blockquote><p><img src="/matplotlib/custom-3d-engine/bunny.jpg" alt="A colourful outline of a bunny."></p>
<p>Matplotlib has a really nice <a href="https://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html">3D
interface</a> with many
capabilities (and some limitations) that is quite popular among users. Yet, 3D
is still considered to be some kind of black magic for some users (or maybe
for the majority of users). I would thus like to explain in this post that 3D
rendering is really easy once you&rsquo;ve understood a few concepts. To demonstrate
that, we&rsquo;ll render the bunny above with 60 lines of Python and one Matplotlib
call. That is, without using the 3D axis.</p>
<p><strong>Advertisement</strong>: This post comes from an upcoming open access book on
scientific visualization using Python and Matplotlib. If you want to
support my work and have an early access to the book, go to
<a href="https://github.com/rougier/scientific-visualization-book">https://github.com/rougier/scientific-visualization-book</a>.</p>
<h1 id="loading-the-bunny">Loading the bunny<a class="headerlink" href="#loading-the-bunny" title="Link to this heading">#</a></h1>
<p>First things first, we need to load our model. We&rsquo;ll use a <a href="/matplotlib/custom-3d-engine/bunny.obj">simplified
version</a> of the <a href="https://en.wikipedia.org/wiki/Stanford_bunny">Stanford
bunny</a>. The file uses the
<a href="https://en.wikipedia.org/wiki/Wavefront_.obj_file">wavefront format</a> which is
one of the simplest format, so let&rsquo;s make a very simple (but error-prone)
loader that will just do the job for this post (and this model):</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">V</span><span class="p">,</span> <span class="n">F</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">&#34;bunny.obj&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">   <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">f</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
</span></span><span class="line"><span class="cl">       <span class="k">if</span> <span class="n">line</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;#&#39;</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">           <span class="k">continue</span>
</span></span><span class="line"><span class="cl">       <span class="n">values</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">       <span class="k">if</span> <span class="ow">not</span> <span class="n">values</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">           <span class="k">continue</span>
</span></span><span class="line"><span class="cl">       <span class="k">if</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;v&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">           <span class="n">V</span><span class="o">.</span><span class="n">append</span><span class="p">([</span><span class="nb">float</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">values</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">4</span><span class="p">]])</span>
</span></span><span class="line"><span class="cl">       <span class="k">elif</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">&#39;f&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">           <span class="n">F</span><span class="o">.</span><span class="n">append</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">values</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">4</span><span class="p">]])</span>
</span></span><span class="line"><span class="cl"><span class="n">V</span><span class="p">,</span> <span class="n">F</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">V</span><span class="p">),</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">F</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span></span></span></code></pre>
</div>
<p><code>V</code> is now a set of vertices (3D points if you prefer) and <code>F</code> is a set of
faces (= triangles). Each triangle is described by 3 indices relatively to the
vertices array. Now, let&rsquo;s normalize the vertices such that the overall bunny
fits the unit box:</p>

<div class="highlight">
  <pre>V = (V-(V.max(0)&#43;V.min(0))/2)/max(V.max(0)-V.min(0))</pre>
</div>

<p>Now, we can have a first look at the model by getting only the x,y coordinates of the vertices and get rid of the z coordinate. To do this we can use the powerful
<a href="https://matplotlib.org/3.1.1/api/collections_api.html#matplotlib.collections.PolyCollection">PolyCollection</a>
object that allow to render efficiently a collection of non-regular
polygons. Since, we want to render a bunch of triangles, this is a perfect
match. So let&rsquo;s first extract the triangles and get rid of the <code>z</code> coordinate:</p>

<div class="highlight">
  <pre>T = V[F][...,:2]</pre>
</div>

<p>And we can now render it:</p>

<div class="highlight">
  <pre>fig = plt.figure(figsize=(6,6))
ax = fig.add_axes([0,0,1,1], xlim=[-1,&#43;1], ylim=[-1,&#43;1],
                  aspect=1, frameon=False)
collection = PolyCollection(T, closed=True, linewidth=0.1,
                            facecolor=&#34;None&#34;, edgecolor=&#34;black&#34;)
ax.add_collection(collection)
plt.show()</pre>
</div>

<p>You should obtain something like this (<a href="/matplotlib/custom-3d-engine/bunny-1.py">bunny-1.py</a>):</p>
<p><img src="/matplotlib/custom-3d-engine/bunny-1.png" alt="A black and white outline of a bunny facing left side."></p>
<h1 id="perspective-projection">Perspective Projection<a class="headerlink" href="#perspective-projection" title="Link to this heading">#</a></h1>
<p>The rendering we&rsquo;ve just made is actually an <a href="https://en.wikipedia.org/wiki/Orthographic_projection">orthographic
projection</a> while the
top bunny uses a <a href="https://en.wikipedia.org/wiki/3D_projection#Perspective_projection">perspective projection</a>:</p>
<p><img src="/matplotlib/custom-3d-engine/projections.png" alt="Difference in perspective projection and orthographic projection. The near clip plane appears smaller in the perspective projective than in the orthographic projection."></p>
<p>In both cases, the proper way of defining a projection is first to define a
viewing volume, that is, the volume in the 3D space we want to render on the
screen. To do that, we need to consider 6 clipping planes (left, right, top,
bottom, far, near) that enclose the viewing volume (frustum) relatively to the
camera. If we define a camera position and a viewing direction, each plane can
be described by a single scalar. Once we have this viewing volume, we can
project onto the screen using either the orthographic or the perspective
projection.</p>
<p>Fortunately for us, these projections are quite well known and can be expressed
using 4x4 matrices:</p>

<div class="highlight">
  <pre>def frustum(left, right, bottom, top, znear, zfar):
    M = np.zeros((4, 4), dtype=np.float32)
    M[0, 0] = &#43;2.0 * znear / (right - left)
    M[1, 1] = &#43;2.0 * znear / (top - bottom)
    M[2, 2] = -(zfar &#43; znear) / (zfar - znear)
    M[0, 2] = (right &#43; left) / (right - left)
    M[2, 1] = (top &#43; bottom) / (top - bottom)
    M[2, 3] = -2.0 * znear * zfar / (zfar - znear)
    M[3, 2] = -1.0
    return M

def perspective(fovy, aspect, znear, zfar):
    h = np.tan(0.5*radians(fovy)) * znear
    w = h * aspect
    return frustum(-w, w, -h, h, znear, zfar)</pre>
</div>

<p>For the perspective projection, we also need to specify the aperture angle that
(more or less) sets the size of the near plane relatively to the far
plane. Consequently, for high apertures, you&rsquo;ll get a lot of &ldquo;deformations&rdquo;.</p>
<p>However, if you look at the two functions above, you&rsquo;ll realize they return 4x4
matrices while our coordinates are 3D. How to use these matrices then ? The
answer is <a href="https://en.wikipedia.org/wiki/Homogeneous_coordinates">homogeneous
coordinates</a>. To make
a long story short, homogeneous coordinates are best to deal with transformation
and projections in 3D. In our case, because we&rsquo;re dealing with vertices (and
not vectors), we only need to add 1 as the fourth coordinate (<code>w</code>) to all our
vertices. Then we can apply the perspective transformation using the dot
product.</p>

<div class="highlight">
  <pre>V = np.c_[V, np.ones(len(V))] @ perspective(25,1,1,100).T</pre>
</div>

<p>Last step, we need to re-normalize the homogeneous coordinates. This means we
divide each transformed vertices with the last component (<code>w</code>) such as to
always have <code>w</code>=1 for each vertices.</p>

<div class="highlight">
  <pre>V /= V[:,3].reshape(-1,1)</pre>
</div>

<p>Now we can display the result again (<a href="/matplotlib/custom-3d-engine/bunny-2.py">bunny-2.py</a>):</p>
<p><img src="/matplotlib/custom-3d-engine/bunny-2.png" alt=""></p>
<p>Oh, weird result. What&rsquo;s wrong? What is wrong is that the camera is actually
inside the bunny. To have a proper rendering, we need to move the bunny away
from the camera or move the camera away from the bunny. Let&rsquo;s do the latter. The
camera is currently positioned at (0,0,0) and looking up in the z direction
(because of the frustum transformation). We thus need to move the camera away a
little bit in the z negative direction and <strong>before the perspective
transformation</strong>:</p>

<div class="highlight">
  <pre>V = V - (0,0,3.5)
V = np.c_[V, np.ones(len(V))] @ perspective(25,1,1,100).T
V /= V[:,3].reshape(-1,1)</pre>
</div>

<p>An now you should obtain (<a href="/matplotlib/custom-3d-engine/bunny-3.py">bunny-3.py</a>):</p>
<p><img src="/matplotlib/custom-3d-engine/bunny-3.png" alt=""></p>
<h1 id="model-view-projection-mvp">Model, view, projection (MVP)<a class="headerlink" href="#model-view-projection-mvp" title="Link to this heading">#</a></h1>
<p>It might be not obvious, but the last rendering is actually a perspective
transformation. To make it more obvious, we&rsquo;ll rotate the bunny around. To do
that, we need some rotation matrices (4x4) and we can as well define the
translation matrix in the meantime:</p>

<div class="highlight">
  <pre>def translate(x, y, z):
    return np.array([[1, 0, 0, x],
                     [0, 1, 0, y],
                     [0, 0, 1, z],
                     [0, 0, 0, 1]], dtype=float)

def xrotate(theta):
    t = np.pi * theta / 180
    c, s = np.cos(t), np.sin(t)
    return np.array([[1, 0,  0, 0],
                     [0, c, -s, 0],
                     [0, s,  c, 0],
                     [0, 0,  0, 1]], dtype=float)

def yrotate(theta):
    t = np.pi * theta / 180
    c, s = np.cos(t), np.sin(t)
    return  np.array([[ c, 0, s, 0],
                      [ 0, 1, 0, 0],
                      [-s, 0, c, 0],
                      [ 0, 0, 0, 1]], dtype=float)</pre>
</div>

<p>We&rsquo;ll now decompose the transformations we want to apply in term of model
(local transformations), view (global transformations) and projection such that
we can compute a global MVP matrix that will do everything at once:</p>

<div class="highlight">
  <pre>model = xrotate(20) @ yrotate(45)
view  = translate(0,0,-3.5)
proj  = perspective(25, 1, 1, 100)
MVP   = proj  @ view  @ model</pre>
</div>

<p>and we now write:</p>

<div class="highlight">
  <pre>V = np.c_[V, np.ones(len(V))] @ MVP.T
V /= V[:,3].reshape(-1,1)</pre>
</div>

<p>You should obtain (<a href="/matplotlib/custom-3d-engine/bunny-4.py">bunny-4.py</a>):</p>
<p><img src="/matplotlib/custom-3d-engine/bunny-4.png" alt=""></p>
<p>Let&rsquo;s now play a bit with the aperture such that you can see the difference.
Note that we also have to adapt the distance to the camera in order for the bunnies to have the same apparent size (<a href="/matplotlib/custom-3d-engine/bunny-5.py">bunny-5.py</a>):</p>
<p><img src="/matplotlib/custom-3d-engine/bunny-5.png" alt=""></p>
<h1 id="depth-sorting">Depth sorting<a class="headerlink" href="#depth-sorting" title="Link to this heading">#</a></h1>
<p>Let&rsquo;s try now to fill the triangles (<a href="/matplotlib/custom-3d-engine/bunny-6.py">bunny-6.py</a>):</p>
<p><img src="/matplotlib/custom-3d-engine/bunny-6.png" alt=""></p>
<p>As you can see, the result is &ldquo;interesting&rdquo; and totally wrong. The problem is
that the PolyCollection will draw the triangles in the order they are given
while we would like to have them from back to front. This means we need to sort
them according to their depth. The good news is that we already computed this
information when we applied the MVP transformation. It is stored in the new z
coordinates. However, these z values are vertices based while we need to sort
the triangles. We&rsquo;ll thus take the mean z value as being representative of the
depth of a triangle. If triangles are relatively small and do not intersect,
this works beautifully:</p>

<div class="highlight">
  <pre>T =  V[:,:,:2]
Z = -V[:,:,2].mean(axis=1)
I = np.argsort(Z)
T = T[I,:]</pre>
</div>

<p>And now everything is rendered right (<a href="/matplotlib/custom-3d-engine/bunny-7.py">bunny-7.py</a>):</p>
<p><img src="/matplotlib/custom-3d-engine/bunny-7.png" alt=""></p>
<p>Let&rsquo;s add some colors using the depth buffer. We&rsquo;ll color each triangle
according to it depth. The beauty of the PolyCollection object is that you can
specify the color of each of the triangle using a NumPy array, so let&rsquo;s just do
that:</p>

<div class="highlight">
  <pre>zmin, zmax = Z.min(), Z.max()
Z = (Z-zmin)/(zmax-zmin)
C = plt.get_cmap(&#34;magma&#34;)(Z)
I = np.argsort(Z)
T, C = T[I,:], C[I,:]</pre>
</div>

<p>And now everything is rendered right (<a href="/matplotlib/custom-3d-engine/bunny-8.py">bunny-8.py</a>):</p>
<p><img src="/matplotlib/custom-3d-engine/bunny-8.png" alt=""></p>
<p>The final script is 57 lines (but hardly readable):</p>

<div class="highlight">
  <pre>import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection

def frustum(left, right, bottom, top, znear, zfar):
    M = np.zeros((4, 4), dtype=np.float32)
    M[0, 0] = &#43;2.0 * znear / (right - left)
    M[1, 1] = &#43;2.0 * znear / (top - bottom)
    M[2, 2] = -(zfar &#43; znear) / (zfar - znear)
    M[0, 2] = (right &#43; left) / (right - left)
    M[2, 1] = (top &#43; bottom) / (top - bottom)
    M[2, 3] = -2.0 * znear * zfar / (zfar - znear)
    M[3, 2] = -1.0
    return M
def perspective(fovy, aspect, znear, zfar):
    h = np.tan(0.5*np.radians(fovy)) * znear
    w = h * aspect
    return frustum(-w, w, -h, h, znear, zfar)
def translate(x, y, z):
    return np.array([[1, 0, 0, x], [0, 1, 0, y],
                     [0, 0, 1, z], [0, 0, 0, 1]], dtype=float)
def xrotate(theta):
    t = np.pi * theta / 180
    c, s = np.cos(t), np.sin(t)
    return np.array([[1, 0,  0, 0], [0, c, -s, 0],
                     [0, s,  c, 0], [0, 0,  0, 1]], dtype=float)
def yrotate(theta):
    t = np.pi * theta / 180
    c, s = np.cos(t), np.sin(t)
    return  np.array([[ c, 0, s, 0], [ 0, 1, 0, 0],
                      [-s, 0, c, 0], [ 0, 0, 0, 1]], dtype=float)
V, F = [], []
with open(&#34;bunny.obj&#34;) as f:
    for line in f.readlines():
        if line.startswith(&#39;#&#39;):  continue
        values = line.split()
        if not values:            continue
        if values[0] == &#39;v&#39;:      V.append([float(x) for x in values[1:4]])
        elif values[0] == &#39;f&#39; :   F.append([int(x) for x in values[1:4]])
V, F = np.array(V), np.array(F)-1
V = (V-(V.max(0)&#43;V.min(0))/2) / max(V.max(0)-V.min(0))
MVP = perspective(25,1,1,100) @ translate(0,0,-3.5) @ xrotate(20) @ yrotate(45)
V = np.c_[V, np.ones(len(V))]  @ MVP.T
V /= V[:,3].reshape(-1,1)
V = V[F]
T =  V[:,:,:2]
Z = -V[:,:,2].mean(axis=1)
zmin, zmax = Z.min(), Z.max()
Z = (Z-zmin)/(zmax-zmin)
C = plt.get_cmap(&#34;magma&#34;)(Z)
I = np.argsort(Z)
T, C = T[I,:], C[I,:]
fig = plt.figure(figsize=(6,6))
ax = fig.add_axes([0,0,1,1], xlim=[-1,&#43;1], ylim=[-1,&#43;1], aspect=1, frameon=False)
collection = PolyCollection(T, closed=True, linewidth=0.1, facecolor=C, edgecolor=&#34;black&#34;)
ax.add_collection(collection)
plt.show()</pre>
</div>

<p>Now it&rsquo;s your turn to play. Starting from this simple script, you can achieve
interesting results:</p>
<p><img src="/matplotlib/custom-3d-engine/checkered-sphere.png" alt="">
<img src="/matplotlib/custom-3d-engine/platonic-solids.png" alt="">
<img src="/matplotlib/custom-3d-engine/surf.png" alt="">
<img src="/matplotlib/custom-3d-engine/bar.png" alt="">
<img src="/matplotlib/custom-3d-engine/contour.png" alt=""></p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="3d" label="3D" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Matplotlib in Data Driven SEO]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/matplotlib-in-data-driven-seo/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="related" type="text/html" title="Creating the Warming Stripes in Matplotlib" />
                <link href="https://blog.scientific-python.org/matplotlib/using-matplotlib-to-advocate-for-postdocs/?utm_source=atom_feed" rel="related" type="text/html" title="Using Matplotlib to Advocate for Postdocs" />
            
                <id>https://blog.scientific-python.org/matplotlib/matplotlib-in-data-driven-seo/</id>
            
            
            <published>2019-12-04T17:23:24+01:00</published>
            <updated>2019-12-04T17:23:24+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>At Whites Agency we analyze big unstructured data to increases client&rsquo;s online visibility. We share our story of how we used Matplotlib to present the complicated data in a simple and reader-friendly way.</blockquote><p><img src="/matplotlib/matplotlib-in-data-driven-seo/fig4.jpg" alt="A collection of visualizations displaying search engine optimization statistics including 1) a pie chart showing last minute is most popular 2) a bar chart showing popularity on different sites 3) a collection of circles displaying the frequency of sites that have features such as sitelinks and prices 4) a line chart displaying the google search rank for a collection of single word queries from first to twentieth."></p>
<p>Search Engine Optimization (SEO) is a process that aims to increase quantity and quality of website traffic by ensuring a website can be found in search engines for phrases that are relevant to what the site is offering. Google is the most popular search engine in the world and presence in top search results is invaluable for any online business since click rates drop exponentially with ranking position. Since the beginning, specialized entities have been decoding signals that influence position in search engine result page (SERP) focusing on e.g. number of outlinks, presence of keywords or content length. Developed practices typically resulted in better visibility, but needed to be constantly challenged because search engines introduce changes to their algorithms even every day. Since the rapid advancements in Big Data and machine learning finding significant ranking factors became increasingly more difficult. Thus, the whole SEO field required a shift where recommendations are backed up by large scale studies based on real data rather than old-fashioned practices. <a href="https://whites.agency/">Whites Agency</a> focuses strongly on Data-Driven SEO. We run many Big Data analyses which give us insights into multiple optimization opportunities.</p>
<p>Majority of cases we are dealing with right now focus on data harvesting and analysis. Data presentation plays an important part and since the beginning, we needed a tool that would allow us to experiment with different forms of visualizations. Because our organization is Python driven, Matplotlib was a straightforward choice for us. It is a mature project that offers flexibility and control. Among other features, Matplotlib figures can be easily exported not only to raster graphic formats (PNG, JPG) but also to vector ones (SVG, PDF, EPS), creating high-quality images that can be embedded in HTML code, LaTeX or utilized by graphic designers. In one of our projects, Matplotlib was a part of the Python processing pipeline that automatically generated PDF summaries from an HTML template for individual clients. Every data visualization project has the same core presented in the figure below, where data is loaded from the database, processed in pandas or PySpark and finally visualized with Matplotlib.</p>
<p><img src="/matplotlib/matplotlib-in-data-driven-seo/fig1.png" alt="Data Visualization Pipeline at Whites Agency"></p>
<p>In what follows, we would like to share two insights from our studies. All figures were prepared in Matplotlib and in each case we set up a global style (overwritten if necessary):</p>

<div class="highlight">
  <pre>import matplotlib.pyplot as plt
from cycler import cycler

colors = [&#39;#00b2b8&#39;, &#39;#fa5e00&#39;, &#39;#404040&#39;, &#39;#78A3B3&#39;, &#39;#008F8F&#39;, &#39;#ADC9D6&#39;]

plt.rc(&#39;axes&#39;, grid=True, labelcolor=&#39;k&#39;, linewidth=0.8, edgecolor=&#39;#696969&#39;,
    labelweight=&#39;medium&#39;, labelsize=18)
plt.rc(&#39;axes.spines&#39;, left=False, right=False, top=False, bottom=True)
plt.rc(&#39;axes.formatter&#39;, use_mathtext=True)

plt.rcParams[&#39;axes.prop_cycle&#39;] = cycler(&#39;color&#39;, colors)

plt.rc(&#39;grid&#39;, alpha=1.0, color=&#39;#B2B2B2&#39;, linestyle=&#39;dotted&#39;, linewidth=1.0)
plt.rc(&#39;xtick.major&#39;, top=False, width=0.8, size=8.0)
plt.rc(&#39;ytick&#39;, left=False, color=&#39;k&#39;)
plt.rcParams[&#39;xtick.color&#39;] = &#39;k&#39;
plt.rc(&#39;font&#39;,family=&#39;Montserrat&#39;)
plt.rcParams[&#39;font.weight&#39;] = &#39;medium&#39;
plt.rcParams[&#39;xtick.labelsize&#39;] = 13
plt.rcParams[&#39;ytick.labelsize&#39;] = 13
plt.rcParams[&#39;lines.linewidth&#39;] = 2.0</pre>
</div>

<h1 id="case-1-website-speed-performance">Case 1: Website Speed Performance<a class="headerlink" href="#case-1-website-speed-performance" title="Link to this heading">#</a></h1>
<p>Our R&amp;D department analyzed a set of 10,000 potential customer intent phrases from the <em>Electronics</em> (eCommerce) and <em>News</em> domains (5000 phrases each). They scraped data from the Google ranking in a specific location (London, United Kingdom) both for mobile and desktop results [full study available <a href="https://whites.agency/blog/google-lighthouse-study-seo-ranking-factors-in-ecommerce-vs-news/">here</a>]. Based on those data, we distinguished TOP 20 results that appeared in SERPs. Next, each page was audited with the <a href="https://developers.google.com/web/tools/lighthouse">Google Lighthouse tool</a>. Google Lighthouse is an open-source, automated tool for improving the quality of web pages, that among other collects information about website loading time. A single sample from our analysis which shows variations of <em>Time to First Byte</em> (TTFB) as a function of Google position (grouped in threes) is presented below. TTFB measures the time it takes for a user&rsquo;s browser to receive the first byte of page content. Regardless of the device, TTFB score is the lowest for websites that occurred in TOP 3 positions. The difference is significant, especially between TOP 3 and 4-6 results. Therefore, Google favors websites that respond fast and therefore it is advised to invest in website speed optimization.</p>
<p><img src="/matplotlib/matplotlib-in-data-driven-seo/fig2.png" alt="Time to first byte from Lighthouse study performed at Whites Agency."></p>
<p>The figure above uses <code>fill_between</code> function from Matplotlib library to draw colored shade that represents the 40-60th percentile range. A simple line plot with circle markers denotes the median (50th percentile). X-axis labels were assigned manually. The whole style is wrapped into a custom function that allows us to reproduce the whole figure in a single line of code. A sample is presented below:</p>

<div class="highlight">
  <pre>import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap

# --------------------------------------------
# Set double column layout
# --------------------------------------------
fig, axx = plt.subplots(figsize=(20,6), ncols=2)

# --------------------------------------------
# Plot 50th percentile
# --------------------------------------------
line_kws = {
   &#39;lw&#39;: 4.0,
   &#39;marker&#39;: &#39;o&#39;,
   &#39;ms&#39;: 9,
   &#39;markerfacecolor&#39;: &#39;w&#39;,
   &#39;markeredgewidth&#39;: 2,
   &#39;c&#39;: &#39;#00b2b8&#39;
}

# just demonstration
axx[0].plot(x, y, label=&#39;Electronics&#39;, **line_kws)

# --------------------------------------------
# Plot 40-60th percentile
# --------------------------------------------
# make color lighter
cmap = LinearSegmentedColormap.from_list(&#39;whites&#39;, [&#39;#FFFFFF&#39;, &#39;#00b2b8&#39;])

# just demonstration
axx[0].fill_between(
   x, yl, yu,
   color=cmap(0.5),
   label=&#39;_nolegend_&#39;
)

# ---------------------------------------------
# Add x-axis labels
# ---------------------------------------------
# done automatically
xtick_labels = [&#39;1-3&#39;,&#39;4-6&#39;,&#39;7-9&#39;,&#39;10-12&#39;,&#39;13-15&#39;,&#39;16-18&#39;,&#39;19-20&#39;]
for ax in axx:
   ax.set_xticklabels(xtick_labels)

# ----------------------------------------------
# Export figure
# ----------------------------------------------
fig.savefig(&#34;lighthouse.png&#34;, bbox_inches=&#39;tight&#39;, dpi=250)</pre>
</div>

<h1 id="case-2-google-ads-ranking">Case 2: Google Ads ranking<a class="headerlink" href="#case-2-google-ads-ranking" title="Link to this heading">#</a></h1>
<p>Another example let us draw insights from Google&rsquo;s paid campaigns (Ads). Our R&amp;D department scraped the first page in Google for more than 7600 queries and analyzed the ads that were present [study available only in <a href="https://agencjawhites.pl/aktualnosci/ponad-1000-graczy-walczy-o-polskiego-turyste-w-wyszukiwarce-google/">Polish</a>]. The queries were narrowed down to <em>Travel</em> category. At the moment of writing this post, each SERP can have up to 4 ads at the top and up to 3 ads at the bottom. Each ad is associated with a domain and has a headline, description, and optional extensions. Below we present TOP 25 domains with the highest visibility on desktop computers. The Y-axis shows the name of a domain and the X-axis indicates how many ads is linked with particular domain, in total. We repeated the study 3 times and aggregated the counts that is why the scale is much larger than 7600. In this project, the type of plot below allows us to summarize different brands&rsquo; ads campaign strategies and their advertising market shares. For example, <em>itaka</em> and <em>wakacje</em> have the strongest presence both on mobile and desktop and most of their ads appear at the top. The <em>neckermann</em> positions itself are very high, but most of their ads appear at the bottom of search results.</p>
<p><img src="/matplotlib/matplotlib-in-data-driven-seo/fig3.png" alt="TOP 25 domains with the highest visibility on desktop computers."></p>
<p>The figure above is a standard horizontal bar plot that can be reproduced with <code>barh</code> function in Matplotlib. Each y-tick has 4 different pieces (see legend). We also added automatically generated count numbers at the end of each bar for better readability. The code snippet is shown below:</p>

<div class="highlight">
  <pre>import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.colors import LinearSegmentedColormap, PowerNorm

# -----------------------------
# Set default colors
# -----------------------------
blues = LinearSegmentedColormap.from_list(name=&#39;WhitesBlues&#39;, colors=[&#39;#FFFFFF&#39;, &#39;#00B3B8&#39;], gamma=1.0)
oranges = LinearSegmentedColormap.from_list(name=&#39;WhitesOranges&#39;, colors=[&#39;#FFFFFF&#39;, &#39;#FB5E01&#39;], gamma=1.0)

# colors
desktop_top = blues(1.0)
desktop_bottom = oranges(1.0)
mobile_top = blues(0.5)
mobile_bottom = oranges(0.5)

# -----------------------------
# Prepare Figure
# -----------------------------
fig, ax = plt.subplots(figsize=(10,15))
ax.grid(False)

# -----------------------------
# Plot bars
# -----------------------------
# just demonstration

for name in yticklabels:
    # tmp_desktop - DataFrame with desktop data
    # tmp_mobile - DataFrame with mobile data

    ax.barh(cnt, tmp_desktop[&#39;top&#39;], color=desktop_top, height=0.9)
    ax.barh(cnt, tmp_desktop[&#39;bottom&#39;], left=tmp_desktop[&#39;top&#39;], color=desktop_bottom, height=0.9)
    # text counter
    ax.text(tmp_desktop[&#39;all&#39;]&#43;100, cnt, &#34;%d&#34; % tmp_desktop[&#39;all&#39;], horizontalalignment=&#39;left&#39;,
            verticalalignment=&#39;center&#39;, fontsize=10)

    ax.barh(cnt-1, tmp_mobile[&#39;top&#39;], color=mobile_top, height=0.9)
    ax.barh(cnt-1, tmp_mobile[&#39;bottom&#39;], left=tmp_mobile[&#39;top&#39;], color=mobile_bottom, height=0.9)
    ax.text(tmp_mobile[&#39;all&#39;]&#43;100, cnt-1, &#34;%d&#34; % tmp_mobile[&#39;all&#39;], horizontalalignment=&#39;left&#39;,
            verticalalignment=&#39;center&#39;, fontsize=10)


    yticks.append(cnt)

    cnt = cnt - 2.5

# -----------------------------
# set labels
# -----------------------------
ax.set_yticks(yticks)
ax.set_yticklabels(yticklabels)

# -----------------------------
# Add legend manually
# -----------------------------
legend_elements = [
    mpatches.Patch(color=desktop_top, label=&#39;desktop top&#39;),
    mpatches.Patch(color=desktop_bottom, label=&#39;desktop bottom&#39;),
    mpatches.Patch(color=mobile_top, label=&#39;mobile top&#39;),
    mpatches.Patch(color=mobile_bottom, label=&#39;mobile bottom&#39;)
]

ax.legend(handles=legend_elements, fontsize=15)</pre>
</div>

<h1 id="summary">Summary<a class="headerlink" href="#summary" title="Link to this heading">#</a></h1>
<p>This is just a sample from our studies and more can be found on our website. The Matplotlib library meets our needs in terms of visual capabilities and flexibility. It allows us to create standard plots in a single line of code, as well as experiment with different forms of graphs thanks to its lower level features. Thanks to opportunities offered by Matplotlib we may present the complicated data in a simple and reader-friendly way.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="industry" label="industry" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Creating the Warming Stripes in Matplotlib]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/warming-stripes/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/matplotlib/using-matplotlib-to-advocate-for-postdocs/?utm_source=atom_feed" rel="related" type="text/html" title="Using Matplotlib to Advocate for Postdocs" />
            
                <id>https://blog.scientific-python.org/matplotlib/warming-stripes/</id>
            
            
            <published>2019-11-11T09:21:28+01:00</published>
            <updated>2019-11-11T09:21:28+01:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Ed Hawkins made this impressively simple plot to show how global temperatures have risen since 1880. Here is how to recreate it using Matplotlib.</blockquote><p><img src="/matplotlib/warming-stripes/warming-stripes.png" alt="A horizontal bar divided into stripes with colors ranging from white to shades of blue and shades of red. There is a clear tendency of shades of blue on the left side of the bar, and shades of red on the right side of the bar."></p>
<p>Earth&rsquo;s temperatures are rising and nothing shows this in a simpler,
more approachable graphic than the “Warming Stripes”.
Introduced by Prof. Ed Hawkins they show the temperatures either for
the global average or for your region as colored bars from blue to red for the last 170 years, available at <a href="https://showyourstripes.info">#ShowYourStripes</a>.</p>
<p>The stripes have since become the logo of the <a href="https://scientistsforfuture.org">Scientists for Future</a>.
Here is how you can recreate this yourself using Matplotlib.</p>
<p>We are going to use the <a href="https://www.metoffice.gov.uk/hadobs/hadcrut4/index.html">HadCRUT4</a> dataset, published by the Met Office.
It uses combined sea and land surface temperatures.
The dataset used for the warming stripes is the annual global average.</p>
<p>First, let&rsquo;s import everything we are going to use.
The plot will consist of a bar for each year, colored using a custom
color map.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.patches</span> <span class="kn">import</span> <span class="n">Rectangle</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.collections</span> <span class="kn">import</span> <span class="n">PatchCollection</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">matplotlib.colors</span> <span class="kn">import</span> <span class="n">ListedColormap</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="nn">pd</span></span></span></code></pre>
</div>
<p>Then we define our time limits, our reference period for
the neutral color and the range around it for maximum saturation.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">FIRST</span> <span class="o">=</span> <span class="mi">1850</span>
</span></span><span class="line"><span class="cl"><span class="n">LAST</span> <span class="o">=</span> <span class="mi">2018</span>  <span class="c1"># inclusive</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Reference period for the center of the color scale</span>
</span></span><span class="line"><span class="cl"><span class="n">FIRST_REFERENCE</span> <span class="o">=</span> <span class="mi">1971</span>
</span></span><span class="line"><span class="cl"><span class="n">LAST_REFERENCE</span> <span class="o">=</span> <span class="mi">2000</span>
</span></span><span class="line"><span class="cl"><span class="n">LIM</span> <span class="o">=</span> <span class="mf">0.7</span>  <span class="c1"># degrees</span></span></span></code></pre>
</div>
<p>Here we use pandas to read the fixed width text file, only the
first two columns, which are the year and the deviation from the
mean from 1961 to 1990.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># data from</span>
</span></span><span class="line"><span class="cl"><span class="c1"># https://www.metoffice.gov.uk/hadobs/hadcrut4/data/current/time_series/HadCRUT.4.6.0.0.annual_ns_avg.txt</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">read_fwf</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;HadCRUT.4.6.0.0.annual_ns_avg.txt&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">index_col</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">usecols</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="n">names</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;year&#34;</span><span class="p">,</span> <span class="s2">&#34;anomaly&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">    <span class="n">header</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">anomaly</span> <span class="o">=</span> <span class="n">df</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">FIRST</span><span class="p">:</span><span class="n">LAST</span><span class="p">,</span> <span class="s2">&#34;anomaly&#34;</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">reference</span> <span class="o">=</span> <span class="n">anomaly</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">FIRST_REFERENCE</span><span class="p">:</span><span class="n">LAST_REFERENCE</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">()</span></span></span></code></pre>
</div>
<p>This is our custom colormap, we could also use one of
the <a href="https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html">colormaps</a> that come with <code>matplotlib</code>, e.g. <code>coolwarm</code> or <code>RdBu</code>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># the colors in this colormap come from http://colorbrewer2.org</span>
</span></span><span class="line"><span class="cl"><span class="c1"># the 8 more saturated colors from the 9 blues / 9 reds</span>
</span></span><span class="line"><span class="cl"><span class="n">cmap</span> <span class="o">=</span> <span class="n">ListedColormap</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#08306b&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#08519c&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#2171b5&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#4292c6&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#6baed6&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#9ecae1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#c6dbef&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#deebf7&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#fee0d2&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#fcbba1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#fc9272&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#fb6a4a&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#ef3b2c&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#cb181d&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#a50f15&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;#67000d&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span></span></span></code></pre>
</div>
<p>We create a figure with a single axes object that fills the full area
of the figure and does not have any axis ticks or labels.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="o">.</span><span class="n">add_axes</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_axis_off</span><span class="p">()</span></span></span></code></pre>
</div>
<p>Finally, we create bars for each year, assign the
data, colormap and color limits and add it to the axes.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># create a collection with a rectangle for each year</span>
</span></span><span class="line"><span class="cl"><span class="n">col</span> <span class="o">=</span> <span class="n">PatchCollection</span><span class="p">([</span><span class="n">Rectangle</span><span class="p">((</span><span class="n">y</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">FIRST</span><span class="p">,</span> <span class="n">LAST</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># set data, colormap and color limits</span>
</span></span><span class="line"><span class="cl"><span class="n">col</span><span class="o">.</span><span class="n">set_array</span><span class="p">(</span><span class="n">anomaly</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">col</span><span class="o">.</span><span class="n">set_cmap</span><span class="p">(</span><span class="n">cmap</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">col</span><span class="o">.</span><span class="n">set_clim</span><span class="p">(</span><span class="n">reference</span> <span class="o">-</span> <span class="n">LIM</span><span class="p">,</span> <span class="n">reference</span> <span class="o">+</span> <span class="n">LIM</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">add_collection</span><span class="p">(</span><span class="n">col</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Make sure the axes limits are correct and save the figure.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_ylim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="n">FIRST</span><span class="p">,</span> <span class="n">LAST</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">savefig</span><span class="p">(</span><span class="s2">&#34;warming-stripes.png&#34;</span><span class="p">)</span></span></span></code></pre>
</div>
<p><img src="/matplotlib/warming-stripes/warming-stripes.png" alt="Warming Stripes"></p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="tutorials" label="tutorials" />
                             
                                <category scheme="taxonomy:Tags" term="academia" label="academia" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[Using Matplotlib to Advocate for Postdocs]]></title>
            <link href="https://blog.scientific-python.org/matplotlib/using-matplotlib-to-advocate-for-postdocs/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
            
                <id>https://blog.scientific-python.org/matplotlib/using-matplotlib-to-advocate-for-postdocs/</id>
            
            
            <published>2019-10-23T12:43:23-04:00</published>
            <updated>2019-10-23T12:43:23-04:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Advocating is all about communicating facts clearly. I used Matplotlib to show the financial struggles of postdocs in the Boston area.</blockquote><p>Postdocs are the <a href="https://en.wikipedia.org/wiki/Postdoctoral_researcher">workers of academia</a>.
They are the main players beyond the majority of scientific papers published in
journals and conferences. Yet, their effort is often not recognized in terms of
salary and benefits.</p>
<p>A few years ago, the NIH has established stipend levels for undergraduate,
predoctoral and postdoctoral trainees and fellows, the so-called NIH guidelines.
Many universities and research institutes currently adopt these guidelines for
deciding how much to pay postdocs.</p>
<p>One of the key problem of the NIH guidelines is that they are established at a
national level. This means that a postdoc in Buffalo is paid the same than a postdoc in Boston,
despite <a href="https://www.mentalfloss.com/article/85668/11-most-affordable-cities-us">Buffalo is one of the most affordable city to live in the USA</a>,
while <a href="https://www.investopedia.com/articles/personal-finance/080916/top-10-most-expensive-cities-us.asp">Boston is one of the most expensive</a>.
Every year, the NIH releases new guidelines, where the stipends are slightly
increased. <strong>Do these adjustments help a postdoc in the Boston area
take home a bit more money?</strong></p>
<p>I have used <a href="https://matplotlib.org">Matplotlib</a> to plot the NIH stipend levels
(y axis) for each year of postdoctoral experience (x axis) for the past 4 years
of NIH guidelines (color). I have also looked at the inflation of years 2017&ndash;2019
and increased the salaries of the previous year by that percentage (dashed lines).
<img src="/matplotlib/using-matplotlib-to-advocate-for-postdocs/gross_salary.png" alt="Plot of the NIH stipend level for postdoc versus the number of years of postdoc experience for every year from 2016 to 2019 inclusive. The x-axis ranges from 0 to 7 years of experience. The y-axis ranges from $45,000 USD to $60,000 USD. The plot also shows how these salaries would increase according to the rate of inflation during the same years. The overall message is that postdoc salaries are adjusted for inflation nationally."></p>
<p>The data revealed that the salaries of 2017 were just increased by the
inflation rate for the most senior postdocs, while junior postdocs (up to 1 year
of experience) received an increase more than 2.5 times of the inflation. In
2018, all salaries were just adjusted to the inflation. In 2019, the increase was
slightly higher than the inflation level. So, overall, every year the NIH makes
sure that the postdoc salaries are, at least, adjusted to the inflation. Great!</p>
<p>As mentioned earlier, there are cities in the US that are more expensive than
others, for example Boston. To partially account for such differences when
looking at the postdoc salaries, I subtracted from each salary the average rent
for a one-bedroom apartment in Boston.
Of course, it also increases every year, but, unfortunately for postdocs, <strong>rent
increases way more than the inflation</strong>. The results are below.
<img src="/matplotlib/using-matplotlib-to-advocate-for-postdocs/gross_salary_minus_rent.png" alt="This plot is similar to the previous plot, but has adjusted the y-axis by subtracting the cost of rent in Boston. Plot of the NIH stipend level for postdocs minus the average rent in Boston versus the number of years of postdoc experience for every year from 2016 to 2019 inclusive. The x-axis ranges from 0 to 7 years of experience. The y-axis ranges from $8,000 USD to $22,000 USD. The overall message is that increases in rent in Boston have outpaced increases in NIH stipends."></p>
<p>It turns out that the best year for postdocs with at least one year of experience
was actually 2016. In the subsequent years, the real estate has eaten larger and
larger portions of the postdoc salary, resulting in 2019-paid postdocs taking home
<strong>20% less money</strong> than 2016-paid postdocs with the same experience.</p>
<p>In the end, life is financially harder and harder for postdocs in the Boston area.
These data should be taken into account by research institutes and universities,
which have the freedom of topping up postdocs&rsquo; salaries to reflect the real cost
of living of different cities.</p>
<p>You can download the Jupyter notebook [here](Postdoc salary Analysis.ipynb).</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="academia" label="academia" />
                             
                                <category scheme="taxonomy:Tags" term="matplotlib" label="matplotlib" />
                            
                        
                    
                
            
        </entry>
    
</feed>
