<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/remaking-luminance-gradient-dependent-lightness-illusion-with-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://rtask.thinkr.fr/blog/luminance-gradient-dependent-lightness-illusion/"> (en) The R Task Force</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><strong>A blogpost inspired by a tweet and a YouTube video.</strong><span></span></p>
<h2>‘Luminance-gradient-dependent lightness illusion’</h2>
<p>In the last days, I’ve stumbled upon this tweet:</p>
<blockquote class="twitter-tweet" data-lang="en">
<p dir="ltr" lang="en">A demo of lightness perception <a rel="nofollow" href="https://t.co/BSVpgcuIw1" target="_blank">pic.twitter.com/BSVpgcuIw1</a></p>
<p>— Akiyoshi Kitaoka (@AkiyoshiKitaoka) <a rel="nofollow" href="https://twitter.com/AkiyoshiKitaoka/status/1028473566193315841?ref_src=twsrc%5Etfw" target="_blank">August 12, 2018</a></p>
</blockquote>
<p></p>
<p>Which is a demonstration of <strong>how our perception of color is affected by the lightness surrounding this color</strong>.</p>
<p>Also recently, I’ve been watching the <a rel="nofollow" href="https://user2018.r-project.org/" target="_blank">useR 2018</a> YouTube recordings, which contains a video called <a rel="nofollow" href="https://www.youtube.com/watch?v=21ZWDrTukEs" target="_blank">The Grammar of Animation</a>, presenting <code>{gganimate}</code> a package by Thomas Lin Pedersen extending the <code>{ggplot2}</code> grammar of graphics to include animation.</p>
<p>If you want to know more about <code>{gganimate}</code>, feel free to browse the <a rel="nofollow" href="https://github.com/thomasp85/gganimate" target="_blank">GitHub repo</a>, and watch the YouTube video.</p>
<div align="center"><iframe width="450" allowfullscreen="allowfullscreen" src="https://www.youtube.com/embed/21ZWDrTukEs"></iframe></div>
<p> </p>
<p>Back to our lightness perception: as you can see, the illusion is made by hand, with a piece of paper, moving the square manually. Let’s recreate this with <code>gganimate</code>.</p>
<h2>The R Code</h2>
<h3>Creating the data.frame</h3>
<p>So, we’ll need three things:</p>
<ul>
<li>A <strong>variable stating all the transition states</strong></li>
<li>A<strong> variable for <code>y</code> min and max, which will stay the same</strong></li>
<li>A <strong>variable for <code>x</code> min and max, which will be incremented by one on each transition states.</strong></li>
</ul>
<pre><code>d &lt;- data.frame(
  # x coordinates
  x1 = 1:10, x2 = 2:11, 
  # y 
  y1 = 4, y2 = 5,
  # transition time
  t = 1:10
  )</code></pre>
