<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://atchen.me/feed.xml" rel="self" type="application/atom+xml" /><link href="http://atchen.me/" rel="alternate" type="text/html" /><updated>2026-07-20T22:06:35+00:00</updated><id>http://atchen.me/feed.xml</id><title type="html">Albert Tian Chen</title><subtitle>Comp Bio, Data Viz, Mass-Spec</subtitle><entry><title type="html">Matplotlib Radarplots / Spiderplots</title><link href="http://atchen.me/data-viz/code/2022/01/08/matplotlib-radarplots-spiderplots.html" rel="alternate" type="text/html" title="Matplotlib Radarplots / Spiderplots" /><published>2022-01-08T00:00:00+00:00</published><updated>2022-01-08T00:00:00+00:00</updated><id>http://atchen.me/data-viz/code/2022/01/08/matplotlib-radarplots-spiderplots</id><content type="html" xml:base="http://atchen.me/data-viz/code/2022/01/08/matplotlib-radarplots-spiderplots.html"><![CDATA[<h2 id="radarplots">Radarplots</h2>

<p>AKA spiderplots AKA Dance Dance Revolution difficulty selector</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">radarplot</span><span class="p">(</span><span class="n">categories</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">colors</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s">''</span><span class="p">,</span> <span class="n">fill</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">facealpha</span><span class="o">=</span><span class="mf">0.1</span><span class="p">):</span>
    <span class="s">"""Radarplot

    Parameters
    ----------
    categories: list of str
    data: dict
        key: str (name)
        value: np.array 
            - data points for each category
            - Can be 1D or 2D
            - rows = observations, columns=categories
    colors: list of matplotlib color
        - same length as data keys
    title: str
    fill: bool
    facealpha: float
    """</span>
    
    <span class="n">theta_inc</span> <span class="o">=</span> <span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">pi</span><span class="o">*</span><span class="mi">2</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">categories</span><span class="p">)</span> <span class="c1"># Angle between assays
</span>    <span class="c1"># theta = np.arange(0, np.pi*2, theta_inc)
</span>    
    <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="p">.</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">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="n">subplot_kw</span><span class="o">=</span><span class="p">{</span><span class="s">'projection'</span><span class="p">:</span> <span class="s">'polar'</span><span class="p">},</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
    <span class="c1"># POLAR COORDINATES
</span>    <span class="c1"># X = theta
</span>    <span class="c1"># Y = r (radius)
</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">colors</span><span class="p">:</span>
        <span class="n">colors</span> <span class="o">=</span> <span class="p">{</span><span class="n">sample</span><span class="p">:</span> <span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">tab10</span><span class="p">.</span><span class="n">colors</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">sample</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">keys</span><span class="p">())}</span>
    <span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">colors</span><span class="p">)</span> <span class="o">==</span> <span class="nb">list</span><span class="p">:</span>
        <span class="n">colors</span> <span class="o">=</span> <span class="p">{</span><span class="n">sample</span><span class="p">:</span> <span class="n">color</span> <span class="k">for</span> <span class="n">sample</span><span class="p">,</span> <span class="n">color</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">keys</span><span class="p">(),</span> <span class="n">colors</span><span class="p">)}</span>
    
    <span class="k">for</span> <span class="n">sample</span><span class="p">,</span> <span class="n">values</span> <span class="ow">in</span> <span class="n">data</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
        <span class="n">r</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">theta</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="c1"># Cast to numpy array
</span>        <span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">==</span> <span class="nb">list</span><span class="p">:</span>
            <span class="n">values</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>

        <span class="c1"># Cast to 2D array if 1D
</span>        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">.</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="n">values</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([</span><span class="n">values</span><span class="p">])</span>

        <span class="c1"># For each set of observations
</span>        <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">values</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
            <span class="c1"># For each category
</span>            <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">values</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="n">r</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">values</span><span class="p">[</span><span class="n">m</span><span class="p">,</span> <span class="n">k</span><span class="p">])</span>
                <span class="n">theta</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">k</span> <span class="o">*</span> <span class="n">theta_inc</span><span class="p">)</span>

        <span class="n">c</span> <span class="o">=</span> <span class="p">(</span><span class="n">colors</span><span class="p">[</span><span class="n">sample</span><span class="p">])</span>
        <span class="c1"># Reduce alpha of facecolor
</span>        <span class="n">fc</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">([</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">c</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="n">facealpha</span><span class="p">])</span>
        <span class="n">ec</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">([</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">c</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="mf">1.0</span><span class="p">])</span>
            
        <span class="k">if</span> <span class="ow">not</span> <span class="n">fill</span><span class="p">:</span>
            <span class="n">fc</span> <span class="o">=</span> <span class="s">'none'</span>
            
        <span class="n">ax</span><span class="p">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">mpl</span><span class="p">.</span><span class="n">patches</span><span class="p">.</span><span class="n">Polygon</span><span class="p">(</span>
            <span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">([</span><span class="n">theta</span><span class="p">,</span> <span class="n">r</span><span class="p">]).</span><span class="n">T</span><span class="p">,</span>
            <span class="n">facecolor</span><span class="o">=</span><span class="n">fc</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="n">ec</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 class="n">ax</span><span class="p">.</span><span class="n">scatter</span><span class="p">(</span>
            <span class="n">theta</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> 
            <span class="n">facecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="n">ec</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="mi">20</span><span class="p">,</span> 
            <span class="n">zorder</span><span class="o">=</span><span class="mi">1000</span> <span class="c1"># Plot over polygon patches
</span>        <span class="p">)</span>
        
    <span class="n">ax</span><span class="p">.</span><span class="n">set_xticks</span><span class="p">(</span><span class="n">theta</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">set_xticklabels</span><span class="p">(</span><span class="n">categories</span><span class="p">)</span>
    <span class="c1"># Place labels on the outside of the plot
</span>    <span class="c1"># Check for left/right side of the circle
</span>    <span class="k">for</span> <span class="n">tick</span> <span class="ow">in</span> <span class="n">ax</span><span class="p">.</span><span class="n">get_xticklabels</span><span class="p">():</span>
        <span class="k">if</span> <span class="n">tick</span><span class="p">.</span><span class="n">_x</span> <span class="o">&gt;</span> <span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">pi</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="ow">and</span> <span class="n">tick</span><span class="p">.</span><span class="n">_x</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">3</span> <span class="o">*</span> <span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">pi</span><span class="o">/</span><span class="mi">2</span><span class="p">)):</span>
            <span class="n">tick</span><span class="p">.</span><span class="n">set_ha</span><span class="p">(</span><span class="s">'right'</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">tick</span><span class="p">.</span><span class="n">set_ha</span><span class="p">(</span><span class="s">'left'</span><span class="p">)</span>
    
    <span class="c1"># CUSTOM TICKS
</span>    <span class="c1">#rticks = np.arange(0, 1.1, 0.2)
</span>    <span class="c1">#ax.set_rlim([0, 1])
</span>    <span class="c1">#ax.set_rticks(rticks)
</span>    <span class="c1"># rgridlines, rgridlabels = ax.set_rgrids(rticks)
</span>    <span class="c1"># for line in rgridlines:
</span>    <span class="c1">#     line.set_linewidth(0.5)
</span>    
    <span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="n">title</span><span class="p">)</span>
    
    <span class="n">legend_patches</span> <span class="o">=</span> <span class="p">[</span>
        <span class="n">mpl</span><span class="p">.</span><span class="n">lines</span><span class="p">.</span><span class="n">Line2D</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="n">color</span><span class="o">=</span><span class="n">colors</span><span class="p">[</span><span class="n">sample</span><span class="p">],</span> <span class="n">marker</span><span class="o">=</span><span class="s">'o'</span><span class="p">,</span> <span class="n">markerfacecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mf">1.</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">sample</span> <span class="ow">in</span> <span class="n">data</span><span class="p">.</span><span class="n">keys</span><span class="p">()</span>
    <span class="p">]</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">legend</span><span class="p">(</span><span class="n">legend_patches</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="n">keys</span><span class="p">()),</span> 
              <span class="n">bbox_to_anchor</span><span class="o">=</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">loc</span><span class="o">=</span><span class="s">'upper left'</span><span class="p">,</span>
              <span class="n">frameon</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">facecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
    <span class="c1"># plt.show()
</span>    
    <span class="k">return</span> <span class="n">fig</span><span class="p">,</span> <span class="n">ax</span>
    
    
<span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">radarplot</span><span class="p">(</span>
    <span class="p">[</span><span class="s">'A'</span><span class="p">,</span> <span class="s">'B'</span><span class="p">,</span> <span class="s">'C'</span><span class="p">,</span> <span class="s">'D'</span><span class="p">,</span> <span class="s">'E'</span><span class="p">],</span> 
    <span class="p">{</span>
        <span class="s">'Control'</span><span class="p">:</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">),</span>
        <span class="s">'Treatment'</span><span class="p">:</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-08-matplotlib-radarplots-spiderplots_files/2022-01-08-matplotlib-radarplots-spiderplots_1_0.png" /></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">radarplot</span><span class="p">(</span>
    <span class="p">[</span><span class="s">'A'</span><span class="p">,</span> <span class="s">'B'</span><span class="p">,</span> <span class="s">'C'</span><span class="p">,</span> <span class="s">'D'</span><span class="p">,</span> <span class="s">'E'</span><span class="p">],</span> 
    <span class="p">{</span>
        <span class="s">'Control'</span><span class="p">:</span> <span class="n">np</span><span class="p">.</span><span class="n">reshape</span><span class="p">(</span><span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">5</span><span class="o">*</span><span class="mi">5</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">),</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="s">'Treatment'</span><span class="p">:</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
    <span class="p">},</span>
    
<span class="p">)</span>

<span class="n">rlabel_pos</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> <span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="n">pi</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">4</span><span class="p">)</span>
<span class="n">rlabel</span><span class="o">=</span><span class="s">'Fold Change'</span>

<span class="c1"># Radius Axis Label
</span><span class="k">if</span> <span class="n">rlabel</span><span class="p">:</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">set_rlabel_position</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">rad2deg</span><span class="p">(</span><span class="n">rlabel_pos</span><span class="p">))</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="n">rlabel_pos</span> <span class="o">+</span> <span class="mf">0.1</span><span class="p">,</span> <span class="mf">2.</span><span class="p">,</span> <span class="n">rlabel</span><span class="p">,</span> 
            <span class="n">ha</span><span class="o">=</span><span class="s">'left'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'top'</span><span class="p">,</span> <span class="n">rotation</span><span class="o">=</span><span class="n">np</span><span class="p">.</span><span class="n">rad2deg</span><span class="p">(</span><span class="n">rlabel_pos</span><span class="p">))</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-08-matplotlib-radarplots-spiderplots_files/2022-01-08-matplotlib-radarplots-spiderplots_2_0.png" /></p>]]></content><author><name></name></author><category term="data-viz" /><category term="code" /><category term="python" /><category term="matplotlib" /><category term="jupyter" /><category term="data viz" /><summary type="html"><![CDATA[Radarplots]]></summary></entry><entry><title type="html">Ridgeplots in Matplotlib</title><link href="http://atchen.me/data-viz/code/2022/01/08/matplotlib-ridgeplots.html" rel="alternate" type="text/html" title="Ridgeplots in Matplotlib" /><published>2022-01-08T00:00:00+00:00</published><updated>2022-01-08T00:00:00+00:00</updated><id>http://atchen.me/data-viz/code/2022/01/08/matplotlib-ridgeplots</id><content type="html" xml:base="http://atchen.me/data-viz/code/2022/01/08/matplotlib-ridgeplots.html"><![CDATA[<p>A sort-of implementation of ggridges (<a href="https://cran.r-project.org/web/packages/ggridges/vignettes/introduction.html">https://cran.r-project.org/web/packages/ggridges/vignettes/introduction.html</a>) from R, except that I don’t think there’s any reason to use kernel density estimates for these plots unless you have to.</p>

<p>Basic premise is that we plot multiple histograms in their own subplot axes, and then use <code class="language-plaintext highlighter-rouge">hspace</code> to overlap the plotting axes vertically</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">matplotlib</span> <span class="k">as</span> <span class="n">mpl</span>
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="kn">import</span> <span class="nn">seaborn</span> <span class="k">as</span> <span class="n">sns</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">norm</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_new_black</span> <span class="o">=</span> <span class="s">'#373737'</span>
<span class="n">sns</span><span class="p">.</span><span class="n">set_theme</span><span class="p">(</span><span class="n">style</span><span class="o">=</span><span class="s">'ticks'</span><span class="p">,</span> <span class="n">font_scale</span><span class="o">=</span><span class="mf">0.75</span><span class="p">,</span> <span class="n">rc</span><span class="o">=</span><span class="p">{</span>
    <span class="s">'font.family'</span><span class="p">:</span> <span class="s">'sans-serif'</span><span class="p">,</span>
    <span class="s">'font.sans-serif'</span><span class="p">:</span> <span class="p">[</span><span class="s">'Arial'</span><span class="p">,</span> <span class="s">'DejaVu Sans'</span><span class="p">],</span>
    <span class="s">'svg.fonttype'</span><span class="p">:</span> <span class="s">'none'</span><span class="p">,</span>
    <span class="s">'text.usetex'</span><span class="p">:</span> <span class="bp">False</span><span class="p">,</span>
    <span class="s">'pdf.fonttype'</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span>
    <span class="s">'ps.fonttype'</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span>
    <span class="s">'font.size'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'axes.labelsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'axes.titlesize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'axes.labelpad'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'axes.linewidth'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'axes.titlepad'</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
    <span class="s">'lines.linewidth'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'legend.fontsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'legend.title_fontsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'xtick.labelsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'ytick.labelsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'xtick.major.size'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'xtick.major.pad'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'xtick.major.width'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'ytick.major.size'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'ytick.major.pad'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'ytick.major.width'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'xtick.minor.size'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'xtick.minor.pad'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'xtick.minor.width'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'ytick.minor.size'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'ytick.minor.pad'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'ytick.minor.width'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>

    <span class="c1"># Avoid black unless necessary
</span>    <span class="s">'text.color'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'patch.edgecolor'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'patch.force_edgecolor'</span><span class="p">:</span> <span class="bp">False</span><span class="p">,</span> <span class="c1"># Seaborn turns on edgecolors for histograms by default and I don't like it
</span>    <span class="s">'hatch.color'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'axes.edgecolor'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="c1"># 'axes.titlecolor': _new_black # should fallback to text.color
</span>    <span class="s">'axes.labelcolor'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'xtick.color'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'ytick.color'</span><span class="p">:</span> <span class="n">_new_black</span>

    <span class="c1"># Default colormap - personal preference
</span>    <span class="c1"># 'image.cmap': 'inferno'
</span><span class="p">})</span>
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># Different vector sizes are OK - we're normalizing histograms by density
</span><span class="n">x1</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">1000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">x2</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">1500</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">x3</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">2000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>

