<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Boyd Tarlinton</title>
<link>https://boyd.tarlinton.au/listings.html</link>
<atom:link href="https://boyd.tarlinton.au/listings.xml" rel="self" type="application/rss+xml"/>
<description></description>
<generator>quarto-1.6.42</generator>
<lastBuildDate>Sat, 20 Sep 2025 14:00:00 GMT</lastBuildDate>
<item>
  <title>September/October Events</title>
  <dc:creator>Boyd Tarlinton</dc:creator>
  <link>https://boyd.tarlinton.au/posts/sept_oct_events.html</link>
  <description><![CDATA[ 




<p>The last two months have been packed with exciting scientific events, which I’d like to briefly recap here.</p>
<p>The first event was the Make it Snappy challenge, held between departments at my workplace as part of National Science Week 2025. This was a fun opportunity to deliver a rapid-fire presentation in the vein of the Three Minute Thesis. Creating and rehearsing a presentation to be delivered in such a short timeframe was a new experience for me, and one that I really enjoyed. It was also fantastic to see some of the work being done by people in my office that is very different to my own.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://boyd.tarlinton.au/posts/images/mis.jpg" class="img-fluid figure-img" width="400"></p>
<figcaption>Make it Snappy challenge</figcaption>
</figure>
</div>
<p>Next up was the Avocado Production R&amp;D Summit. I got to absorb a full day of presentations on key avocado research projects being conducted across Australia. This event did a particularly great job of approaching scientific research with an industry perspective.</p>
<p>Finally, I attended The Future of Hort Science Roadshow, hosted by the Australian Society of Horticultural Science with funding by the National Farmers’ Federation. I was fortunate enough to get the opportunity to present at this event and even received a travel award to do so. The other presentations were excellent, and the enthusiasm for horticulture among the attendees was palpable. The event also featured a fantastic keynote presentation by Honorary Professor Daryl Joyce, whom I have been fortunate enough to work with for the past two years.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://boyd.tarlinton.au/posts/images/fhs_roadshow.jpg" class="img-fluid figure-img" width="400"></p>
<figcaption>Future of Hort Science Roadshow</figcaption>
</figure>
</div>



 ]]></description>
  <category>Events</category>
  <guid>https://boyd.tarlinton.au/posts/sept_oct_events.html</guid>
  <pubDate>Sat, 20 Sep 2025 14:00:00 GMT</pubDate>
</item>
<item>
  <title>Supply Chain Attestations in Docker Hub</title>
  <dc:creator>Boyd Tarlinton</dc:creator>
  <link>https://boyd.tarlinton.au/posts/docker_provenance.html</link>
  <description><![CDATA[ 




<p>If you have a subscription to Docker Hub, Docker’s automated builds can be an important part of your CI/CD pipelines. You might expect it to be simple to add SBOM or provenance attestations to images built in Docker Hub, especially given given the warnings produced by Docker Scout if you fail to do so. Unfortunately, due to some lacking documentation, the process can be tricky. But, once you understand a few intricacies, you will be able to add supply chain attestations to your builds with little trouble.</p>
<p>Making any changes to the default build instructions supplied to the Docker Hub automated build system requires you to add a custom build hook in <code>/hooks/build</code>. Here is a custom build hook with code that, having read <a href="https://docs.docker.com/build/metadata/attestations/">the docs</a>, you might assume would add your supply chain attestations.</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>/hooks/build</strong></pre>
</div>
<div class="sourceCode" id="cb1" data-filename="/hooks/build" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#!/bin/bash</span></span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> buildx build <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--sbom</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>generator=docker/scout-sbom-indexer:latest <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--provenance</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>mode=max <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$IMAGE_NAME</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--output</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>type=registry .</span></code></pre></div>
</div>
<p>In reality, it’s not quite so simple. As pointed out in <a href="https://forums.docker.com/t/docker-hub-automated-build-with-providence-attestation/148412">this helpful comment thread</a>, the version of Docker running in Docker Hub’s automated pipelines is out of date, requiring you to use a custom builder.</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>/hooks/build</strong></pre>
</div>
<div class="sourceCode" id="cb2" data-filename="/hooks/build" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#!/bin/bash</span></span>
<span id="cb2-2"></span>
<span id="cb2-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> buildx create <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--name</span> container <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--driver</span> docker-container <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--use</span></span>
<span id="cb2-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">docker</span> buildx build <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--sbom</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>generator=docker/scout-sbom-indexer:latest <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--provenance</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>mode=max <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$IMAGE_NAME</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--output</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>type=registry .</span></code></pre></div>
</div>
<p>If you run this, you will see your build succeed in docker hub. But when you try to pull and run your latest image, you will notice that it doesn’t work. This is because the custom build instructions we are using automatically pushes to the registry, but the default push instruction included in the Docker Hub build pipeline is still being run immediately afterwards, overwriting your successful build. Fortunately, the solution is very simple – you just need to overwrite the default push instructions with a blank hook.</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>/hooks/push</strong></pre>
</div>
<div class="sourceCode" id="cb3" data-filename="/hooks/push" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#!/bin/bash</span></span></code></pre></div>
</div>
<p>You should now have a working build pipeline with supply chain attestations.</p>



 ]]></description>
  <category>Docker</category>
  <guid>https://boyd.tarlinton.au/posts/docker_provenance.html</guid>
  <pubDate>Wed, 10 Sep 2025 14:00:00 GMT</pubDate>