<h3>Getting the background</h3>
<p>The background is basically a <strong>gradient</strong> from <code>#000000</code> to <code>#FFFFFF</code> (read <a rel="nofollow" href="https://rtask.thinkr.fr/blog/ggplot2-welcome-viridis/" target="_blank">this post</a> for more about hex color notation). Let’s create that object:</p>
<pre><code>library(grid)
g &lt;- rasterGrob(
  # Creating the color gradient
  t(colorRampPalette(c(&quot;#000000&quot;, &quot;#FFFFFF&quot;))(1000)), 
  # Scaling it to fit the graph
  width= unit(1,&quot;npc&quot;), height = unit(1,&quot;npc&quot;)
  )</code></pre>
<h3>Creating the ggplot</h3>
<p>I’ll first create the <code>ggplot</code> object, which is composed of 10 squares, filled with <strong>the same grey</strong>: <code>&quot;#7E7E7E&quot;</code>. I use the <code>theme_nothing()</code> from <code>{ggmap}</code> as an empty theme.</p>
<pre><code>library(ggplot2)
gg &lt;- ggplot() + 
  annotation_custom(g , -Inf, Inf, -Inf, Inf) +
  geom_rect(data=d, 
            mapping=
              aes(xmin=x1, 
                  xmax=x2, 
                  ymin=y1, 
                  ymax=y2), 
            color=&quot;black&quot;, fill = &quot;#7E7E7E&quot;) + 
  ylim(c(1,8)) + 
  ggmap::theme_nothing() 

gg</code></pre>
<h3><img sizes="(max-width: 1000px) 100vw, 1000px" src="https://i1.wp.com/rtask.thinkr.fr/wp-content/uploads/greypalette.png?w=450&ssl=1" alt="" class="wp-image-623" data-recalc-dims="1"></h3>
<h3>Animation is illusion</h3>
<p>Let’s now <strong>animate our plot to create the illusion</strong>. As I want the move to be linear, I’ll use a combination of <code>transition_time</code> and <code>ease_aes('linear')</code> to make the transition smooth.</p>
<pre><code>library(gganimate)
gg_animated &lt;- gg + 
  transition_time(t) + 
  ease_aes('linear')</code></pre>
<p>And tadaa !</p>
<pre><code>gg_animated</code></pre>
<p><img alt="" src="https://i1.wp.com/rtask.thinkr.fr/wp-content/uploads/lightness_illustion.gif?w=450&ssl=1" class="wp-image-622" data-recalc-dims="1"></p>
<p>On this animation, <strong>the square appears to be changing color. But it’s not</strong>: the <code>fill</code> is always <code>&quot;#7E7E7E&quot;</code>.</p>
<h2>What’s behind</h2>
<h3>Luminance and perception of color</h3>
<blockquote>
<p>“Every light is a shade, compared to the higher lights, till you come to the sun; and every shade is a light, compared to the deeper shades, till you come to the night.” —John Ruskin, 1879.</p>
</blockquote>
<p>OK, let’s forget R to focus on what is happening here, and quickly talk about perception of luminance (the level of light coming to your eye) and color.</p>
<p>We are here <strong>facing a phenomenon known as a “gradient illusion”</strong>. The important idea behind this is that <strong>every color we perceive is influenced by its surrounding</strong>: in other words, we perceive the color lighter on the left of our image, as it is contrasted with black. The more the square move toward the white, the more the grey appears dark.</p>
<p>How does it work? When a color comes to your eye, you perceive a certain amount of luminance. In other words, you are able to tell if something is dark or light or somewhere in the middle. Our ability to do so is called “lightness consistency”, but these gradient illusions show us one thing: this ability is not perfect, and the “luminance environment” in which the color appears influence how we see it.</p>
<h3>A phenomenon to know</h3>
<p>So, as we’ve just seen, <strong>perception of color is influenced by its surrounding</strong>. When it comes to creating a dataviz, color scales are crucial – even more now that we know that. Let’s imagine that for some weird reason we have created this plot:</p>
<pre><code>
ggplot() + 
  annotation_custom(g , -Inf, Inf, -Inf, Inf) + 
  geom_col(aes(x = 1, y = 3), fill = &quot;#7E7E7E&quot;) + 
  geom_col(aes(x = 8, y = 4), fill = &quot;#7E7E7E&quot;)
</code></pre>
<p><img sizes="(max-width: 664px) 100vw, 664px" src="https://i2.wp.com/rtask.thinkr.fr/wp-content/uploads/grey_scale_2.png?w=450&ssl=1" alt="" class="wp-image-624" data-recalc-dims="1"></p>
<p>Again,<strong> the fill is the same</strong>, but one bar seems to be darker than the other, which can <strong>trick the reader into thinking the value in the two is not the same</strong>. Something to consider if there is a chance your plot will be turned to black and white.</p>
<p>Let’s say we are drawing a map. Maps are composed of regions, and can be colored following a specific scale. But <strong>there’s a probability that two regions with the very same result on that scale would be surrounded by two opposite colors</strong>. For example, two <code>#7E7E7E</code> could be surrounded one by <code>#515151</code>, the other by <code>#aeaeae</code>.</p>
<pre><code>
ggplot() + 
  geom_rect(aes(xmin = 1, xmax = 4, ymin = 1, ymax = 4), fill = &quot;#515151&quot;) + 
  geom_rect(aes(xmin = 2, xmax = 3, ymin = 2, ymax = 3), fill = &quot;#7E7E7E&quot;) + 
  geom_rect(aes(xmin = 4, xmax = 7, ymin = 1, ymax = 4), fill = &quot;#aeaeae&quot;) + 
  geom_rect(aes(xmin = 5, xmax = 6, ymin = 2, ymax = 3), fill = &quot;#7E7E7E&quot;) 
</code></pre>
<p><img sizes="(max-width: 664px) 100vw, 664px" src="https://i2.wp.com/rtask.thinkr.fr/wp-content/uploads/grey_scame_3.png?w=450&ssl=1" alt="" class="wp-image-631" data-recalc-dims="1"></p>
<blockquote>
<p>
From <a rel="nofollow" href="http://persci.mit.edu/pub_pdfs/gazzan.pdf" target="_blank">Lightness Perception and Lightness Illusions </a>
</p>
</blockquote>
<p>What to do now?</p>
<ul>
<li>Now that you know this phenomenom, <strong>pay attention to it</strong> when you create plots</li>
<li>Be<strong> careful when chosing palettes</strong></li>
<li>Try to <strong>turn your graph to black and white</strong> with <code>colorspace::desaturate</code></li>
</ul>
<pre><code>with_palette &lt;- function(palette) {
  x &lt;- y &lt;- seq(-8 * pi, 8 * pi, len = 40)
  r &lt;- sqrt(outer(x^2, y^2, &quot;+&quot;))
  filled.contour(cos(r^2) * exp(-r / (2 * pi)),
    axes = FALSE,
    color.palette = palette,
    asp = 1
  )
}
with_palette(
    purrr:::compose(
      colorspace::desaturate,
      viridis::viridis
    )
)

</code></pre>
<p><img sizes="(max-width: 672px) 100vw, 672px" src="https://i1.wp.com/rtask.thinkr.fr/wp-content/uploads/unnamed-chunk-13-1.png?w=450&ssl=1" alt="" class="wp-image-540" data-recalc-dims="1"></p>
<blockquote>
<p>
From <a rel="nofollow" href="https://rtask.thinkr.fr/blog/ggplot2-welcome-viridis/" target="_blank">ggplot2 – Welcome viridis !</a>
</p>
</blockquote>
<h2>Further reading :</h2>
<ul>
<li>“Lightness Perception and Lightness Illusions”, Edward H. Adelson, 2000 <a rel="nofollow" href="http://persci.mit.edu/pub_pdfs/gazzan.pdf" target="_blank">link</a></li>
<li>“Lightness models, gradient illusions, and curl”, Lawrence E. Arend and Robert Goldstein, 1987 <a rel="nofollow" href="https://link.springer.com/content/pdf/10.3758/BF03211515.pdf" target="_blank">link</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://rtask.thinkr.fr/blog/luminance-gradient-dependent-lightness-illusion/" target="_blank">Remaking ‘Luminance-gradient-dependent lightness illusion’ with R</a> appeared first on <a rel="nofollow" href="https://rtask.thinkr.fr/" target="_blank">(en) The R Task Force</a>.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://rtask.thinkr.fr/blog/luminance-gradient-dependent-lightness-illusion/"> (en) The R Task Force</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/TVlk2O_v_jk" height="1"></a></div>