<span class="c1"># Same bins across all distributions for valid comparisons
</span><span class="n">bins</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linspace</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>

<span class="n">x</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'X1'</span><span class="p">:</span> <span class="n">x1</span><span class="p">,</span>
    <span class="s">'X2'</span><span class="p">:</span> <span class="n">x2</span><span class="p">,</span>
    <span class="s">'X3'</span><span class="p">:</span> <span class="n">x3</span>
<span class="p">}</span>

<span class="n">colors</span> <span class="o">=</span> <span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">tab10</span><span class="p">.</span><span class="n">colors</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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="n">hspace</span><span class="o">=-</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">left</span><span class="o">=</span><span class="mf">0.2</span><span class="p">)</span>

<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="n">label</span><span class="p">,</span> <span class="n">vals</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>

    <span class="n">ax</span><span class="p">.</span><span class="n">hist</span><span class="p">(</span><span class="n">vals</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="n">bins</span><span class="p">,</span> <span class="n">density</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
        <span class="n">color</span><span class="o">=</span><span class="n">colors</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.7</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">set_ylim</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="c1"># Fixed ylimit for density comparisons
</span>
    <span class="c1"># Transparent background
</span>    <span class="n">ax</span><span class="p">.</span><span class="n">patch</span><span class="p">.</span><span class="n">set_alpha</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

    <span class="c1"># Turn off all spines except the bottom one
</span>    <span class="k">for</span> <span class="n">spine</span> <span class="ow">in</span> <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">.</span><span class="n">keys</span><span class="p">():</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="n">spine</span><span class="p">].</span><span class="n">set_visible</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
        
    <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="s">'bottom'</span><span class="p">].</span><span class="n">set_visible</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="s">'bottom'</span><span class="p">].</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="s">'bottom'</span><span class="p">].</span><span class="n">set_color</span><span class="p">(</span><span class="s">'#AAA'</span><span class="p">)</span>

    <span class="c1"># Only show x ticks and label for bottom plot
</span>    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="s">'bottom'</span><span class="p">].</span><span class="n">set_color</span><span class="p">(</span><span class="s">'#444'</span><span class="p">)</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'Score'</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">set_xticks</span><span class="p">([])</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">set_xticklabels</span><span class="p">([])</span>
    
    <span class="n">ax</span><span class="p">.</span><span class="n">set_yticks</span><span class="p">([])</span>

    <span class="c1"># Label
</span>    <span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="o">-</span><span class="mf">0.01</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="n">colors</span><span class="p">[</span><span class="n">i</span><span class="p">],</span>
        <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'bottom'</span><span class="p">)</span>
    
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-11-matplotlib-ridgeplots_files/2022-01-11-matplotlib-ridgeplots_3_0.png" /></p>

<p>Here’s a similar version, but with additional graphics to display missing data (NaNs) while still appropriately scaling the histograms</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># Different vector sizes are OK - we're normalizing histograms by density
</span><span class="n">x1</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">1000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">x2</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">1500</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">x3</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">2000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>

<span class="c1"># Knockout half of the points
</span><span class="n">x1</span><span class="p">[:</span><span class="mi">700</span><span class="p">]</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">nan</span>

<span class="c1"># Same bins across all distributions for valid comparisons
</span><span class="n">bins</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linspace</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>

<span class="n">x</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'X1'</span><span class="p">:</span> <span class="n">x1</span><span class="p">,</span>
    <span class="s">'X2'</span><span class="p">:</span> <span class="n">x2</span><span class="p">,</span>
    <span class="s">'X3'</span><span class="p">:</span> <span class="n">x3</span>
<span class="p">}</span>

<span class="n">colors</span> <span class="o">=</span> <span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">tab10</span><span class="p">.</span><span class="n">colors</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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="n">hspace</span><span class="o">=-</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">left</span><span class="o">=</span><span class="mf">0.2</span><span class="p">)</span>

<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="n">label</span><span class="p">,</span> <span class="n">vals</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>

    <span class="c1"># Set NaNs to some really low value and extend the bin range to count it,
</span>    <span class="c1"># but use xlim to only keep our plot within the original bin range
</span>    <span class="n">nan_placeholder_val</span> <span class="o">=</span> <span class="o">-</span><span class="mi">10</span>
    <span class="n">n_missing</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nb">sum</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">isnan</span><span class="p">(</span><span class="n">vals</span><span class="p">))</span>
    <span class="n">vals</span><span class="p">[</span><span class="n">np</span><span class="p">.</span><span class="n">isnan</span><span class="p">(</span><span class="n">vals</span><span class="p">)]</span> <span class="o">=</span> <span class="n">nan_placeholder_val</span>
    <span class="n">xlim</span> <span class="o">=</span> <span class="p">[</span><span class="n">bins</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">bins</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span>
    <span class="n">new_bins</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">nan_placeholder_val</span><span class="p">,</span> <span class="n">bins</span><span class="p">)</span>

    <span class="n">ax</span><span class="p">.</span><span class="n">hist</span><span class="p">(</span><span class="n">vals</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="n">new_bins</span><span class="p">,</span> <span class="n">density</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
        <span class="n">color</span><span class="o">=</span><span class="n">colors</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.7</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">set_xlim</span><span class="p">(</span><span class="n">xlim</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">set_ylim</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="c1"># Transparent background
</span>    <span class="n">ax</span><span class="p">.</span><span class="n">patch</span><span class="p">.</span><span class="n">set_alpha</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

    <span class="c1"># Turn off all spines except the bottom one
</span>    <span class="k">for</span> <span class="n">spine</span> <span class="ow">in</span> <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">.</span><span class="n">keys</span><span class="p">():</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="n">spine</span><span class="p">].</span><span class="n">set_visible</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
        
    <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="s">'bottom'</span><span class="p">].</span><span class="n">set_visible</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="s">'bottom'</span><span class="p">].</span><span class="n">set_linewidth</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="s">'bottom'</span><span class="p">].</span><span class="n">set_color</span><span class="p">(</span><span class="s">'#AAA'</span><span class="p">)</span>

    <span class="c1"># Only show x ticks and label for bottom plot
</span>    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">spines</span><span class="p">[</span><span class="s">'bottom'</span><span class="p">].</span><span class="n">set_color</span><span class="p">(</span><span class="s">'#444'</span><span class="p">)</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'Score'</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">set_xticks</span><span class="p">([])</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">set_xticklabels</span><span class="p">([])</span>
    
    <span class="n">ax</span><span class="p">.</span><span class="n">set_yticks</span><span class="p">([])</span>
        
    <span class="c1"># % Not detected
</span>    <span class="n">rect_width</span> <span class="o">=</span> <span class="mf">0.07</span>
    <span class="n">rect_height</span> <span class="o">=</span> <span class="mf">0.5</span>
    <span class="n">rect_padding</span> <span class="o">=</span> <span class="mf">0.01</span> <span class="c1"># Padding from the axis
</span>    <span class="n">ax</span><span class="p">.</span><span class="n">add_patch</span><span class="p">(</span><span class="n">mpl</span><span class="p">.</span><span class="n">patches</span><span class="p">.</span><span class="n">Rectangle</span><span class="p">(</span>
        <span class="p">((</span><span class="o">-</span><span class="mi">1</span> <span class="o">*</span> <span class="n">rect_width</span><span class="p">)</span> <span class="o">-</span> <span class="n">rect_padding</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">rect_width</span><span class="p">,</span> <span class="n">rect_height</span><span class="p">,</span>
        <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">clip_on</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">facecolor</span><span class="o">=</span><span class="n">colors</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.5</span>
    <span class="p">))</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">text</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">rect_width</span> <span class="o">/</span> <span class="mi">2</span><span class="p">))</span><span class="o">-</span><span class="n">rect_padding</span><span class="p">,</span> <span class="mf">0.25</span><span class="p">,</span> 
        <span class="s">'{:.1f}'</span><span class="p">.</span><span class="nb">format</span><span class="p">((</span><span class="n">n_missing</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="n">vals</span><span class="p">))</span> <span class="o">*</span> <span class="mi">100</span><span class="p">),</span> 
        <span class="n">fontsize</span><span class="o">=</span><span class="mi">7</span><span class="p">,</span> <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">rotation</span><span class="o">=</span><span class="mi">90</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'center'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'center'</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">text</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">rect_width</span> <span class="o">/</span> <span class="mi">2</span><span class="p">))</span><span class="o">-</span><span class="n">rect_padding</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> 
        <span class="s">'%ND'</span><span class="p">,</span> <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'center'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'top'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">7</span><span class="p">)</span>

    <span class="c1"># Label
</span>    <span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">((</span><span class="o">-</span><span class="mi">1</span> <span class="o">*</span> <span class="n">rect_width</span><span class="p">)</span> <span class="o">-</span> <span class="n">rect_padding</span> <span class="o">-</span> <span class="mf">0.02</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">label</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="n">colors</span><span class="p">[</span><span class="n">i</span><span class="p">],</span>
        <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'bottom'</span><span class="p">)</span>
    
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-11-matplotlib-ridgeplots_files/2022-01-11-matplotlib-ridgeplots_5_0.png" /></p>]]></content><author><name></name></author><category term="data-viz" /><category term="code" /><category term="python" /><category term="matplotlib" /><category term="jupyter" /><category term="data viz" /><summary type="html"><![CDATA[A sort-of implementation of ggridges (https://cran.r-project.org/web/packages/ggridges/vignettes/introduction.html) from R, except that I don’t think there’s any reason to use kernel density estimates for these plots unless you have to.]]></summary></entry><entry><title type="html">Making publication-quality figures with Matplotlib</title><link href="http://atchen.me/research/code/data-viz/2022/01/04/plotting-matplotlib-reference.html" rel="alternate" type="text/html" title="Making publication-quality figures with Matplotlib" /><published>2022-01-04T00:00:00+00:00</published><updated>2022-01-04T00:00:00+00:00</updated><id>http://atchen.me/research/code/data-viz/2022/01/04/plotting-matplotlib-reference</id><content type="html" xml:base="http://atchen.me/research/code/data-viz/2022/01/04/plotting-matplotlib-reference.html"><![CDATA[<p>Making this reference mostly for myself - hope others find these tricks useful</p>

<h2 id="table-of-contents">Table of Contents</h2>

<ul>
  <li><a href="#imports">Imports</a></li>
  <li><a href="#theming">Theming</a>
    <ul>
      <li><a href="#colorblind-testing">Colorblind testing</a></li>
      <li><a href="#categorical-colors">Categorical Colors</a></li>
      <li><a href="#continuous-and-divergent-colormaps">Continuous and Divergent Colormaps</a></li>
    </ul>
  </li>
  <li><a href="#figure-sizing">Figure sizing</a>
    <ul>
      <li><a href="#figure-padding">Figure padding</a></li>
    </ul>
  </li>
  <li><a href="#gridspec">Gridspec</a>
    <ul>
      <li><a href="#nested-gridspecs">Nested gridspecs</a></li>
    </ul>
  </li>
  <li><a href="#scatterplots">Scatterplots</a>
    <ul>
      <li><a href="#density-scatterplots">Density scatterplots</a>
        <ul>
          <li><a href="#fast-subsampled-density-kernels">Fast subsampled density kernels</a></li>
          <li><a href="#stored-density-kernels">Stored density kernels</a></li>
        </ul>
      </li>
      <li><a href="#scatterplot-rasterization">Scatterplot rasterization</a></li>
    </ul>
  </li>
  <li><a href="#text-annotation">Text annotation</a>
    <ul>
      <li><a href="#blended-transforms">Blended transforms</a></li>
      <li><a href="#point-annotation">Point annotation</a></li>
    </ul>
  </li>
  <li><a href="#grids">Grids</a></li>
  <li><a href="#colorbars">Colorbars</a></li>
</ul>

<h3 id="imports">Imports</h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="n">pd</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="kn">import</span> <span class="nn">matplotlib</span> <span class="k">as</span> <span class="n">mpl</span>
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="kn">import</span> <span class="nn">seaborn</span> <span class="k">as</span> <span class="n">sns</span>
</code></pre></div></div>

<h2 id="theming">Theming</h2>

<p><a href="https://matplotlib.org/stable/tutorials/introductory/customizing.html">Matplotlib rcParams reference</a></p>

<p>Most of the seaborn defaults are sensible, so I just build around them with <code class="language-plaintext highlighter-rouge">sns.set</code></p>

<p>For figures, I go with a default font size of 9 pt and a line size of 0.5 pt. Smaller fonts and thinner lines will be harder to read on print, but for super compact figures I sometimes go down to 7 pt font.</p>

<p>For theme colors, I follow <em>Never Use Black</em>: <a href="https://ianstormtaylor.com/design-tip-never-use-black/">https://ianstormtaylor.com/design-tip-never-use-black/</a></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_new_black</span> <span class="o">=</span> <span class="s">'#373737'</span>
<span class="n">sns</span><span class="p">.</span><span class="n">set_theme</span><span class="p">(</span><span class="n">style</span><span class="o">=</span><span class="s">'ticks'</span><span class="p">,</span> <span class="n">font_scale</span><span class="o">=</span><span class="mf">0.75</span><span class="p">,</span> <span class="n">rc</span><span class="o">=</span><span class="p">{</span>
    <span class="s">'font.family'</span><span class="p">:</span> <span class="s">'sans-serif'</span><span class="p">,</span>
    <span class="s">'font.sans-serif'</span><span class="p">:</span> <span class="p">[</span><span class="s">'Arial'</span><span class="p">,</span> <span class="s">'DejaVu Sans'</span><span class="p">],</span>
    <span class="s">'svg.fonttype'</span><span class="p">:</span> <span class="s">'none'</span><span class="p">,</span>
    <span class="s">'text.usetex'</span><span class="p">:</span> <span class="bp">False</span><span class="p">,</span>
    <span class="s">'pdf.fonttype'</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span>
    <span class="s">'ps.fonttype'</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span>
    <span class="s">'font.size'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'axes.labelsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'axes.titlesize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'axes.labelpad'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'axes.linewidth'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'axes.titlepad'</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
    <span class="s">'lines.linewidth'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'legend.fontsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'legend.title_fontsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'xtick.labelsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'ytick.labelsize'</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
    <span class="s">'xtick.major.size'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'xtick.major.pad'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
    <span class="s">'xtick.major.width'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'ytick.major.size'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'ytick.major.pad'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
    <span class="s">'ytick.major.width'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'xtick.minor.size'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'xtick.minor.pad'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
    <span class="s">'xtick.minor.width'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>
    <span class="s">'ytick.minor.size'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
    <span class="s">'ytick.minor.pad'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
    <span class="s">'ytick.minor.width'</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span>

    <span class="c1"># Avoid black unless necessary
</span>    <span class="s">'text.color'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'patch.edgecolor'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'patch.force_edgecolor'</span><span class="p">:</span> <span class="bp">False</span><span class="p">,</span> <span class="c1"># Seaborn turns on edgecolors for histograms by default and I don't like it
</span>    <span class="s">'hatch.color'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'axes.edgecolor'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="c1"># 'axes.titlecolor': _new_black # should fallback to text.color
</span>    <span class="s">'axes.labelcolor'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'xtick.color'</span><span class="p">:</span> <span class="n">_new_black</span><span class="p">,</span>
    <span class="s">'ytick.color'</span><span class="p">:</span> <span class="n">_new_black</span>

    <span class="c1"># Default colormap - personal preference
</span>    <span class="c1"># 'image.cmap': 'inferno'
</span><span class="p">})</span>
</code></pre></div></div>