</item>
<item>
  <title>Managing Remote Database Connections from Quarto Documents</title>
  <dc:creator>Boyd Tarlinton</dc:creator>
  <link>https://boyd.tarlinton.au/posts/remote_databases.html</link>
  <description><![CDATA[ 




<p>R offers excellent facilities for working interactively with SQL databases on a remote server. It becomes more challenging to do so in a self-contained Quarto document, especially if you wish to be able to render it without running into errors. Fortunately, there are ways around these challenges.</p>
<p>The first step is establishing an SSH connection with the remote server on which your database is running, allowing you to interact with the database as though it were running on your own device. In an interactive session you could use the following code to establish an SSH connection and open a tunnel. The <code>ssh_tunnel</code> function will run indefinitely, leaving you unable to execute other code, but you can open a second R session and communicate with the database in that second session.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb1-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb1-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">session &lt;- ssh::ssh_connect("username@targetserver.com")</span></span>
<span id="cb1-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">ssh::ssh_tunnel(session, port = 3305, </span></span>
<span id="cb1-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">         target = "localhost:3306")</span></span>
<span id="cb1-5"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
</div>
<p>In the example above we map port 3306 on the remote server (the default port for MySQL) to port 3305 on our local machine. You will often want to use the same port on the local machine, but I find it is easier to keep track of examples where different values are used.</p>
<p>In a Quarto document you will need to run the SSH tunnel in the background. This is made easy with the <code>callr</code> package. The example below will run the SSH tunnel in a separate background process.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb2-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb2-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">rbg &lt;- callr::r_bg(\() {</span></span>
<span id="cb2-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  session &lt;- ssh::ssh_connect("username@targetserver.com")</span></span>
<span id="cb2-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  ssh::ssh_tunnel(session, port = 3305, </span></span>
<span id="cb2-5"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">           target = "localhost:3306")</span></span>
<span id="cb2-6"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">})</span></span>
<span id="cb2-7"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
</div>
<p>You can now open a connection to the database as though it were running on your local machine on port 3305. Given that the SSH tunnel is opened in a separate process, I often find that if you attempt to connect to the database<br>
directly after opening the tunnel you will encounter an error. To prevent this, I use <code>Sys.sleep()</code> to add a delay and allow the SSH tunnel to finish connecting before establishing the connection to the database.</p>
<p>It is easiest and safest to manage your database connections with a configuration file. Typically these are stored in a user directory, but I prefer to create them on a per-project basis.</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>.my.cnf</strong></pre>
</div>
<div class="sourceCode" id="cb3" data-filename=".my.cnf" style="background: #f1f3f5;"><pre class="sourceCode cnf code-with-copy"><code class="sourceCode toml"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[groupname]</span></span>
<span id="cb3-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">database</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mydatabase"</span></span>
<span id="cb3-3"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">host</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"localhost"</span></span>
<span id="cb3-4"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">port</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"3305"</span></span>
<span id="cb3-5"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">user</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"username"</span></span>
<span id="cb3-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">password</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mypassword"</span></span></code></pre></div>
</div>
<p>You can use the a conf file setup like above to connect to the database.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb4-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb4-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">con &lt;- DBI::dbConnect(RMySQL::MySQL(), </span></span>
<span id="cb4-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">                 group = "groupname", </span></span>
<span id="cb4-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">                 default.file = ".my.cnf")</span></span>
<span id="cb4-5"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
</div>
<p>You can now access the database using <code>DBI</code> in R.</p>
<p>If you are already an experienced SQL user, you can write SQL directly in Quarto using your established connection. The ability to switch between R, Python, and even Julia is marketed quite heavily by the Posit team, while this SQL functionality seems much more obscure.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb5-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{sql}</span></span>
<span id="cb5-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| connection: "con"</span></span>
<span id="cb5-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">select * from mytable;</span></span>
<span id="cb5-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
</div>
<p>You can even output of an SQL query to an R object, in this example named <code>df</code>, allowing you to seamlessly integrate SQL queries and R code.</p>
<div class="cell" data-output.var="df">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb6-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{sql}</span></span>
<span id="cb6-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| connection: "con"</span></span>
<span id="cb6-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| output.var: "df"</span></span>
<span id="cb6-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">select * from mytable;</span></span>
<span id="cb6-5"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
</div>
<p>You should now be set to query with confidence.</p>



 ]]></description>
  <category>R</category>
  <category>Databases</category>
  <guid>https://boyd.tarlinton.au/posts/remote_databases.html</guid>
  <pubDate>Sat, 09 Aug 2025 14:00:00 GMT</pubDate>