<h3 id="colorblind-testing">Colorblind testing</h3>

<p>For figure development, try Color Oracle <a href="https://colororacle.org/">https://colororacle.org/</a>, which simulates multiple different colorblindnesses and also grayscale. Ideally you should design your figure colors to also work in grayscale but in practice it’s quite difficult with more than 2 categories.</p>

<p>If you’re polishing figures in Illustrator, they also have colorblindness modes, in View -&gt; Proof Setup -&gt; Colorblindness</p>

<h3 id="categorical-colors">Categorical Colors</h3>

<p>I use <a href="http://web.archive.org/web/20211011090208/https://personal.sron.nl/~pault/">Paul Tol’s Colorblind-friendly colors</a> for all categorical mappings. Full python code is <a href="http://personal.sron.nl/~pault/data/tol_colors.py">here</a>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">tol_cset</span><span class="p">(</span><span class="n">colorset</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
    <span class="s">"""
    Discrete color sets for qualitative data.

    Define a namedtuple instance with the colors.
    Examples for: cset = tol_cset(&lt;scheme&gt;)
      - cset.red and cset[1] give the same color (in default 'bright' colorset)
      - cset._fields gives a tuple with all color names
      - list(cset) gives a list with all colors
    """</span>
    <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
    
    <span class="n">namelist</span> <span class="o">=</span> <span class="p">(</span><span class="s">'bright'</span><span class="p">,</span> <span class="s">'high-contrast'</span><span class="p">,</span> <span class="s">'vibrant'</span><span class="p">,</span> <span class="s">'muted'</span><span class="p">,</span> <span class="s">'medium-contrast'</span><span class="p">,</span> <span class="s">'light'</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">colorset</span> <span class="o">==</span> <span class="bp">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">namelist</span>
    <span class="k">if</span> <span class="n">colorset</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">namelist</span><span class="p">:</span>
        <span class="n">colorset</span> <span class="o">=</span> <span class="s">'bright'</span>
        <span class="k">print</span><span class="p">(</span><span class="s">'*** Warning: requested colorset not defined,'</span><span class="p">,</span>
              <span class="s">'known colorsets are {}.'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">namelist</span><span class="p">),</span>
              <span class="s">'Using {}.'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">colorset</span><span class="p">))</span> 

    <span class="k">if</span> <span class="n">colorset</span> <span class="o">==</span> <span class="s">'bright'</span><span class="p">:</span>
        <span class="n">cset</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Bcset'</span><span class="p">,</span>
                    <span class="s">'blue red green yellow cyan purple grey black'</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">cset</span><span class="p">(</span><span class="s">'#4477AA'</span><span class="p">,</span> <span class="s">'#EE6677'</span><span class="p">,</span> <span class="s">'#228833'</span><span class="p">,</span> <span class="s">'#CCBB44'</span><span class="p">,</span> <span class="s">'#66CCEE'</span><span class="p">,</span>
                    <span class="s">'#AA3377'</span><span class="p">,</span> <span class="s">'#BBBBBB'</span><span class="p">,</span> <span class="s">'#000000'</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">colorset</span> <span class="o">==</span> <span class="s">'high-contrast'</span><span class="p">:</span>
        <span class="n">cset</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Hcset'</span><span class="p">,</span>
                    <span class="s">'blue yellow red black'</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">cset</span><span class="p">(</span><span class="s">'#004488'</span><span class="p">,</span> <span class="s">'#DDAA33'</span><span class="p">,</span> <span class="s">'#BB5566'</span><span class="p">,</span> <span class="s">'#000000'</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">colorset</span> <span class="o">==</span> <span class="s">'vibrant'</span><span class="p">:</span>
        <span class="n">cset</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Vcset'</span><span class="p">,</span>
                    <span class="s">'orange blue cyan magenta red teal grey black'</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">cset</span><span class="p">(</span><span class="s">'#EE7733'</span><span class="p">,</span> <span class="s">'#0077BB'</span><span class="p">,</span> <span class="s">'#33BBEE'</span><span class="p">,</span> <span class="s">'#EE3377'</span><span class="p">,</span> <span class="s">'#CC3311'</span><span class="p">,</span>
                    <span class="s">'#009988'</span><span class="p">,</span> <span class="s">'#BBBBBB'</span><span class="p">,</span> <span class="s">'#000000'</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">colorset</span> <span class="o">==</span> <span class="s">'muted'</span><span class="p">:</span>
        <span class="n">cset</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Mcset'</span><span class="p">,</span>
                    <span class="s">'rose indigo sand green cyan wine teal olive purple pale_grey black'</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">cset</span><span class="p">(</span><span class="s">'#CC6677'</span><span class="p">,</span> <span class="s">'#332288'</span><span class="p">,</span> <span class="s">'#DDCC77'</span><span class="p">,</span> <span class="s">'#117733'</span><span class="p">,</span> <span class="s">'#88CCEE'</span><span class="p">,</span>
                    <span class="s">'#882255'</span><span class="p">,</span> <span class="s">'#44AA99'</span><span class="p">,</span> <span class="s">'#999933'</span><span class="p">,</span> <span class="s">'#AA4499'</span><span class="p">,</span> <span class="s">'#DDDDDD'</span><span class="p">,</span>
                    <span class="s">'#000000'</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">colorset</span> <span class="o">==</span> <span class="s">'medium-contrast'</span><span class="p">:</span>
        <span class="n">cset</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Mcset'</span><span class="p">,</span>
                    <span class="s">'light_blue dark_blue light_yellow dark_red dark_yellow light_red black'</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">cset</span><span class="p">(</span><span class="s">'#6699CC'</span><span class="p">,</span> <span class="s">'#004488'</span><span class="p">,</span> <span class="s">'#EECC66'</span><span class="p">,</span> <span class="s">'#994455'</span><span class="p">,</span> <span class="s">'#997700'</span><span class="p">,</span>
                    <span class="s">'#EE99AA'</span><span class="p">,</span> <span class="s">'#000000'</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">colorset</span> <span class="o">==</span> <span class="s">'light'</span><span class="p">:</span>
        <span class="n">cset</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Lcset'</span><span class="p">,</span>
                    <span class="s">'light_blue orange light_yellow pink light_cyan mint pear olive pale_grey black'</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">cset</span><span class="p">(</span><span class="s">'#77AADD'</span><span class="p">,</span> <span class="s">'#EE8866'</span><span class="p">,</span> <span class="s">'#EEDD88'</span><span class="p">,</span> <span class="s">'#FFAABB'</span><span class="p">,</span> <span class="s">'#99DDFF'</span><span class="p">,</span>
                    <span class="s">'#44BB99'</span><span class="p">,</span> <span class="s">'#BBCC33'</span><span class="p">,</span> <span class="s">'#AAAA00'</span><span class="p">,</span> <span class="s">'#DDDDDD'</span><span class="p">,</span> <span class="s">'#000000'</span><span class="p">)</span>
</code></pre></div></div>

<h3 id="continuous-and-divergent-colormaps">Continuous and Divergent Colormaps</h3>

<p>Matplotlib’s base guide on colormaps is quite good: <a href="https://matplotlib.org/stable/tutorials/colors/colormaps.html">https://matplotlib.org/stable/tutorials/colors/colormaps.html</a></p>

<p><strong>For continuous colormaps, always stick to “Perceptually Uniform Sequential Colormaps”</strong>, as these colormaps convert nicely to grayscale and therefore to colorblindness as well. For a visual demonstration, see: <a href="https://matplotlib.org/stable/tutorials/colors/colormaps.html#grayscale-conversion">https://matplotlib.org/stable/tutorials/colors/colormaps.html#grayscale-conversion</a>.</p>

<p>For divergent colormaps, since it’s impossible to differentiate high/low on grayscale, I usually use <code class="language-plaintext highlighter-rouge">coolwarm</code> over <code class="language-plaintext highlighter-rouge">bwr</code>, since the white tends to distract by blending into figure backgrounds (usually also white).</p>

<p>Just my opinion, but I would stay away from divergent colormaps with black as the middle color (you still might see this being used in some RNA-seq papers, with the green-black-pink] colormap). They strike me as super overwhelming and more difficult to interpret than the middle-white colormaps.</p>

<p>I use the <code class="language-plaintext highlighter-rouge">matplotlib.cm</code> module to reference named colormaps directly:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cmap</span> <span class="o">=</span> <span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">inferno</span>

<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="p">.</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">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
<span class="n">gradient</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</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">256</span><span class="p">)</span>
<span class="n">gradient</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">((</span><span class="n">gradient</span><span class="p">,</span> <span class="n">gradient</span><span class="p">))</span>
<span class="n">ax</span><span class="p">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">gradient</span><span class="p">,</span> <span class="n">aspect</span><span class="o">=</span><span class="s">'auto'</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">cmap</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_axis_off</span><span class="p">()</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_9_0.png" /></p>

<p>You can get the reversed version of any colormap in <code class="language-plaintext highlighter-rouge">matplotlib</code> by appending <code class="language-plaintext highlighter-rouge">_r</code> to the colormap name</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cmap</span> <span class="o">=</span> <span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">inferno_r</span> <span class="c1"># Added _r to reverse colormap
</span>
<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="p">.</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">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
<span class="n">gradient</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</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">256</span><span class="p">)</span>
<span class="n">gradient</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">((</span><span class="n">gradient</span><span class="p">,</span> <span class="n">gradient</span><span class="p">))</span>
<span class="n">ax</span><span class="p">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">gradient</span><span class="p">,</span> <span class="n">aspect</span><span class="o">=</span><span class="s">'auto'</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">cmap</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_axis_off</span><span class="p">()</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_11_0.png" /></p>

<h2 id="figure-sizing">Figure sizing</h2>

<p>I like to create my figures in the exact size that they will appear on paper/in print, so that I can get a good idea of what elements I can fit and how the font sizes/line sizes will look.</p>

<p>It’s always hard to know exactly what your panel sizes for each plot will be inside of a figure, so I like to, if possible, block the figure out in Illustrator and use the rulers to estimate how big each panel will be.</p>

<p>If I don’t know your panel sizes ahead of time, then I follow these general rules:</p>
<ul>
  <li>For standard letter size (8.5 in x 11 in), your figures/panels should not exceed 6 inches</li>
  <li>For standard letter size, your whole figure shouldn’t be taller than 8 inches. This leaves room for a figure caption on the same page (figure captions split across multiple pages are the worst).</li>
  <li>Size conservatively - more padding between panels is always better for readability</li>
</ul>

<p>Matplotlib defaults to figure sizes in inches, which is convenient for converting to Illustrator/print. Define this with <code class="language-plaintext highlighter-rouge">figsize</code></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>

<span class="c1"># Also works in subplots() command
</span><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="p">.</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">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>
<span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">norm</span>
<span class="n">ax</span><span class="p">.</span><span class="n">hist</span><span class="p">(</span><span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">100</span><span class="p">))</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;Figure size 216x144 with 0 Axes&gt;
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_13_1.png" /></p>

<p>For smaller panels (i.e., 2 x 1 inches), the output in Jupyter can be too small to view when developing the plot. You can use the <code class="language-plaintext highlighter-rouge">dpi</code> setting to increase the size of the image output in Jupyter</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">norm</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>

<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="p">.</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">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">75</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">hist</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>

<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="p">.</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">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">hist</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_15_0.png" /></p>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_15_1.png" /></p>

<h3 id="figure-padding">Figure padding</h3>

<p>I frequently add or remove padding around figures to account for removed axis labels, or maybe large axis labels that jut out a bit more.</p>

<p>You can adjust these via <code class="language-plaintext highlighter-rouge">fig.add_gridspec()</code> or <code class="language-plaintext highlighter-rouge">plt.subplots_adjust()</code> with the parameters <code class="language-plaintext highlighter-rouge">left</code>, <code class="language-plaintext highlighter-rouge">right</code>, <code class="language-plaintext highlighter-rouge">top</code>, and <code class="language-plaintext highlighter-rouge">bottom</code>. Units are in fractions of the figure [0, 1]</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><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="p">.</span><span class="n">subplots</span><span class="p">()</span>
<span class="n">plt</span><span class="p">.</span><span class="n">subplots_adjust</span><span class="p">(</span><span class="n">left</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">bottom</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">top</span><span class="o">=</span><span class="mf">0.9</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="s">'A really long y axis label'</span><span class="p">,</span> <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'center'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="n">figure</span><span class="p">()</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">left</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">bottom</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">top</span><span class="o">=</span><span class="mf">0.9</span><span class="p">)</span>
<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="s">'A really long y axis label'</span><span class="p">,</span> <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'center'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_17_0.png" /></p>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_17_1.png" /></p>

<p>By default jupyter cuts off whitespace around the plot and extends the plot to cover all grapical elements - so you won’t be able to visualize your padding results in the jupyter cell output.</p>

<p>You can solve this by first saving the plot to an image (in a file or in a buffer), and then displaying the raw image</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">io</span>
<span class="n">buf</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">BytesIO</span><span class="p">()</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="n">figure</span><span class="p">()</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">left</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">bottom</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">top</span><span class="o">=</span><span class="mf">0.9</span><span class="p">)</span>
<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="o">-</span><span class="mf">0.1</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="s">'A really long y axis label'</span><span class="p">,</span> <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'center'</span><span class="p">)</span>
<span class="c1"># Save to buffer
</span><span class="n">buf</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="n">BytesIO</span><span class="p">()</span>
<span class="n">fig</span><span class="p">.</span><span class="n">savefig</span><span class="p">(</span><span class="n">buf</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="s">'png'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">close</span><span class="p">()</span> <span class="c1"># Suppress output of raw figure object
</span>
<span class="c1"># Read image from buffer and display
</span><span class="kn">from</span> <span class="nn">IPython.display</span> <span class="kn">import</span> <span class="n">Image</span>
<span class="n">buf</span><span class="p">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">im</span> <span class="o">=</span> <span class="n">Image</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="n">buf</span><span class="p">.</span><span class="n">read</span><span class="p">())</span>
<span class="n">buf</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">im</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_19_0.png" /></p>

<h2 id="gridspec">Gridspec</h2>

<p>It’s a few more lines to lay out your plots with <code class="language-plaintext highlighter-rouge">gridspec</code> instead of <code class="language-plaintext highlighter-rouge">subplots</code> but it’s totally worth it for complex layouts. Plus it also saves you from a <code class="language-plaintext highlighter-rouge">subplots_adjust</code> call later on.</p>

<p>See: <a href="https://matplotlib.org/stable/gallery/subplots_axes_and_figures/gridspec_multicolumn.html">https://matplotlib.org/stable/gallery/subplots_axes_and_figures/gridspec_multicolumn.html</a></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</span><span class="p">(</span>
    <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="c1"># rows x cols
</span>    <span class="c1"># Cell relative width/heights
</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="mf">1.5</span><span class="p">,</span> <span class="mi">1</span><span class="p">],</span> <span class="c1"># Units are relative to each other
</span>    <span class="n">height_ratios</span><span class="o">=</span><span class="p">[</span><span class="mi">150</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="c1"># Padding between cells
</span>    <span class="n">wspace</span><span class="o">=</span><span class="mf">0.0</span><span class="p">,</span> <span class="c1"># Units are in fractions of the row above/column left? I think?
</span>    <span class="n">hspace</span><span class="o">=</span><span class="mf">0.7</span>
<span class="p">)</span>

<span class="n">ax1</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax2</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">:</span><span class="mi">3</span><span class="p">])</span>
<span class="n">ax3</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">3</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">ax4</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">2</span><span class="p">])</span>
<span class="n">ax5</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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">2</span><span class="p">])</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_21_0.png" /></p>

<p>For greating a grid of subplots, similar to <code class="language-plaintext highlighter-rouge">subplots()</code>:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>

<span class="n">nrow</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">ncol</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</span><span class="p">(</span><span class="n">nrow</span><span class="p">,</span> <span class="n">ncol</span><span class="p">)</span>

<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">nrow</span> <span class="o">*</span> <span class="n">ncol</span><span class="p">):</span>
    <span class="n">row</span> <span class="o">=</span> <span class="n">i</span> <span class="o">//</span> <span class="n">ncol</span>
    <span class="n">col</span> <span class="o">=</span> <span class="n">i</span> <span class="o">%</span> <span class="n">ncol</span>
    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="n">row</span><span class="p">,</span> <span class="n">col</span><span class="p">])</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_23_0.png" /></p>

<h3 id="nested-gridspecs">Nested Gridspecs</h3>

<p>See: <a href="https://matplotlib.org/stable/gallery/subplots_axes_and_figures/gridspec_nested.html">https://matplotlib.org/stable/gallery/subplots_axes_and_figures/gridspec_nested.html</a></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># From: https://matplotlib.org/stable/gallery/subplots_axes_and_figures/gridspec_nested.html
</span>
<span class="k">def</span> <span class="nf">format_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">):</span>
    <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="p">.</span><span class="n">axes</span><span class="p">):</span>
        <span class="n">ax</span><span class="p">.</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="s">"ax%d"</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="s">"center"</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">"center"</span><span class="p">)</span>
        <span class="n">ax</span><span class="p">.</span><span class="n">tick_params</span><span class="p">(</span><span class="n">labelbottom</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">labelleft</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>


<span class="c1"># gridspec inside gridspec
</span><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="n">figure</span><span class="p">()</span>
<span class="n">gs0</span> <span class="o">=</span> <span class="n">mpl</span><span class="p">.</span><span class="n">gridspec</span><span class="p">.</span><span class="n">GridSpec</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">figure</span><span class="o">=</span><span class="n">fig</span><span class="p">)</span>
<span class="n">gs00</span> <span class="o">=</span> <span class="n">mpl</span><span class="p">.</span><span class="n">gridspec</span><span class="p">.</span><span class="n">GridSpecFromSubplotSpec</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="n">subplot_spec</span><span class="o">=</span><span class="n">gs0</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>

<span class="n">ax1</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs00</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="p">:])</span>
<span class="n">ax2</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs00</span><span class="p">[</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 class="n">ax3</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs00</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="p">])</span>

<span class="c1"># the following syntax does the same as the GridSpecFromSubplotSpec call above:
</span><span class="n">gs01</span> <span class="o">=</span> <span class="n">gs0</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">subgridspec</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>

<span class="n">ax4</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs01</span><span class="p">[:,</span> <span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="n">ax5</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs01</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="p">])</span>
<span class="n">ax6</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs01</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="p">])</span>

<span class="n">plt</span><span class="p">.</span><span class="n">suptitle</span><span class="p">(</span><span class="s">"GridSpec Inside GridSpec"</span><span class="p">)</span>
<span class="n">format_axes</span><span class="p">(</span><span class="n">fig</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_25_0.png" /></p>

<h2 id="scatterplots">Scatterplots</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">norm</span>

<span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">0.3</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_27_0.png" /></p>

<p>By default, matplotlib/seaborn also plots an edge around each scatterplot marker that limits the minimum size of points. If you specify <code class="language-plaintext highlighter-rouge">edgecolor='none'</code>, then you can get correct point sizes</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Point size 1.0'</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mf">0.2</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Point size 0.2'</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">2</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Point size 0.2, no edge color'</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_29_0.png" /></p>

<h3 id="density-scatterplots">Density scatterplots</h3>

<p>For huge datasets of thousands of points, scatterplots will result in points plotting over each other and hiding the underlying distribution of data. For middling datasets you can get away with this by adjusting the alpha of each point, but then it might get difficult to see individual points. It’s better to apply a density kernel as a color on top of each point</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">norm</span>

<span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</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="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">8</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Base color'</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Smaller points'</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">2</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.2</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Smaller points + alpha'</span><span class="p">)</span>

<span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">gaussian_kde</span>
<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">3</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Density Kernel'</span><span class="p">)</span>

<span class="n">fig</span><span class="p">.</span><span class="n">suptitle</span><span class="p">(</span><span class="s">'N=10,000 points'</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mf">1.05</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_31_0.png" /></p>

<h4 id="fast-subsampled-density-kernels">Fast subsampled density kernels</h4>

<p>For huge datasets, the density kernel takes a really long time to calculate. When developing plots for these huge datasets, I subsample the kernel for faster run times. The result is usually indistinguishable (although for final publication I re-generate with the fully sampled density kernel)</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">norm</span>

<span class="n">x</span> <span class="o">=</span> <span class="n">pd</span><span class="p">.</span><span class="n">Series</span><span class="p">(</span><span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">))</span> <span class="c1"># Use pandas Series for the sample function
</span><span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</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="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">gaussian_kde</span>
<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Full Sample (n=10,000)'</span><span class="p">)</span>

<span class="c1"># Kernel subsampling
# Maintain random state between x and y, otherwise we'll pull different samples
# from each vector
</span><span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">([</span>
    <span class="n">x</span><span class="p">.</span><span class="n">sample</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="mi">1000</span><span class="p">,</span> <span class="n">random_state</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">sample</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="mi">1000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="p">]))</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Subsampled (n=1000)'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_33_0.png" /></p>

<h4 id="stored-density-kernels">Stored density kernels</h4>

<p>For full density kernels, you could also store the color vectors in a list/dictionary in a prior cell, so that you can iterate on your plot without regenerating the kernel and its estimates every run</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">n_datasets</span> <span class="o">=</span> <span class="mi">4</span>

<span class="n">xs</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">ys</span> <span class="o">=</span> <span class="p">[]</span>
<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_datasets</span><span class="p">):</span>
    <span class="n">xs</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">))</span> <span class="c1"># Use pandas Series for the sample function
</span>    <span class="n">ys</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">xs</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="mi">0</span><span class="p">,</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="o">/</span> <span class="mi">4</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">))</span>

<span class="n">colorvecs</span> <span class="o">=</span> <span class="p">[]</span>
<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_datasets</span><span class="p">):</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">xs</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">ys</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
    <span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">colorvecs</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">])))</span>

</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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="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_datasets</span><span class="p">):</span>
    <span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs</span><span class="p">[</span><span class="n">i</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="mi">2</span><span class="p">])</span>
    <span class="n">x</span> <span class="o">=</span> <span class="n">xs</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
    <span class="n">y</span> <span class="o">=</span> <span class="n">ys</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
    <span class="n">c</span> <span class="o">=</span> <span class="n">colorvecs</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
    <span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_36_0.png" /></p>

<h3 id="scatterplot-rasterization">Scatterplot rasterization</h3>

<p>If moving large scatterplot figures into another program (i.e., Illustrator), saving as vector graphics (SVG, PDF) will make every point an object and make the resulting file impossible to open/edit. Saving the entire plot as an image (JPEG/PNG) is also undesirable since we would want the line/text elements (axis labels, etc) to remain as vector graphics.</p>

<p>The solution is to pass <code class="language-plaintext highlighter-rouge">rasterized=True</code> into the <code class="language-plaintext highlighter-rouge">scatter()</code> call, so that <em>only the scatterplot points</em> are rasterized, while the rest of the plot stays vectorized.</p>

<p>At small figure sizes/low DPIs, the rasterization may be too apparent (too low resolution). You can solve this by bumping up the DPI of the figure</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</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="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Vector'</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">rasterized</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Rasterized'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_38_0.png" /></p>

<h2 id="text-annotation">Text annotation</h2>

<p>Placing text annotations on plots can be tricky if using the same coordinate system as the data - different scales will require a lot of custom code to tweak the exact location of each text label.</p>

<p>Instead, use <code class="language-plaintext highlighter-rouge">transform=ax.transAxes</code> to place text relative to the <em>axis box</em>, instead of in the data coordinate system</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">y1</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">y2</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">3</span><span class="p">))</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">wspace</span><span class="o">=</span><span class="mf">0.4</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y1</span><span class="p">]))</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y1</span><span class="p">]))</span>

<span class="n">ax</span><span class="p">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.05</span><span class="p">,</span> <span class="mf">0.95</span><span class="p">,</span> <span class="sa">r</span><span class="s">'$\rho$ = {:.2f}'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">corrcoef</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y1</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">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'left'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'top'</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">])</span>
<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y2</span><span class="p">]))</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</span><span class="p">([</span><span class="n">x</span><span class="p">,</span> <span class="n">y2</span><span class="p">]))</span>

<span class="n">ax</span><span class="p">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y2</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.05</span><span class="p">,</span> <span class="mf">0.95</span><span class="p">,</span> <span class="sa">r</span><span class="s">'$\rho$ = {:.2f}'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">corrcoef</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y2</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">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'left'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'top'</span><span class="p">)</span>


<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>

</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_40_0.png" /></p>

<h3 id="blended-transforms">Blended transforms</h3>

<p>Guide: <a href="https://matplotlib.org/stable/tutorials/advanced/transforms_tutorial.html#blended-transformations">https://matplotlib.org/stable/tutorials/advanced/transforms_tutorial.html#blended-transformations</a></p>

<p>Sometimes it’s useful to have one coordinate relative to the axis, and another relative to the data. For example, annotating a significance cutoff on a plot:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">expon</span>

<span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">random_state</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">np</span><span class="p">.</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="n">expon</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">scale</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>

<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">2</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">wspace</span><span class="o">=</span><span class="mf">0.4</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">axhline</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'r'</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 class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.03</span><span class="p">,</span> <span class="mf">2.2</span><span class="p">,</span> <span class="s">'FDR &lt; 1%'</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'red'</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">transform</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">transforms</span><span class="p">.</span><span class="n">blended_transform_factory</span><span class="p">(</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ax</span><span class="p">.</span><span class="n">transData</span><span class="p">),</span>
    <span class="n">rotation</span><span class="o">=</span><span class="mi">90</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'left'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'bottom'</span>
<span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">axvline</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'gray'</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 class="n">linestyle</span><span class="o">=</span><span class="s">'--'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">arange</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">ax</span><span class="p">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'Log FC'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s">'–Log10 FDR'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_42_0.png" /></p>

<h3 id="point-annotation">Point annotation</h3>

<p>adjustText is a great package (inspired from <code class="language-plaintext highlighter-rouge">ggrepel</code>) to annotate individual points: <a href="https://github.com/Phlya/adjustText">https://github.com/Phlya/adjustText</a></p>

<ul>
  <li>adjustText guide: <a href="https://github.com/Phlya/adjustText/wiki">https://github.com/Phlya/adjustText/wiki</a></li>
  <li>adjustText API: <a href="https://adjusttext.readthedocs.io/en/latest/">https://adjusttext.readthedocs.io/en/latest/</a></li>
  <li><code class="language-plaintext highlighter-rouge">annotate</code> API: <a href="https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.annotate.html">https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.annotate.html</a></li>
  <li>Arrow parameters: <a href="https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.FancyArrowPatch.html#matplotlib.patches.FancyArrowPatch">https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.FancyArrowPatch.html#matplotlib.patches.FancyArrowPatch</a></li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">expon</span>
<span class="kn">from</span> <span class="nn">adjustText</span> <span class="kn">import</span> <span class="n">adjust_text</span>

<span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">random_state</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">np</span><span class="p">.</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="n">expon</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">scale</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>

<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">2</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">wspace</span><span class="o">=</span><span class="mf">0.4</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">scatter</span> <span class="o">=</span> <span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">axhline</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'r'</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 class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.03</span><span class="p">,</span> <span class="mf">2.2</span><span class="p">,</span> <span class="s">'FDR &lt; 1%'</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'red'</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">transform</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">transforms</span><span class="p">.</span><span class="n">blended_transform_factory</span><span class="p">(</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ax</span><span class="p">.</span><span class="n">transData</span><span class="p">),</span>
    <span class="n">rotation</span><span class="o">=</span><span class="mi">90</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'left'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'bottom'</span>
<span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">axvline</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'gray'</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 class="n">linestyle</span><span class="o">=</span><span class="s">'--'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">arange</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">ax</span><span class="p">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'Log FC'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s">'–Log10 FDR'</span><span class="p">)</span>