</item>
<item>
  <title>Apply the Dracula Theme to Quarto Websites</title>
  <dc:creator>Boyd Tarlinton</dc:creator>
  <link>https://boyd.tarlinton.au/posts/dracula_theme.html</link>
  <description><![CDATA[ 




<p>I am something of a <a href="https://draculatheme.com/">Dracula theme</a> fanatic. After first discovering the open-source theme in RStudio, I had to see if it was supported by other applications. To my delight, I found custom Dracula themes for over 400 applications. Applying these themes to my OS, IDEs, browsers, and other applications is now the first thing I do when I install a new tool or set up a computer. I’ve even gone so far as to get <a href="https://oblotzky.industries/products/gmk-cyl-dracula-v2">Dracula keycaps for my mechanical keyboard</a>.</p>
<p>When I decided to add dark mode to my <code>Quarto</code> website, Dracula was the obvious choice. But, given the wide-ranging support for the theme, I was surprised to discover there was no pre-packaged Bootstrap theme which I could plug into <code>Quarto</code>. Of course, I wasn’t going to let that stop me!</p>
<p>Starting with the <a href="https://bootswatch.com/darkly/">Darkly theme from Bootswatch</a> as a base, I customised the theme to incorporate the <a href="https://draculatheme.com/contribute#color-palette">Dracula palette</a> using the handy <a href="https://www.bootstrap-live-customizer.com/">Bootstrap Live Customizer</a> tool, before exporting the resulting LESS code and converting it to the SCSS required by <code>Quarto</code>. I had to remove a few variables which seemed to cause issues when rendering. After a few additional tweaks, I was left with a Dracula themed site that felt like home. You can access the SCSS file <a href="https://github.com/B0ydT/boyd/blob/main/styles-dark.scss">here</a>. If you’re reading this post through an aggregator, you can see it in action on my original post.</p>
<p>There are a few things to consider when adding the Dracula theme to your own <code>Quarto</code> site. Not all viewers prefer the dark mode experience, so I prefer to let the user decide. In the snippet from my site-wide YAML configuration below, the user is offered a choice between a light and dark mode (Darkly + Dracula), but the website defaults to the user’s system preference. I also specified a custom font to be used across both themes, as I wanted to minimize changes besides colour when switching between themes. As a final touch, specify Dracula code highlighting if you are going to be including code chunks. You may optionally include a styles.css file in the root directory of the project,<br>
incorporating other style changes that are applied across both themes.</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb1-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">format</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">html</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">respect-user-color-scheme</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb1-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span></span>
<span id="cb1-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dark</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">darkly</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">,</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> styles-dark.scss</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span>
<span id="cb1-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">light</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> sandstone</span></span>
<span id="cb1-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">    header-includes</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">: </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">|</span></span>
<span id="cb1-9">      &lt;link rel="stylesheet" media="screen" href="https://fonts.googleapis.com/css2?family=Fira+Sans" type="text/css"/&gt;</span>
<span id="cb1-10">      &lt;link rel="stylesheet" media="screen" href="https://fonts.googleapis.com/css2?family=Fira+Code" type="text/css"/&gt;</span>
<span id="cb1-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mainfont</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fira Sans"</span></span>
<span id="cb1-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">monofont</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Fira Code"</span></span>
<span id="cb1-13"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">highlight-style</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Dracula</span></span>
<span id="cb1-14"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div>
<p>Hopefully this will be of use to some other Dracula diehards out there. I’m sure I will continue to tweak the SCSS file as I spot opportunities for improvement.</p>



 ]]></description>
  <category>R</category>
  <guid>https://boyd.tarlinton.au/posts/dracula_theme.html</guid>
  <pubDate>Fri, 11 Jul 2025 14:00:00 GMT</pubDate>