<span class="n">sig</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="mf">1.8</span><span class="p">)</span> <span class="o">&amp;</span> <span class="p">(</span><span class="n">y</span> <span class="o">&gt;</span> <span class="mf">4.5</span><span class="p">)</span>
<span class="n">texts</span> <span class="o">=</span> <span class="p">[</span>
    <span class="n">plt</span><span class="p">.</span><span class="n">text</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="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="n">ha</span><span class="o">=</span><span class="s">'center'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'center'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">7</span><span class="p">)</span> 
    <span class="k">for</span> <span class="n">i</span><span class="p">,</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="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="n">sig</span><span class="p">],</span> <span class="n">y</span><span class="p">[</span><span class="n">sig</span><span class="p">]))</span>
<span class="p">]</span>
<span class="n">adjust_text</span><span class="p">(</span><span class="n">texts</span><span class="p">,</span> <span class="n">add_objects</span><span class="o">=</span><span class="p">[</span><span class="n">scatter</span><span class="p">],</span> <span class="n">expand_points</span><span class="o">=</span><span class="p">(</span><span class="mf">1.5</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">),</span>
<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="s">'-'</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'#AAA'</span><span class="p">,</span> <span class="n">mutation_scale</span><span class="o">=</span><span class="mi">3</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 class="c1"># Make significant points bigger
</span><span class="n">ax</span><span class="p">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="n">sig</span><span class="p">],</span> <span class="n">y</span><span class="p">[</span><span class="n">sig</span><span class="p">],</span> <span class="n">s</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'r'</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/Users/chena/miniconda3/lib/python3.7/site-packages/matplotlib/transforms.py:659: RuntimeWarning: invalid value encountered in double_scalars
  deltaw = (sw * width - width) / 2.0
/Users/chena/miniconda3/lib/python3.7/site-packages/matplotlib/transforms.py:660: RuntimeWarning: invalid value encountered in double_scalars
  deltah = (sh * height - height) / 2.0
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_44_1.png" /></p>

<h2 id="grids">Grids</h2>

<p>IMO grids are distracting and should only be used when comparing values is crucial to the message of the figure.</p>

<p>For example, grids in scatterplots are generally not useful. For plots like volcano plots where it’s necessary to visualize a significance cutoff (e.g., FDR &lt; 1%), it’s more efficient to draw just the cutoff and still forgo the grid.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</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="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">grid</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 class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Grid'</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">rasterized</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'No Grid'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_46_0.png" /></p>

<p>Of course the use of the grid is stylistic and also dependent on the message. Does it matter that the reader can use the grid to know that the top points are between 10e-6 and 10e-8? Or is it sufficient to just communicate that those points are <em>way</em> above the other hits and our significance cutoff?</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">expon</span>

<span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">random_state</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">np</span><span class="p">.</span><span class="nb">abs</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="n">expon</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">scale</span><span class="o">=</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>

<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">wspace</span><span class="o">=</span><span class="mf">0.4</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">arange</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">ax</span><span class="p">.</span><span class="n">grid</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 class="n">ax</span><span class="p">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'Log FC'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s">'–Log10 FDR'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Grid'</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">axhline</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'r'</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 class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="mf">0.03</span><span class="p">,</span> <span class="mf">2.2</span><span class="p">,</span> <span class="s">'FDR &lt; 1%'</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'red'</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">transform</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">transforms</span><span class="p">.</span><span class="n">blended_transform_factory</span><span class="p">(</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ax</span><span class="p">.</span><span class="n">transData</span><span class="p">),</span>
    <span class="n">rotation</span><span class="o">=</span><span class="mi">90</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'left'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'bottom'</span>
<span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">axvline</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s">'gray'</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 class="n">linestyle</span><span class="o">=</span><span class="s">'--'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">arange</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">ax</span><span class="p">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'Log FC'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s">'–Log10 FDR'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'No grid'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_48_0.png" /></p>

<p>For this example, it probably matters more where exactly each bar lies. We’re comparing a two values, and the scale is not as stretched out as the volcano plot so it matters more to know the exact location between our y-ticks. In this case the grid is helpful</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
<span class="n">y1</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">y2</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">scale</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">bar_width</span> <span class="o">=</span> <span class="mf">0.4</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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">4</span><span class="p">,</span> <span class="mf">1.5</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">wspace</span><span class="o">=</span><span class="mf">0.4</span><span class="p">)</span>

<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">bar</span><span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="p">(</span><span class="n">bar_width</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="p">,</span> <span class="n">y1</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="n">bar_width</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">'Control'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">bar</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="p">(</span><span class="n">bar_width</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="p">,</span> <span class="n">y2</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="n">bar_width</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">'Treatment'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_xticks</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'Conditions'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s">'Fold change'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'Grid'</span><span class="p">,</span> <span class="n">pad</span><span class="o">=</span><span class="mi">40</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">grid</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="s">'y'</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 class="n">ax</span><span class="p">.</span><span class="n">legend</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="s">'lower left'</span><span class="p">,</span> <span class="n">bbox_to_anchor</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="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">1</span><span class="p">])</span>
<span class="n">ax</span><span class="p">.</span><span class="n">bar</span><span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="p">(</span><span class="n">bar_width</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="p">,</span> <span class="n">y1</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="n">bar_width</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">'Control'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">bar</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="p">(</span><span class="n">bar_width</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="p">,</span> <span class="n">y2</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="n">bar_width</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s">'Treatment'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_xticks</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="s">'Conditions'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="s">'Log Fold Change'</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">set_title</span><span class="p">(</span><span class="s">'No grid'</span><span class="p">,</span> <span class="n">pad</span><span class="o">=</span><span class="mi">40</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">legend</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="s">'lower left'</span><span class="p">,</span> <span class="n">bbox_to_anchor</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="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_50_0.png" /></p>

<h2 id="colorbars">Colorbars</h2>

<p>I prefer to manually allocate space for colorbars instead of trusting matplotlib to create a sensible placement. This also gives you more direct control over the spacing and the axes (instead of having to rely on proxy functions on the created colorbar object).</p>

<p>Instead of tuning <code class="language-plaintext highlighter-rouge">width_ratio</code> on <code class="language-plaintext highlighter-rouge">subplot()</code> or <code class="language-plaintext highlighter-rouge">gridspec()</code>, I create separate gridspecs for the plot and the colorbar, which let’s me tune the spacing with the padding keyword arguments</p>

<p>I first test this out by creating empty axes to see where things will land:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</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="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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="mf">2.2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">right</span><span class="o">=</span><span class="mf">0.9</span><span class="p">)</span>

<span class="c1"># kernel = gaussian_kde(np.vstack([x, y]))
# c = kernel(np.vstack([x, y]))
</span>
<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="c1"># ax.scatter(x, y, s=1, c=c, cmap=mpl.cm.viridis, edgecolor='none')
</span>
<span class="c1"># Colorbar grid and axes
</span><span class="n">gs_cbar</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">left</span><span class="o">=</span><span class="mf">0.92</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="mf">0.95</span><span class="p">)</span>
<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs_cbar</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">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_52_0.png" /></p>

<p>Then I fill in, and pass the scatterplot object to the colorbar as a mappable.</p>

<p>I try to avoid sideways text wherever possible, and to instead place the colorbar label on top and offset of the colorbar for easier reading</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</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="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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="mf">2.2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">right</span><span class="o">=</span><span class="mf">0.9</span><span class="p">)</span>

<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">scatter</span> <span class="o">=</span> <span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>

<span class="c1"># Colorbar grid and axes
</span><span class="n">gs_cbar</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">left</span><span class="o">=</span><span class="mf">0.92</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="mf">0.95</span><span class="p">)</span>
<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs_cbar</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">fig</span><span class="p">.</span><span class="n">colorbar</span><span class="p">(</span><span class="n">scatter</span><span class="p">,</span> <span class="n">cax</span><span class="o">=</span><span class="n">ax</span><span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mf">1.01</span><span class="p">,</span> <span class="s">'Density'</span><span class="p">,</span> <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'bottom'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_54_0.png" /></p>

<p>If you have multiple panels, or multiple <code class="language-plaintext highlighter-rouge">mappables</code> to pass to colorbar, it’s simple to define the mapping yourself. Just remember that if you set <code class="language-plaintext highlighter-rouge">vmin</code> and <code class="language-plaintext highlighter-rouge">vmax</code> manually on the colorbar, to also enforce the same limits on your other plots as well.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">norm</span><span class="p">.</span><span class="n">rvs</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="n">size</span><span class="o">=</span><span class="mi">10_000</span><span class="p">)</span>

<span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</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="mf">2.2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">150</span><span class="p">)</span>
<span class="n">gs</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">right</span><span class="o">=</span><span class="mf">0.9</span><span class="p">)</span>

<span class="n">kernel</span> <span class="o">=</span> <span class="n">gaussian_kde</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">c</span> <span class="o">=</span> <span class="n">kernel</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">vstack</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">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</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 class="mi">0</span><span class="p">])</span>
<span class="n">scatter</span> <span class="o">=</span> <span class="n">ax</span><span class="p">.</span><span class="n">scatter</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">s</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="n">c</span><span class="p">,</span> <span class="n">vmin</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">vmax</span><span class="o">=</span><span class="mf">0.3</span><span class="p">,</span> <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="s">'none'</span><span class="p">)</span>

<span class="c1"># Colorbar grid and axes
</span><span class="n">gs_cbar</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_gridspec</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">left</span><span class="o">=</span><span class="mf">0.92</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="mf">0.95</span><span class="p">)</span>
<span class="n">ax</span> <span class="o">=</span> <span class="n">fig</span><span class="p">.</span><span class="n">add_subplot</span><span class="p">(</span><span class="n">gs_cbar</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">fig</span><span class="p">.</span><span class="n">colorbar</span><span class="p">(</span>
    <span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">ScalarMappable</span><span class="p">(</span>
        <span class="n">norm</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">colors</span><span class="p">.</span><span class="n">Normalize</span><span class="p">(</span><span class="n">vmin</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">vmax</span><span class="o">=</span><span class="mf">0.3</span><span class="p">),</span> 
        <span class="n">cmap</span><span class="o">=</span><span class="n">mpl</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">viridis</span>
    <span class="p">),</span> 
    <span class="n">cax</span><span class="o">=</span><span class="n">ax</span>
<span class="p">)</span>
<span class="n">ax</span><span class="p">.</span><span class="n">text</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mf">1.01</span><span class="p">,</span> <span class="s">'Density'</span><span class="p">,</span> <span class="n">transform</span><span class="o">=</span><span class="n">ax</span><span class="p">.</span><span class="n">transAxes</span><span class="p">,</span> <span class="n">ha</span><span class="o">=</span><span class="s">'right'</span><span class="p">,</span> <span class="n">va</span><span class="o">=</span><span class="s">'bottom'</span><span class="p">)</span>

<span class="n">plt</span><span class="p">.</span><span class="n">show</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="/images/2022-01-04-plotting-matplotlib-reference_files/2022-01-04-plotting-matplotlib-reference_56_0.png" /></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
</code></pre></div></div>]]></content><author><name></name></author><category term="research" /><category term="code" /><category term="data-viz" /><category term="guide" /><category term="python" /><category term="matplotlib" /><category term="jupyter" /><category term="data viz" /><summary type="html"><![CDATA[Making this reference mostly for myself - hope others find these tricks useful]]></summary></entry><entry><title type="html">Simple Zotero Cloud Storage Integration</title><link href="http://atchen.me/research/2019/12/01/simple-zotero-cloud-storage.html" rel="alternate" type="text/html" title="Simple Zotero Cloud Storage Integration" /><published>2019-12-01T00:00:00+00:00</published><updated>2019-12-01T00:00:00+00:00</updated><id>http://atchen.me/research/2019/12/01/simple-zotero-cloud-storage</id><content type="html" xml:base="http://atchen.me/research/2019/12/01/simple-zotero-cloud-storage.html"><![CDATA[<p><a class="logo-link" href="https://www.zotero.org/" style="display:flex;flex-direction:row;align-items:center;">
<img src="/images/zotero_icon.png" width="90" style="margin-right:15px" />
<img src="/images/zotero_logo.png" width="220" />
</a></p>

<p><br />
<a href="https://www.zotero.org/">Zotero</a> is a fantastic <a href="https://www.zotero.org/support/privacy">non-profit</a>, <a href="https://github.com/zotero">open source</a> paper and reference manager with <a href="https://www.zotero.org/why">a ton of cool features</a>. I mostly use it to organize and annotate papers, but it can be used for a lot, lot more!</p>

<p>While Zotero provides integrated library storage as part of the standalone application, I quickly overran the 300MB free tier, and didn’t want to worry about data quotas when I was adding papers to my library. (Note, you can still <a href="https://www.zotero.org/getinvolved/">support Zotero in other ways</a>.) Instead of storing paper files with Zotero, you can easily connect Zotero with a cloud storage provider like <a href="https://www.google.com/drive/">Google Drive</a>, <a href="https://www.dropbox.com/">Dropbox</a>, <a href="https://www.box.com/home">Box</a>, <a href="https://www.sync.com/">Sync</a> etc.</p>

<p>There’s <a href="https://www.researchgate.net/publication/325828616_Tutorial_The_Best_Reference_Manager_Setup_Zotero_ZotFile_Cloud_Storage">a great guide on doing this</a> with the <a href="http://zotfile.com/">Zotfile plugin</a> for Zotero, and while that guide adds more functionality I found the following steps to be a simpler and still effective way of integrating Zotero with cloud storage.</p>

<p><strong>1. Create an account on <a href="https://www.zotero.org/user/register">zotero.org</a></strong></p>

<p>This is free. Note that if syncing libraries between devices, Zotero will collect data as part of the syncing process, but <a href="https://www.zotero.org/support/privacy">has no financial incentive to sell your data</a>.</p>

<p><strong>2. Download Zotero standalone</strong></p>

<p>You can download the Zotero desktop app here: <a href="https://www.zotero.org/download/">https://www.zotero.org/download/</a></p>

<p><strong>3. Find the Zotero data directory</strong></p>

<p>On the top bar, go to Zotero → Preferences, and in the “Advanced” tab, find the “Data Directory Location”. This is where your PDFs are normally stored and linked to through Zotero.</p>

<p><img src="/images/zotero_advanced_settings.png" width="300" /></p>

<p><strong>4. Symlink the data directory with cloud storage</strong></p>

<p>This requires that your cloud storage provider has filesystem integration - which nearly all do. I’m using <a href="https://support.google.com/a/answer/7491144?hl=en">Google Drive File Stream</a> which mounts my cloud storage at <code class="language-plaintext highlighter-rouge">/Volumes/GoogleDrive/</code>. A service like Dropbox could link its sync folder in <code class="language-plaintext highlighter-rouge">/Users/&lt;user&gt;/Dropbox</code>, for example. Create a folder in the synced directory for storing PDFs.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="s2">"/Volumes/GoogleDrive/My Drive/papers"</span>
</code></pre></div></div>

<p>In the data directory folder, make a backup copy of your <code class="language-plaintext highlighter-rouge">storage/</code> directory, and then delete the original directory. Then, make a symbolic link (symlink) to the synced directory you created earlier.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Remove the original storage/ folder. Make a backup first!!!</span>
<span class="nb">rm</span> <span class="nt">-r</span> /Users/chena/Zotero/storage
<span class="c"># Make a symlink to the folder in the synced directory</span>
<span class="nb">ln</span> <span class="nt">-s</span> <span class="s2">"/Volumes/GoogleDrive/My Drive/papers"</span> <span class="s2">"/Users/chena/Zotero/storage"</span>
</code></pre></div></div>

<p>On Windows, the above syntax will be different:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Create a "directory junction" - windows version of a symlink</span><span class="w">
</span><span class="n">mklink</span><span class="w"> </span><span class="nx">/J</span><span class="w"> </span><span class="s2">"G:\My Drive\papers"</span><span class="w"> </span><span class="s2">"C:\Users\chena\Zotero\storage"</span><span class="w">
</span></code></pre></div></div>

<p><strong>5. Copy original data to the synced folder</strong></p>

<p>If you already had files stored in the original <code class="language-plaintext highlighter-rouge">storage/</code> directory, then move the contents of that directory back into the new <code class="language-plaintext highlighter-rouge">storage/</code> directory link, which now points to the synced folder.</p>

<p><img src="/images/zotero_symlinked.png" width="300" /></p>

<p>Now our <code class="language-plaintext highlighter-rouge">storage/</code> folder points to a synced folder, backed up by our cloud storage provider. (On Mac, that little arrow under the folder indicates the folder is a symlink)</p>

<p><strong>6. Enable Zotero Sync</strong></p>

<p>Go to Zotero → Preferences, and in the “Sync” tab, sign into your Zotero account. Enable “Automatic Sync” if you want changes to automatically push to their server. By disabling the “File Syncing” options, we are no longer uploading PDFs to Zotero’s servers, and instead using our symlinked storage folder to carry files across devices.</p>

<p><img src="/images/zotero_sync.png" width="300" /></p>

<p>That’s it! Now you can store unlimited papers (or whatever your data quota is on your cloud storage provider) across multiple devices.</p>

<p>Thanks to the Zotero team for creating a great reference management solution. It’s great.</p>]]></content><author><name></name></author><category term="research" /><category term="guide" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Valdar Sequence Conservation Code</title><link href="http://atchen.me/research/2019/09/26/valdar-conservation-code.html" rel="alternate" type="text/html" title="Valdar Sequence Conservation Code" /><published>2019-09-26T00:00:00+00:00</published><updated>2019-09-26T00:00:00+00:00</updated><id>http://atchen.me/research/2019/09/26/valdar-conservation-code</id><content type="html" xml:base="http://atchen.me/research/2019/09/26/valdar-conservation-code.html"><![CDATA[<p>Recently I needed to investigate <a href="https://en.wikipedia.org/wiki/Conserved_sequence">sequence conservation</a> for a project, and found that there was no easy-to-use script to generate conservation scores for a list of sequences.</p>

<p>The code is posted as a gist here: <a href="https://gist.github.com/atc3/f0260a99c5328a12f4b6fbbe65beec83">https://gist.github.com/atc3/f0260a99c5328a12f4b6fbbe65beec83</a>, as a python function and a CSV file for the <a href="https://doi.org/10.1093/bioinformatics/8.3.275">PET91 substitution matrix</a> (Thanks to <a href="https://github.com/ACRMGroup">@ACRMGroup</a> for <a href="https://github.com/ACRMGroup/bioplib/blob/master/data/pet91.mat">digitizing it</a>).</p>

<p>The conservation function I’m using is the “Valdar conservation score” described in <a href="https://doi.org/10.1002/1097-0134(20010101)42:1%3C108::AID-PROT110%3E3.0.CO;2-O">Valdar and Thornton, 2001</a>. It’s written from scratch and validated by checking the output on the same set of sequences when compared to the same Valdar score generated in <a href="https://www.snapgene.com/snapgene-viewer/">SnapGene Viewer</a>. Input a list of aligned sequences (I’m using <a href="http://www.clustal.org/omega/">Clustal Omega</a> for multiple sequence alignment), and the function returns a list of conservation scores - one for each base in the alignment. The score is scaled from 0 to 1, where 0 is not conserved at all, and 1 is perfectly conserved.</p>

<p>I’ve split up the code into some general parts so it should be simple to use a different substitution matrix (BLOSUM, etc) or a different amino acid similarity function entirely.</p>]]></content><author><name></name></author><category term="research" /><category term="code" /><category term="genomics" /><summary type="html"><![CDATA[Recently I needed to investigate sequence conservation for a project, and found that there was no easy-to-use script to generate conservation scores for a list of sequences.]]></summary></entry><entry><title type="html">Slavov Lab Sweaters</title><link href="http://atchen.me/design/2019/05/24/slavov-lab-sweaters.html" rel="alternate" type="text/html" title="Slavov Lab Sweaters" /><published>2019-05-24T00:00:00+00:00</published><updated>2019-05-24T00:00:00+00:00</updated><id>http://atchen.me/design/2019/05/24/slavov-lab-sweaters</id><content type="html" xml:base="http://atchen.me/design/2019/05/24/slavov-lab-sweaters.html"><![CDATA[<p>The <a href="http://slavovlab.net">Slavov Lab</a> recently got some embroidered team sweaters, so I decided to rework our <a href="https://atchen.me/design/2017/01/05/slavov-lab-logo.html">old logo design</a> with the help of some of my colleagues (s.o. to Annie Schide for the beautiful ribosomes!)</p>

<p><a href="https://northeastern.edu">Northeastern University</a> recently got a <a href="https://www.upstatement.com/work/northeastern-brand/">brand-new re-branding</a>, from the great designers over at <a href="https://www.upstatement.com/">Upstatement</a>. My first attempts at a sweater-friendly logo were closely led by <a href="https://brand.northeastern.edu/wp-content/uploads/NU_Brand_Book_digital.pdf">Northeastern’s Brand Book</a>.</p>

<h2 id="typography">Typography</h2>

<p>Some vanilla stuff, based on the strict guidelines in the brand book:</p>

<p><img src="/images/sweater_type_1.png" alt="" /></p>

<h2 id="lab-branding">Lab Branding</h2>

<p>We next decided to try to incorporate our rainbow colors from last round</p>

<p><img src="/images/sweaters_colorbar.png" alt="" width="50%" /></p>

<p><img src="/images/sweater_bar_text.png" alt="" width="50%" /></p>

<p>For the second row here, I followed the advice of my friend <a href="http://michaelrascati.com">Mike</a> and saturated/darkened some of the lighter colors.</p>

<p><img src="/images/sweater_rainbow_n.png" alt="" /></p>

<p>It also doesn’t look bad stacked vertically:</p>

<p><img src="/images/sweater_rainbow_vertical.png" alt="" width="70%" /></p>

<h2 id="ribosomes">Ribosomes!</h2>

<p>Our lab likes ribosomes, so we decided to try to make a graphic out of a bunch of them translating on an mRNA!</p>

<p><img src="/images/sweater_ribo_1.png" alt="" /></p>

<p>Getting our ribosomes to look less like birds on a power line…</p>

<p><img src="/images/sweater_ribo_2.png" alt="" width="40%" /></p>

<p>And finally, our design on different backgrounds:</p>

<p><img src="/images/sweater_final.png" alt="" width="50%" /></p>]]></content><author><name></name></author><category term="design" /><category term="illustrator" /><category term="brand" /><category term="digital" /><summary type="html"><![CDATA[The Slavov Lab recently got some embroidered team sweaters, so I decided to rework our old logo design with the help of some of my colleagues (s.o. to Annie Schide for the beautiful ribosomes!)]]></summary></entry><entry><title type="html">Targeted DDA in XCalibur</title><link href="http://atchen.me/research/2019/04/28/thermo-xcalibur-inclusion-list.html" rel="alternate" type="text/html" title="Targeted DDA in XCalibur" /><published>2019-04-28T00:00:00+00:00</published><updated>2019-04-28T00:00:00+00:00</updated><id>http://atchen.me/research/2019/04/28/thermo-xcalibur-inclusion-list</id><content type="html" xml:base="http://atchen.me/research/2019/04/28/thermo-xcalibur-inclusion-list.html"><![CDATA[<h1 id="table-of-contents">Table of Contents</h1>

<ul>
  <li><a href="#intro">Intro</a></li>
  <li><a href="#background">Background</a></li>
  <li><a href="#building-the-list">Building the List</a>
    <ul>
      <li><a href="#getting-the-data">Getting the Data</a></li>
      <li><a href="#generating-the-list">Generating the List</a></li>
    </ul>
  </li>
  <li><a href="#running-the-experiment">Running the Experiment</a>
    <ul>
      <li><a href="#instrument-settings">Instrument Settings</a></li>
    </ul>
  </li>
  <li><a href="#appendix">Appendix</a>
    <ul>
      <li><a href="#inclusion-list-format">Inclusion List Format</a></li>
    </ul>
  </li>
</ul>

<hr />

<h2 id="intro">Intro</h2>

<p>Running data-dependent acquisiton (DDA) mass spectrometry experiments in targeting mode is very powerful and desirable if you are trying to get around the bias towards more intense ions inherent in the data-dependent algorithm. For single cell proteomics methods (<a href="https://genomebiology.biomedcentral.com/articles/10.1186/s13059-018-1547-5">SCoPE-MS</a>, <a href="https://www.biorxiv.org/content/10.1101/399774v1">mPOP</a>) especially, where short methods and long injection times yield at most 10K MS/MS events per experiment, we may <em>need</em> targeting in order to analyze low-abundance pathways of interest.</p>

<p>Of course <a href="https://proteomicsresource.washington.edu/docs/protocols05/PRM_QExactive.pdf">SRM/PRM methods</a> are more sensitive, but they’re more limited in the number of proteins analyzed – targeted DDA is a nice middle ground to get what we want and a lot of it too.</p>

<p><a href="http://maxquant.live/">MaxQuant.Live</a> (<a href="https://doi.org/10.1074/mcp.TIR118.001131">link to manuscript</a>) is a great alternative to targeted DDA in Xcalibur, but it does require some extra set-up and tuning. Targeting in Xcalibur is less powerful, but may be more convenient for some users.</p>

<h2 id="background">Background</h2>

<p>Conventional DDA performs a survey scan (MS1 scan) on all ions passing through our MS, and then selects the <em>N</em> most intense ions (“Top N”) to analyze sequentially. It only will select an ion if it is not on an exclusion list and if it passes the AGC Min threshold. The algorithm will then accumulate the ion in an ion trap until either 1) the accumulation time hits the maximum injection time (IT) or 2) the number of ions hits the AGC Max threshold. Only then will the collected ions be released into the mass analyzer.</p>

<!--
```pseudocode
# pseudocode:

select N most intense ions
for ion in ions:
    if ion.intensity < AGC_min: continue;

    time_start = now

    while accumulating:
        if now - time_start > max_injection_time: break;
        if ion.accumulated_intensity > AGC_max: break;

    inject ion
```
-->

<p>When we put DDA into targeting mode, we give it a list of ions to look at. Instead of picking the <em>N</em> most intense ions after a survey scan, it will pick the <em>N</em> most intense ions that are <em>also</em> on the provided list of ions. These ions still have to pass the AGC Min threshold and the accumulation procedure is the same for non-targeted DDA.</p>

<h2 id="building-the-list">Building the List</h2>

<h3 id="getting-the-data">Getting the Data</h3>

<p>In order to tell the instrument to target ions, we must first identify them. You can build a targeting list from previous runs, but if these previous runs were run on conventional non-targeted DDA methods then we will be passing the instrument a list of the most abundant ions – defeating the purpose of running targeted DDA in the first place.</p>

<p>We want to analyze and sequence as many ions as we can, especially low-abundnce peptides that would normally be ignored by Top N DDA. We also want to match LC-MS/MS conditions as best as possible to the eventual targeted run, so fractionating or running a super-long gradient is not optimal.</p>

<p>To achieve this, we can:</p>

<p><strong>1)</strong> Run the sample of interest a few times back-to-back, but before each run add the IDs from the previous run to an exclusion list. While the first run will select only the most abundant ions, each successive run will select less and less abundant ions. Generating an exclusion list is almost the same process as generating the inclusion list, which is explained below.</p>

<p><strong>2)</strong> Run a bulkier sample with instrument settings tuned to maximize IDs at the expense of quantification quality. For low-abundance TMT sets, for example, this could mean decreasing the max injection time and tuning the NCE to maximize identifications instead of to maximize the number of TMT reporter ions (normally: 33 NCE → 28 NCE)</p>

<h3 id="generating-the-list">Generating the List</h3>

<p>All we have to provide the MS with for targeted DDA is 1) the target m/z, 2) the retention time window, and 3) the target ion’s charge. These are all fields that we can find from search results, such as from the evidence.txt output from a MaxQuant search. Reformatting your data is then as simple as a short script or copy/pasting columns in Excel.</p>

<p>Our lab uses MaxQuant, but since many of our experiments are TMT-tagged, and since MaxQuant does not calculate masses and m/z correctly for TMT-labelled peptides, we have to calculate the mass on our own. I wrote a script to do this and a few other useful things, such as simple retention time alignment. You can find it here: <a href="https://gist.github.com/atc3/84c35bc900f746fa21a558e278efc67c">https://gist.github.com/atc3/84c35bc900f746fa21a558e278efc67c</a></p>

<h2 id="running-the-experiment">Running the Experiment</h2>

<p>In XCalibur, open the Methods Editor and go to the tab for your mass spec. At the top of the MS method, click on “Global Lists”:</p>

<p><img src="/images/xcalibur_global_lists.png" alt="" height="50%" width="50%" /></p>

<p>From here you can specify inclusion and exclusion lists, among others. Click on “Inclusion List” to edit the method’s inclusion list.</p>

<p><img src="/images/xcalibur_inclusion_button.png" alt="" height="50%" width="50%" /></p>

<p>A dialog box should pop up with an excel-like editable table.</p>

<p><img src="/images/xcalibur_inclusion_dialog.png" alt="" height="50%" width="50%" /></p>

<p>If you don’t want to enter in values manually, you can import a .csv (such as the one generated with my script linked above)</p>

<p><img src="/images/xcalibur_inclusion_import.png" alt="" height="50%" width="50%" /></p>

<h3 id="instrument-settings">Instrument Settings</h3>