</item>
<item>
  <title>Beyond the Basics: Books to Supercharge Your R Skills</title>
  <dc:creator>Boyd Tarlinton</dc:creator>
  <link>https://boyd.tarlinton.au/posts/r_books.html</link>
  <description><![CDATA[ 




<div class="page-columns page-full"><p>There are a plethora of great books that are widely recommended for the beginner R user, but I many users often find their skills plateauing once they learn just enough to get by on a day-to-day basis. These are some of the books that helped me to break through that plateau and take full advantage of R. </p><div class="no-row-height column-margin column-container"><span class="margin-aside">And doesn’t it reflect well on the R community that all of these books are available for free?</span></div></div>
<section id="advanced-r" class="level3">
<h3 class="anchored" data-anchor-id="advanced-r"><a href="https://adv-r.hadley.nz/index.html">Advanced R</a></h3>
<p>Advanced R is the best one stop shop for everything about R that your introductory courses and textbooks didn’t teach you. It is a relatively dense book and, if you’re like me, it might not be immediately clear why some of the techniques and strategies are so valuable. By at least browsing the entire book, you will gain a much better understanding of what advanced programming strategies are available to you in R. If you can recognise when these techniques are needed in your own work you can revisit the relevant chapters as needed.</p>
</section>
<section id="the-r-inferno" class="level3">
<h3 class="anchored" data-anchor-id="the-r-inferno"><a href="https://www.burns-stat.com/documents/books/the-r-inferno/">The R Inferno</a></h3>
<p>I often learn from making mistakes, fixing them, and learning to avoid them in the future. The R Inferno helped me avoid a lot of mistakes, pointing out a lot of R’s sharpest edges and how to avoid them. It is not necessarily a book that you should work through like a textbook – it is another dense book, and it helps to reflect on chapters as you work on some relevant code. This is one book that I often revisit, finding more to take away each time.</p>
</section>
<section id="r-packages" class="level3">
<h3 class="anchored" data-anchor-id="r-packages"><a href="https://r-pkgs.org/">R Packages</a></h3>
<p>Given his massive contributions to R in general and the <code>tidyverse</code>, it is no surprise that Hadley Wickham is an author of two entries on this list (the other being Advanced R). Even if you don’t intend to create and publish R packages for others to use, they can be an incredibly valuable part of your workflow. Making your code portable and reusable can yield massive efficiencies, and knowing how R packages work under the hood can make debugging code or contributing to open-source software much easier. Now in its second edition, R Packages should be your go to for anything related to… R packages.</p>
</section>
<section id="building-reproducible-analytical-pipelines-with-r-raps-with-r" class="level3">
<h3 class="anchored" data-anchor-id="building-reproducible-analytical-pipelines-with-r-raps-with-r"><a href="https://raps-with-r.dev/">Building Reproducible Analytical Pipelines With R (RAPs With R)</a></h3>
<p>The most recently published book on this list, RAPs with R has quickly become one of my favourites, collecting some of the highest yield strategies the data scientist or analyst can implement to ensure reproducibility in their work. This is an incredibly readable book that you can sit down and work through from start to finish, following along with practical examples. The section on Git is incredibly useful for R users, who typically aren’t exposed to version control in introductory courses. RAPS with R also helps illustrate how writing functions and packages should be part of any R user’s workflow, whileI have found the section on deploying R code in docker containers particularly valuable in my own work.</p>
</section>
<section id="engineering-production-grade-shiny-apps" class="level3">
<h3 class="anchored" data-anchor-id="engineering-production-grade-shiny-apps"><a href="https://engineering-shiny.org/index.html">Engineering Production-Grade Shiny Apps</a></h3>
<p>This final entry is different from the others in that I wouldn’t necessarily recommend it to every user – it is really only useful for those trying to make interactive <code>shiny</code> applications. That said, it is so good for that purpose that I wanted to highlight it. The <code>golem</code> approach to <code>shiny</code> applications championed by this book is a total game changer. Writing clean, modular code, and making use of the bundled deployment tools makes building interactive applications much less stressful. If you’re looking to make your R code useful to a wider audience through interactive applications, this could be a game changer.</p>


</section>

 ]]></description>
  <category>R</category>
  <guid>https://boyd.tarlinton.au/posts/r_books.html</guid>
  <pubDate>Thu, 26 Jun 2025 14:00:00 GMT</pubDate>