<p>To turn inclusion on, simply set the “inclusion” parameter to on in the method properties sidebar.</p>

<p><img src="/images/xcalibur_inclusion_on.png" alt="" width="25%" /></p>

<p>One other important behavior is what the instrument should do when it can’t find anything on the inclusion list. Should it do nothing? Or go for other peaks anyways? To expose this option first switch into advanced user mode, in the method properties sidebar:</p>

<p><img src="/images/xcalibur_user_role_advanced.png" alt="" width="50%" /></p>

<p>Then at the bottom you can choose your desired behavior.</p>

<p><img src="/images/xcalibur_if_idle.png" alt="" width="30%" /></p>

<h2 id="appendix">Appendix</h2>

<p>Thanks to <a href="http://edemmott.co.uk">Ed Emmott</a> for help &amp; knowledge.</p>

<h3 id="inclusion-list-format">Inclusion List Format</h3>

<p>Details taken from a <a href="file:///Users/albert/Downloads/PlanetOrbitrapA1410.pdf">QE-Plus software manual</a> and the XCalibur help pages.</p>

<p><strong>Mass [m/z]</strong>: Enter the mass-to-charge-ratio of the inclusion mass into the field (with a maximum of five decimals). <strong>NOTICE</strong>: If you use the Mass Calculator to edit the Formula field, this field is automatically
updated when you exit the editor.</p>

<p><strong>Formula [M]</strong>: Use this field to describe the structure of the active compound. In addition to chemical formulas, you can enter amino acid sequences (one letter code) and peptide sequences (if they are structural terminated by H<sub>2</sub>O). The different ways of definition are called formula types. You can either enter the formula directly or use the Mass Calculator. To display this editor, click the down arrow in this field.</p>

<p>If more than one formula type for your input is possible, the Method Editor chooses the type with the highest priority (chemical formula &gt; peptides &gt; amino acids). Peptide sequences are marked by the prefix “p:” (for example, p: MRFA with <em>m/z</em> = 524.26496), amino acids by the prefix “aa:” (for example, aa: MRFA with <em>m/z</em> = 506.25440). Enter a prefix directly with the formula to ensure that the right type is applied.</p>

<p>Pay attention to the following restrictions:</p>

<p>• When you enter a valid formula, the Method Editor will set the default values for charge state (1) and Species (+H/-H). Then it will display an automatically calculated value in the Mass [m/z] field.</p>

<p>• When you enter a formula that the Method Editor cannot interpret, the Mass [m/z] field will stay empty. When you save the method, the Method Editor will warn you that the method is not in the shape to be executed (due to the missing <em>m/z</em> value). When you reopen the method, the Method Editor will display exactly the formula that was entered.</p>

<p>• When you enter a formula, The Method Editor requires a value for the charge state to calculate an <em>m/z</em> value. You can, however, save the method without specifying a charge state for the entry. When you save the method, the Method Editor will warn you that the method is not in the shape to be executed (due to the missing charge state). When you reopen the method, the Method Editor will display exactly the formula that was entered.</p>

<p>• Entries of compounds with calculated <em>m/z</em> values outside the measurement specifications of the mass spectrometer (<em>m/z</em>=50–6000) can be saved in an instrument method. The instrument software, however, will ignore these entries when it executes the method.</p>

<p>• When you change the <em>m/z</em> value that was calculated for the given set of formula, species and charge state, the Method Editor will clear the formula and species definition. The charge state will be preserved.</p>

<p>• When you change the polarity for a set of calculated <em>m/z</em>, formula, species and charge state, the Method Editor will clear the Mass [m/z] field if the species definition is not valid for this polarity. You then need to change the species definition.</p>

<p><strong>Species</strong>: Use this text field to define adducts or modifications of the active compound that are expected to be formed. The default value is +H for positive polarity and –H for negative polarity. The Method Editor will then recalculate the value in the Mass [m/z] field, if possible.</p>

<p>The Species field can be used in two ways:</p>

<p>• Click the down arrow to display a list of predefined adducts for each polarity:</p>
<ul>
  <li>+H, +Na, +K, +NH4 for positive polarity</li>
  <li>-H, +Cl, +OH, +HCOO for negative polarity</li>
  <li>an empty entry to express adducts (for example, radical cations) for both polarities.</li>
</ul>

<p>The corresponding set will be displayed depending on the selected polarity.</p>

<p>Selecting an adduct (A) will result in the strict behavior of applying one unit A to the compound and using “+H” or “-H” adduct depending on the charge state and active polarity.</p>

<p>“+K” = [M + K<sup>+</sup> + (z-1)H<sup>+</sup>]<sup>z+</sup>; for example, MRFA, +K, CS=2, positive pol. = [M + K<sup>+</sup>+ H+]<sup>2+</sup></p>

<p>Enter the modifications of the compound by using squared brackets and at least M as representation of the basic compound (for example, [M + Na + K] or [2M + Na]). The predefined adducts can be entered, too. This definition is used without additional auto dependencies, like adding protons.</p>

<p>NOTICE: If you use the Mass Calculator to edit the Formula field, the Species field is automatically filled when you exit the editor.</p>

<p><strong>CS [z]</strong>:  Use this spin box to enter the charge state of the ion to be fragmented. The valid range is 1–25. The required collision energy for fragmenting an ion depends on its charge state. The higher the charge state, the lower the required collision energy. If this field is left blank, any
charge state will be accepted, even unassigned.</p>

<p>NOTICE If you use the Mass Calculator to edit the Formula field, this field is automatically updated when you exit the editor.</p>

<p><strong>Polarity</strong>: Use this list box to toggle between positive ion and negative ion polarity. During a scan, the mass spectrometer uses only the inclusion masses with a polarity that matches the active ion mode.</p>

<p>NOTICE If you use the Mass Calculator to edit the Formula field, this field is automatically updated when you exit the editor</p>

<p><strong>Start [min]</strong>: Enter the start of the time window (in minutes) that corresponds to the mass in this row. Alternatively, you can enter a time in seconds (by appending the letter s) or in hours (by appending the letter h). The software automatically converts your input into minutes.</p>

<p><strong>End [min]</strong>:  Enter the end of the time window in minutes. Alternatively, you can enter a time in seconds (by appending the letter s) or in hours (by appending the letter h). The software automatically converts your input into minutes.</p>

<p><strong>(N)CE</strong>: Use the spin box to enter a potential gradient in the HCD cell used to fragment ions. The default collision energy is 35 eV. In the list box, specify whether absolute collision energy CE [eV] is used or normalized collision energy NCE is used. The valid range is 10 to 200 eV for CE or 10 to 200 for NCE. In the list, the software adds the prefix “ce:” to collision energy values (for example, ce:35).</p>

<p>A high collision energy value results in more energy deposition (which generally leads to more fragmentation). A low collision energy value results in less energy deposition (which generally leads to less fragmentation).</p>

<p><strong>MSX ID</strong>: Enter the number of the multiplexed scan event in which the inclusion mass was analyzed.</p>

<p><strong>Comment</strong>: Enter a comment for the inclusion mass into the field (for example, the compound name). This field is optional.</p>]]></content><author><name></name></author><category term="research" /><category term="guide" /><category term="proteomics" /><category term="code" /><summary type="html"><![CDATA[Table of Contents]]></summary></entry><entry><title type="html">Row Reordering in DataTables/Shiny</title><link href="http://atchen.me/code/2019/04/09/datatables-rowreorder.html" rel="alternate" type="text/html" title="Row Reordering in DataTables/Shiny" /><published>2019-04-09T00:00:00+00:00</published><updated>2019-04-09T00:00:00+00:00</updated><id>http://atchen.me/code/2019/04/09/datatables-rowreorder</id><content type="html" xml:base="http://atchen.me/code/2019/04/09/datatables-rowreorder.html"><![CDATA[<p><a href="https://datatables.net/extensions/rowreorder/">Row reordering</a> is a cool extension to the <a href="https://datatables.net/">DataTables</a> library, which is packaged to R/Shiny through the <a href="https://rstudio.github.io/DT/">DT Package</a>. Unlike other table actions like row selecting, reordering doesn’t have functionality built in so it takes a little more effort to get it working.</p>

<p>First, we have to enable the extension by passing a few flags to the <code class="language-plaintext highlighter-rouge">renderDataTable</code> call. Since Shiny doesn’t have a JS –&gt; R hook built-in for the <a href="https://datatables.net/reference/event/row-reorder">row-reorder event</a>, we have to make it manually, with some custom javascript code.</p>

<div class="language-R highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">## server.R</span><span class="w">

</span><span class="c1"># example data</span><span class="w">
</span><span class="n">get_table</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">reactive</span><span class="p">({</span><span class="w">
    </span><span class="n">data.frame</span><span class="p">(</span><span class="w">
        </span><span class="n">A</span><span class="o">=</span><span class="nb">LETTERS</span><span class="p">[</span><span class="m">1</span><span class="o">:</span><span class="m">10</span><span class="p">]</span><span class="w">
        </span><span class="n">B</span><span class="o">=</span><span class="n">rnorm</span><span class="p">(</span><span class="m">10</span><span class="p">)</span><span class="w">
    </span><span class="p">)</span><span class="w">
</span><span class="p">})</span><span class="w">

</span><span class="n">output</span><span class="o">$</span><span class="n">table</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">DT</span><span class="o">::</span><span class="n">renderDataTable</span><span class="p">({</span><span class="w">
    </span><span class="n">get_table</span><span class="p">()</span><span class="w">
</span><span class="p">},</span><span class="w"> </span><span class="n">extensions</span><span class="o">=</span><span class="s1">'RowReorder'</span><span class="p">,</span><span class="w"> </span><span class="n">options</span><span class="o">=</span><span class="nf">list</span><span class="p">(</span><span class="n">rowReorder</span><span class="o">=</span><span class="nb">T</span><span class="p">),</span><span class="w"> </span><span class="n">callback</span><span class="o">=</span><span class="n">JS</span><span class="p">(</span><span class="w">
    </span><span class="s2">"// pass on data to R
    table.on('row-reorder', function(e, details, changes) {
        Shiny.onInputChange('table_row_reorder', JSON.stringify(details));
    });"</span><span class="w">
</span><span class="p">))</span><span class="w">

</span><span class="c1">## ui.R</span><span class="w">
</span><span class="n">DT</span><span class="o">::</span><span class="n">dataTableOutput</span><span class="p">(</span><span class="s1">'table'</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>

<p>Now, when we reorder the rows in our table, we will catch this event in our javascript and pass back the details of the reorder event via. the shiny event <code class="language-plaintext highlighter-rouge">table_row_reorder</code>. To change the underlying order of the table from this event, we first need to listen to the <code class="language-plaintext highlighter-rouge">table_row_reorder</code> event in the server.</p>

<div class="language-R highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># store the order of the table as a reactive value that we</span><span class="w">
</span><span class="c1"># can set and also listen for changes</span><span class="w">
</span><span class="n">table_order</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">reactiveVal</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="n">seq</span><span class="p">(</span><span class="m">1</span><span class="p">,</span><span class="m">10</span><span class="p">))</span><span class="w">

</span><span class="c1"># observe row reordering event - sent from javascript function</span><span class="w">
</span><span class="n">observeEvent</span><span class="p">(</span><span class="n">input</span><span class="o">$</span><span class="n">table_row_reorder</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="n">info</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">input</span><span class="o">$</span><span class="n">table_row_reorder</span><span class="w">
    </span><span class="c1"># error checking</span><span class="w">
    </span><span class="k">if</span><span class="p">(</span><span class="nf">is.null</span><span class="p">(</span><span class="n">info</span><span class="p">)</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nf">class</span><span class="p">(</span><span class="n">info</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="s1">'character'</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nf">return</span><span class="p">()</span><span class="w"> </span><span class="p">}</span><span class="w">

    </span><span class="c1"># I'm using the "yaml" package to read JSON, but you can use "jsonlite" </span><span class="w">
    </span><span class="c1"># if you want. just be aware that jsonlite also uses the "validate" </span><span class="w">
    </span><span class="c1"># function which conflicts with the same "validate" function in shiny.</span><span class="w">
    </span><span class="n">info</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">read_yaml</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="n">info</span><span class="p">)</span><span class="w">
    </span><span class="c1"># info will be empty if a reorder event fired but no row orders changed</span><span class="w">
    </span><span class="k">if</span><span class="p">(</span><span class="nf">length</span><span class="p">(</span><span class="n">info</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="m">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nf">return</span><span class="p">()</span><span class="w"> </span><span class="p">}</span><span class="w">

    </span><span class="c1"># load our order vectors</span><span class="w">
    </span><span class="n">.order</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">table_order</span><span class="p">()</span><span class="w">
    </span><span class="n">.new_order</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">.order</span><span class="w">

    </span><span class="c1"># for each updated row in the info object, update the order vector</span><span class="w">
    </span><span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">1</span><span class="o">:</span><span class="nf">length</span><span class="p">(</span><span class="n">info</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">info</span><span class="p">[[</span><span class="n">i</span><span class="p">]]</span><span class="w">
        </span><span class="n">.new_order</span><span class="p">[(</span><span class="n">j</span><span class="o">$</span><span class="n">newPosition</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">1</span><span class="p">)]</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="n">.order</span><span class="p">[(</span><span class="n">j</span><span class="o">$</span><span class="n">oldPosition</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="m">1</span><span class="p">)]</span><span class="w">
    </span><span class="p">}</span><span class="w">

    </span><span class="c1"># update our order vector's reactive value</span><span class="w">
    </span><span class="n">table_order</span><span class="p">(</span><span class="n">.new_order</span><span class="p">)</span><span class="w">
</span><span class="p">})</span><span class="w">
</span></code></pre></div></div>

<p>Here’s a slightly more complex version in action, inside <a href="https://github.com/SlavovLab/DO-MS">DO-MS</a>:</p>

<p><img src="/images/reorder_demo.gif" alt="" /></p>

<h2 id="bugs-glitches">Bugs, Glitches</h2>

<ul>
  <li>The left row-number column doesn’t change when reordering, but you could create your own “original order” column to let the user keep track of the original order</li>
  <li>There are some visual glitches/flashes when the table is updating. I understand that this can be fixed by modifying the underlying datatables instance directly with a <code class="language-plaintext highlighter-rouge">dataTableProxy()</code> object (<a href="https://rstudio.github.io/DT/shiny.html">as described here</a>), but I’ve had some issues with it and can’t get it to work</li>
</ul>]]></content><author><name></name></author><category term="code" /><category term="guide" /><category term="R" /><category term="shiny" /><summary type="html"><![CDATA[Row reordering is a cool extension to the DataTables library, which is packaged to R/Shiny through the DT Package. Unlike other table actions like row selecting, reordering doesn’t have functionality built in so it takes a little more effort to get it working.]]></summary></entry><entry><title type="html">MaxQuant in Linux</title><link href="http://atchen.me/research/2019/03/21/mq-linux.html" rel="alternate" type="text/html" title="MaxQuant in Linux" /><published>2019-03-21T00:00:00+00:00</published><updated>2019-03-21T00:00:00+00:00</updated><id>http://atchen.me/research/2019/03/21/mq-linux</id><content type="html" xml:base="http://atchen.me/research/2019/03/21/mq-linux.html"><![CDATA[<h1 id="guide-to-maxquant-in-linux">Guide to MaxQuant in Linux</h1>

<p>(MaxQuant Version 1.6.5.0 - <a href="http://www.maxquant.org/">Home Page</a>)</p>

<p>The popular proteomics search engine <a href="http://www.biochem.mpg.de/5111795/maxquant">MaxQuant</a> has <a href="https://www.nature.com/articles/s41592-018-0018-y">recently gone Linux</a>, after getting their code base to work with the Mono/C# runtime.</p>

<p>The <a href="http://coxdocs.org/doku.php?id=maxquant:common:download_and_installation">official documentation</a> on getting MaxQuant to run on Linux is sparse, so this repo is dedicated to passing on small tips and helper scripts that help people get started.</p>

<p>All code is hosted in <a href="https://github.com/atc3/maxquant_linux_guide">this GitHub repo</a></p>

<h1 id="table-of-contents">Table of Contents</h1>

<ul>
  <li><a href="#requirements">Requirements</a></li>
  <li><a href="#running-maxquant">Running MaxQuant</a></li>
  <li><a href="#partial-processing">Partial Processing</a></li>
  <li><a href="#helper-scripts">Helper Scripts</a></li>
</ul>

<h1 id="requirements">Requirements</h1>

<ul>
  <li>A decent computer</li>
  <li>Mono Framework &gt;= 5.4.1
    <ul>
      <li>&gt;&gt; <a href="https://www.mono-project.com/download/stable/#download-lin">Install Mono</a> for Linux</li>
      <li>Check version: <code class="language-plaintext highlighter-rouge">mono --version</code></li>
    </ul>
  </li>
</ul>

<p>Note, If searching Bruker timsTOF data, you need <code class="language-plaintext highlighter-rouge">gcc</code> version 8.3+. Check the version with <code class="language-plaintext highlighter-rouge">gcc --version</code>. You can install gcc8 with these commands:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># For CentOS 7:</span>

yum <span class="nb">install </span>centos-release-scl
yum <span class="nb">install </span>devtoolset-8
scl <span class="nb">enable </span>devtoolset-8 <span class="nt">--</span> bash

<span class="c"># Enable the tools (put this into .bash_profile)</span>
<span class="nb">source</span> /opt/rh/devtoolset-8/enable
</code></pre></div></div>

<p>(Thanks to <a href="https://github.com/cscaife">@cscaife</a> for identifying this step, and <a href="https://stackoverflow.com/a/55876012">https://stackoverflow.com/a/55876012</a> for the install instructions)</p>

<h1 id="running-maxquant">Running MaxQuant</h1>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="nv">$ </span>mono MaxQuant/bin/MaxQuantCmd.exe mqpar.xml
</code></pre></div></div>

<p>The default output options aren’t too descriptive to the exact task that MaxQuant is busy with, especially during the “Preparing for searches” step. You can query the exact status of your search by printing and grepping the process file names.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="nv">$ </span><span class="nb">ls</span> <span class="nv">$MQ_combined_folder</span>/combined/proc | <span class="nb">grep </span>started

MSMS_first_search 16.started.txt
MSMS_first_search 26.started.txt
MSMS_first_search 36.started.txt
MSMS_first_search 46.started.txt
</code></pre></div></div>

<p>You can also print the <code class="language-plaintext highlighter-rouge">#runningTimes.txt</code> table to see exactly which steps are taking the longest</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="nv">$ </span><span class="nb">cat</span> <span class="nv">$MQ_combined_folder</span>/combined/proc/#runningTimes.txt

Job Running <span class="nb">time</span> <span class="o">[</span>min]  Start <span class="nb">date  </span>Start <span class="nb">time  </span>End <span class="nb">date  </span>End <span class="nb">time
</span>Configuring   0.0168226333333333  14/11/2018  11:03:03  14/11/2018  11:03:04
Testing fasta files   0.0334432333333333  14/11/2018  11:03:04  14/11/2018  11:03:06
Testing raw files   0.11721345  14/11/2018  11:03:06  14/11/2018  11:03:13
Feature detection   5.0676712 14/11/2018  11:03:13  14/11/2018  11:08:17
Tmp folder cleanup  0.0172500333333333  14/11/2018  11:08:17  14/11/2018  11:08:18
Calculating peak properties   3.06749265  14/11/2018  11:08:18  14/11/2018  11:11:22
Combining apl files <span class="k">for </span>first search  0.216795733333333 14/11/2018  11:11:22  14/11/2018  11:11:35
Preparing searches  28.8861353833333  14/11/2018  11:11:35  14/11/2018  11:40:28
MS/MS first search  68.32271715 14/11/2018  11:40:28  14/11/2018  12:48:47
...
</code></pre></div></div>

<h1 id="partial-processing">Partial Processing</h1>

<p>The partial processing feature of the MaxQuant GUI is present in the command-line interface, but to run it you first need to list out the individual steps that MaxQuant wants to take. You can list these out by using the “dry-run” command – appending <code class="language-plaintext highlighter-rouge">-n</code> to the normal execution command.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="nv">$ </span>mono MaxQuant/bin/MaxQuantCmd.exe mqpar.xml <span class="nt">-n</span>

<span class="nb">id  </span>number of threads job name
0 1 Configuring 
1 1 Testing fasta files 
2 8 Testing raw files 
3 8 Feature detection 

...

39  1 Prepare writing tables  
40  8 Writing tables 
41  1 Finish writing tables
</code></pre></div></div>

<p>Then use the <code class="language-plaintext highlighter-rouge">--partial-processing=[id]</code> flag to tell MaxQuant to start at that specific step</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="nv">$ </span>mono MaxQuant/bin/MaxQuantCmd.exe mqpar.xml <span class="nt">--partial-processing</span><span class="o">=</span>35
</code></pre></div></div>

<p>For the best chance to run partial processing successfully, you should have run the previous steps with the <strong><em>same</em></strong> <code class="language-plaintext highlighter-rouge">mqpar.xml</code> configuration file. Although it could be possible that partial processing tolerates small configuration changes (for example, the feature detection step may not depend at all on the variable modification settings), for reproducibility’s sake it is best to be consistent with your configuration files. (I haven’t tested this thoroughly, so if you know more get back to me!)</p>

<h1 id="helper-scripts">Helper Scripts</h1>

<p>Nowadays I’m running MaxQuant on <a href="https://its.northeastern.edu/researchcomputing/overview/">Northeastern’s Research Computing cluster</a> which is hosted at the <a href="https://www.mghpcc.org/">Massachusetts Green High-Performance Computing Center (MGHPCC)</a> in Holyoke, MA. It uses the <a href="https://slurm.schedmd.com/documentation.html">Slurm workload manager</a> to run tasks, and as such I have to package all of my MaxQuant calls into slurm-compatible bash scripts.</p>

<p>All code is hosted in <a href="https://github.com/atc3/maxquant_linux_guide">this GitHub repo</a></p>

<p>I have one python script, <code class="language-plaintext highlighter-rouge">gen_mqpar.py</code>, which takes as input the <code class="language-plaintext highlighter-rouge">mqpar.xml</code> template, folder(s) of raw files, and some other parameters to generate both a filled-out <code class="language-plaintext highlighter-rouge">mqpar.xml</code> file and a bash script that can be run by slurm.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="nv">$ </span>./gen_mqpar.py <span class="nt">-h</span>
usage: gen_mqpar.py <span class="o">[</span><span class="nt">-h</span><span class="o">]</span> <span class="nt">-o</span> OUTFILE <span class="o">[</span><span class="nt">-mq</span> <span class="o">{</span>1_6_2_3,1_6_2_10,1_6_3_2,1_6_3_3<span class="o">}]</span>
                    <span class="o">[</span><span class="nt">-t</span> THREADS]
                    input_xml raw_file_folders <span class="o">[</span>raw_file_folders ...]

MaxQuant <span class="k">for </span>linux

positional arguments:
  input_xml
  raw_file_folders

optional arguments:
  <span class="nt">-h</span>, <span class="nt">--help</span>            show this <span class="nb">help </span>message and <span class="nb">exit</span>
  <span class="nt">-o</span> OUTFILE, <span class="nt">--outfile</span> OUTFILE
  <span class="nt">-mq</span> <span class="o">{</span>1_6_2_3,1_6_2_10,1_6_3_2,1_6_3_3<span class="o">}</span>, <span class="nt">--mq-version</span> <span class="o">{</span>1_6_2_3,1_6_2_10,1_6_3_2,1_6_3_3<span class="o">}</span>
                        MaxQuant version
  <span class="nt">-t</span> THREADS, <span class="nt">--threads</span> THREADS
                        Number of threads to specify <span class="k">in </span>MaxQuant configuration
                        file
</code></pre></div></div>

<p>Example:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="nv">$ </span>./gen_mqpar.py templates/SILAC.xml raw_files/FP93 <span class="nt">-o</span> fp93_silac.xml <span class="nt">-t</span> 6
success!
</code></pre></div></div>

<p>I keep a list of templates in a folder, <code class="language-plaintext highlighter-rouge">templates/</code>, which I can pull from when I want to change the parameters of a search. For example, I might do a normal TMT search to get quantitation, and also search where TMT is a variable mod to see my labeling efficiency.</p>

<p>Also note that I keep multiple versions of MaxQuant on hand, in case any of them breaks for some reason or another. I manage these versions with aliases in my <code class="language-plaintext highlighter-rouge">.bashrc</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">MQ_1_6_2_3</span><span class="o">=</span>~/MQ_1.6.2.3/bin/MaxQuantCmd.exe
<span class="nv">MQ_1_6_2_10</span><span class="o">=</span>~/MQ_1.6.2.10/bin/MaxQuantCmd.exe
<span class="nv">MQ_1_6_3_2</span><span class="o">=</span>~/MQ_1.6.3.2/bin/MaxQuantCmd.exe
<span class="nv">MQ_1_6_3_3</span><span class="o">=</span>~/MQ_1.6.3.3/bin/MaxQuantCmd.exe
</code></pre></div></div>

<p>As I want all of my MaxQuant versions to have the same <code class="language-plaintext highlighter-rouge">modifications.xml</code> list, I have a symlink going from <code class="language-plaintext highlighter-rouge">bin/conf/modifications.xml</code> to a common <code class="language-plaintext highlighter-rouge">modifications.xml</code> file that I maintain.</p>

<p>The script outputs an XML file that is ready to run by <code class="language-plaintext highlighter-rouge">MaxQuantCmd.exe</code>, and a shell script that can be queued up by the slurm job manager:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
<span class="c">#SBATCH --job-name=fp103f</span>
<span class="c">#SBATCH --output=fp103f.out</span>
<span class="c">#SBATCH --ntasks=1</span>
<span class="c">#SBATCH --cpus-per-task=16</span>
<span class="c">#SBATCH --mem-per-cpu=1000</span>
<span class="c">#SBATCH --time=24:0:0</span>
<span class="c">#SBATCH --partition=general</span>

<span class="nb">source</span> /home/chen.alb/.bashrc
srun mono <span class="nv">$MQ_1_6_3_3</span> /home/chen.alb/fp103f.xml
</code></pre></div></div>

<p>Check out the git repo with all the code and some examples shown: <a href="https://github.com/atc3/maxquant_linux_guide">https://github.com/atc3/maxquant_linux_guide</a>.</p>

<p>All in all, this workflow is great for me, as I just upload some raw files, then run:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;</span><span class="nv">$ </span>./gen_mqpar.py templates/SILAC.xml raw_files/FP93 <span class="nt">-o</span> fp93_silac.xml <span class="nt">-t</span> 6
<span class="o">&gt;</span><span class="nv">$ </span>sbatch scripts/fp93_silac.sh
...
</code></pre></div></div>

<p>And I’m done! I have to wait for a long time for the run to finish, of course, but I try to not babysit the task and just check back after a few hours.</p>

<h3 id="notes">Notes:</h3>

<p>The <code class="language-plaintext highlighter-rouge">gen_mqpar.py</code> script does create separate output, temp, and andromeda index directories for each search. This was done because I noticed that sharing any of these directories could result in conflicts where two concurrent searches would try to access the same resource at the same time and then one of them would crash. I know this does slow down my search times, especially since all the andromeda indices are separate, but the cluster is fast anyways so I’m willing to take this hit.</p>]]></content><author><name></name></author><category term="research" /><category term="guide" /><category term="proteomics" /><category term="code" /><summary type="html"><![CDATA[Guide to MaxQuant in Linux]]></summary></entry><entry><title type="html">Easy Monday Covers - Unreleased Pt. 2</title><link href="http://atchen.me/art/2019/03/18/easy-monday-unreleased-2.html" rel="alternate" type="text/html" title="Easy Monday Covers - Unreleased Pt. 2" /><published>2019-03-18T00:00:00+00:00</published><updated>2019-03-18T00:00:00+00:00</updated><id>http://atchen.me/art/2019/03/18/easy-monday-unreleased-2</id><content type="html" xml:base="http://atchen.me/art/2019/03/18/easy-monday-unreleased-2.html"><![CDATA[<p>Unreleased album covers for my friends Soundcloud, <a href="https://soundcloud.com/easy-monday">Easy Monday</a>, Part 2</p>

<p><img src="/images/beachtime-monday.gif" alt="" /></p>

<p><img src="/images/garf-demonic.png" alt="" /></p>

<p><img src="/images/tigervhs.png" alt="" /></p>

<p><img src="/tumblr_files/tumblr_osu7paAgKT1r8gweso1_640.png" alt="" /></p>

<p>Apologies to ∆</p>

<p><img src="/tumblr_files/tumblr_osu7paAgKT1r8gweso2_640.png" alt="" /></p>

<p>Bonus: MIA AIM:</p>

<p><img src="/images/waves-boring.gif" alt="" /></p>]]></content><author><name></name></author><category term="art" /><category term="easy-monday" /><category term="album-art" /><category term="digital" /><category term="photoshop" /><summary type="html"><![CDATA[Unreleased album covers for my friends Soundcloud, Easy Monday, Part 2]]></summary></entry></feed>