</item>
<item>
  <title>Three Tips for Better R Figures</title>
  <dc:creator>Boyd Tarlinton</dc:creator>
  <link>https://boyd.tarlinton.au/posts/plot_design.html</link>
  <description><![CDATA[ 




<p>Recently I shared my favourite ways to <a href="../posts/quarto_plots.html">ensure your R plots look great in <code>Quarto</code> documents</a>. Now I want to share my most commonly used tips for building effective and readable plots in <code>R</code>.</p>
<p>As an example dataset I’ll be using chip_dataset.csv, downloaded from <a href="https://chip-dataset.vercel.app/">Vercel</a>. Redistribution of the dataset is not permitted.</p>
<p>Let’s create a rough figure, and see how we can improve it in a few simple steps.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb1-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb1-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| dev: "CairoPNG" </span></span>
<span id="cb1-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| fig-cap: "A rough figure"</span></span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(ggplot2)</span></span>
<span id="cb1-6"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(dplyr)</span></span>
<span id="cb1-7"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(lubridate)</span></span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">chips &lt;- read.csv("chip_dataset.csv")</span></span>
<span id="cb1-10"></span>
<span id="cb1-11"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">chips &lt;- chips |&gt; </span></span>
<span id="cb1-12"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  mutate(Date = mdy(Release.Date),</span></span>
<span id="cb1-13"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">         transistors = as.numeric(Transistors..million.)) |&gt;</span></span>
<span id="cb1-14"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  filter(Foundry != "" &amp;</span></span>
<span id="cb1-15"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">           Type == "GPU" &amp;</span></span>
<span id="cb1-16"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">           !is.na(Date) &amp;</span></span>
<span id="cb1-17"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">           !is.na(transistors))</span></span>
<span id="cb1-18"></span>
<span id="cb1-19"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">chips |&gt; </span></span>
<span id="cb1-20"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  ggplot(aes(x = Date, </span></span>
<span id="cb1-21"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">           y = transistors, </span></span>
<span id="cb1-22"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">           color = Foundry)) +</span></span>
<span id="cb1-23"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    geom_point()</span></span>
<span id="cb1-24"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://boyd.tarlinton.au/posts/plot_design_files/figure-html/unnamed-chunk-1-1.png" class="img-fluid figure-img" width="672"></p>
<figcaption>A rough figure</figcaption>
</figure>
</div>
</div>
</div>
<section id="pick-a-great-base-theme" class="level3">
<h3 class="anchored" data-anchor-id="pick-a-great-base-theme">Pick a great base theme</h3>
<p>With <code>R</code> being more popular than ever, the default <code>ggplot2</code> theme is <em>everywhere</em>. In addition to being overused, the grey background can be a bit much. <code>ggplot2::theme_minimal</code> is an easy substitute and a great base for further customisation, but I really like <code>hrbrthemes::theme_ipsum</code>.</p>
</section>
<section id="use-an-effective-colour-palette" class="level3">
<h3 class="anchored" data-anchor-id="use-an-effective-colour-palette">Use an effective colour palette</h3>
<p>Effective use of colour can ensure that your plots are able to be interpreted at a glance. The <code>viridis</code> palettes help to ensure that different values are distinct, and are colourblind-friendly. Like the base <code>ggplot2</code> theme, <code>viridis</code> palettes are everywhere, but it’s a hard choice to argue with!</p>
</section>
<section id="modify-your-theme" class="level3">
<h3 class="anchored" data-anchor-id="modify-your-theme">Modify your theme</h3>
<p>Even though we’ve chosen a great theme, it’s still important to consider whether it perfectly suits you needs. For example, I often like to drop the x-axis gridlines for a cleaner look. I will also place the legend below the plot, to allow the main contents to fill the page.</p>
<p>We’ll apply the tips described above, as well as rescaling the y-axis and adding some trendlines. Do you think this is a more effective figure?</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb2-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb2-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| dev: "CairoPNG" </span></span>
<span id="cb2-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| label: feature-image</span></span>
<span id="cb2-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| fig-cap: "The final figure"</span></span>
<span id="cb2-5"></span>
<span id="cb2-6"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(hrbrthemes)</span></span>
<span id="cb2-7"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(sysfonts)</span></span>
<span id="cb2-8"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(viridis)</span></span>
<span id="cb2-9"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(scales)</span></span>
<span id="cb2-10"></span>
<span id="cb2-11"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">font_add_google("Roboto Condensed")</span></span>
<span id="cb2-12"></span>
<span id="cb2-13"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">chips |&gt;</span></span>
<span id="cb2-14"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  ggplot(aes(x = Date, y = transistors, color = Foundry)) +</span></span>
<span id="cb2-15"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  geom_point(alpha = 0.2) +</span></span>
<span id="cb2-16"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  geom_smooth(method = "lm", se = FALSE, alpha = 0.5) +</span></span>
<span id="cb2-17"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  scale_colour_viridis_d(option = "H", direction = -1) +</span></span>
<span id="cb2-18"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  scale_y_log10(labels = label_number()) +</span></span>
<span id="cb2-19"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  theme_ipsum_rc(axis_title_size = 12) +</span></span>
<span id="cb2-20"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  theme(legend.position = "bottom",</span></span>
<span id="cb2-21"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        panel.grid.major.x = element_blank(),</span></span>
<span id="cb2-22"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        panel.grid.minor.x = element_blank()) +</span></span>
<span id="cb2-23"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  labs(y = "Transistors (millions)",</span></span>
<span id="cb2-24"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">       title = "GPU Transistor Count by Release Date",</span></span>
<span id="cb2-25"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">       subtitle = "Data from https://chip-dataset.vercel.app/")</span></span>
<span id="cb2-26"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://boyd.tarlinton.au/posts/plot_design_files/figure-html/feature-image-1.png" class="img-fluid figure-img" width="672"></p>
<figcaption>The final figure</figcaption>
</figure>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>R</category>
  <guid>https://boyd.tarlinton.au/posts/plot_design.html</guid>
  <pubDate>Sat, 05 Apr 2025 14:00:00 GMT</pubDate>
</item>
<item>
  <title>Three Tips for Better Quarto Plots</title>
  <dc:creator>Boyd Tarlinton</dc:creator>
  <link>https://boyd.tarlinton.au/posts/quarto_plots.html</link>
  <description><![CDATA[ 




<p>If you regularly create <code>Quarto</code> documents, it s important to ensure that you can incorporate quality figures without spending a long time messing about. These are some of my favourite settings to ensure that my figures look great every time I render a <code>Quarto</code> document.</p>
<section id="use-showtext-through-knitr" class="level3">
<h3 class="anchored" data-anchor-id="use-showtext-through-knitr">Use <code>showtext</code> through <code>Knitr</code></h3>
<p><code>Showtext</code> offers better text rendering, as well as great control over settings such as DPI, which controls text size. Setting up <code>showtext</code> in your <code>Quarto</code> YAML metadata is much easier the calling <code>showtext_begin()</code> and <code>showtext_end()</code> every time you want to produce a plot!</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb1-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">knitr</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">opts_chunk</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span></span>
<span id="cb1-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fig-showtext</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb1-5"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span></code></pre></div>
</section>
<section id="use-google-fonts-with-sysfonts" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="use-google-fonts-with-sysfonts">Use Google Fonts with <code>sysfonts</code></h3>
<p>Simply calling <code>font_add_google()</code> with your chosen <a href="https://fonts.google.com/">Google Font</a> will make that font available in your R session and will look excellent in your <code>showtext</code>-enabled plots. Using Google Fonts has the added benefit of make your code much more portable.</p>
<p>Let’s load something a bit wacky:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb2-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb2-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(sysfonts)</span></span>
<span id="cb2-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">font_add_google("Bungee Tint", db_cache = FALSE)</span></span>
<span id="cb2-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
</div>

<div class="no-row-height column-margin column-container"><div class="">
<p>You may need to specify <code>db_cache = FALSE</code> for some fonts that have not been cached in your <code>sysfonts</code> install.</p>
</div></div></section>
<section id="set-dev-options-in-knitr-chunks" class="level3">
<h3 class="anchored" data-anchor-id="set-dev-options-in-knitr-chunks">Set dev options in <code>Knitr</code> chunks</h3>
<p>You can set dev arguments in your chunks, again avoiding the (in my opinion) rather clunky dev functions. I typically use this to set a transparent background, but that’s a pretty poor example on a white page. Let’s set a solid background and see how a plot looks with our custom settings!</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb3-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{r}</span></span>
<span id="cb3-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| dev.args: !expr list(bg="beige")</span></span>
<span id="cb3-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#| fig-cap: "An example figure"</span></span>
<span id="cb3-4"></span>
<span id="cb3-5"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">library(ggplot2)</span></span>
<span id="cb3-6"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">data("mtcars")</span></span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">mtcars |&gt;</span></span>
<span id="cb3-9"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  ggplot(aes(x = disp,</span></span>
<span id="cb3-10"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">             y = mpg)) +</span></span>
<span id="cb3-11"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  geom_point() +</span></span>
<span id="cb3-12"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">  theme(text = element_text(family = "Bungee Tint"),</span></span>
<span id="cb3-13"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        panel.background = element_blank(),</span></span>
<span id="cb3-14"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        plot.background = element_blank())</span></span>
<span id="cb3-15"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
<div class="cell-output-display">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://boyd.tarlinton.au/posts/quarto_plots_files/figure-html/unnamed-chunk-2-1.png" class="img-fluid figure-img" width="384"></p>
<figcaption>An example figure</figcaption>
</figure>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>R</category>
  <guid>https://boyd.tarlinton.au/posts/quarto_plots.html</guid>
  <pubDate>Fri, 28 Mar 2025 14:00:00 GMT</pubDate>
</item>
</channel>
</rss>
