Thoughts rearrange, familiar now strange.break flowersmore quotes

# green: color

Scientific graphical abstracts — design guidelines

# things on the side

visualization + design
If you are interested in color, explore my other color tools, Brewer palettes resources, color blindness palettes and math and an exhausting list of 10,000 color names for all those times you couldn't distinguish between tan hide, sea buckthorn, orange peel, west side, sunshade, california and pizzaz.

# Color choices and transformations for deuteranopia and other afflictions

Here, I help you understand color blindness and describe a process by which you can make good color choices when designing for accessibility. You can also delve into the mathematics behind the color blindness simulations.

Different color blindness simulations don't all agree on the luminance of the simulated color. See methods for details.

## color blindness R code

R code for converting an RGB color for color blindness. For details see the math tab and the resources section for background reading.

$--- title: 'RGB color correction for color blindess: protanopia, deuteranopia, tritanopia' author: 'Martin Krzywinski' web: http://mkweb.bcgsc.ca/colorblind ---${r}
gamma = 2.4

###############################################
# Linear RGB to XYZ
# https://en.wikipedia.org/wiki/SRGB
XYZ = matrix(c(0.4124564, 0.3575761, 0.1804375,
0.2126729, 0.7151522, 0.0721750,
0.0193339, 0.1191920, 0.9503041),
byrow=TRUE,nrow=3)

SA = matrix(c(0.2126,0.7152,0.0722,
0.2126,0.7152,0.0722,
0.2126,0.7152,0.0722),byrow=TRUE,nrow=3)

###############################################
# XYZ to LMS, normalized to D65
# https://en.wikipedia.org/wiki/LMS_color_space
# Hunt, Normalized to D65
LMSD65 = matrix(c( 0.4002, 0.7076, -0.0808,
-0.2263, 1.1653,  0.0457,
0     , 0     ,  0.9182),
byrow=TRUE,nrow=3)
# Hunt, equal-energy illuminants
LMSEQ = matrix(c( 0.38971, 0.68898,-0.07868,
-0.22981, 1.18340, 0.04641,
0      , 0      , 1      ),
byrow=TRUE,nrow=3)
# CIECAM97
SMSCAM97 = matrix(c(  0.8951,  0.2664, -0.1614,
-0.7502,  1.7135,  0.0367,
0.0389, -0.0685,  1.0296),
byrow=TRUE,nrow=3)
# CIECAM02
LMSCAM02 = matrix(c( 0.7328, 0.4296, -0.1624,
-0.7036, 1.6975,  0.0061,
0.0030, 0.0136,  0.9834),
byrow=TRUE,nrow=3)

###############################################
# Determine the color blindness correction in LMS space
# under the condition that the correction does not
# alter the appearance of white as well as
# blue (for protanopia/deuteranopia) or red (for tritanopia).
# For achromatopsia, greyscale conversion is applied
# to the linear RGB values.
getcorrection = function(LMS,type="p",g=gamma) {
red = matrix(c(255,0,0),nrow=3)
blue = matrix(c(0,0,255),nrow=3)
white = matrix(c(255,255,255),nrow=3)
LMSr = LMS %*% XYZ %*% apply(red,1:2,linearize,g)
LMSb = LMS %*% XYZ %*% apply(blue,1:2,linearize,g)
LMSw = LMS %*% XYZ %*% apply(white,1:2,linearize,g)
if(type == "p") {
x = matrix(c(LMSb[2,1],LMSb[3,1],
LMSw[2,1],LMSw[3,1]),byrow=T,nrow=2)
y = matrix(c(LMSb[1,1],LMSw[1,1]),nrow=2)
ab = solve(x) %*% y
C = matrix(c(0,ab[1,1],ab[2,1],0,1,0,0,0,1),byrow=T,nrow=3)
} else if (type == "d") {
x = matrix(c(LMSb[1,1],LMSb[3,1],
LMSw[1,1],LMSw[3,1]),byrow=T,nrow=2)
y = matrix(c(LMSb[2,1],LMSw[2,1]),nrow=2)
ab = solve(x) %*% y
C = matrix(c(1,0,0,ab[1,1],0,ab[2,1],0,0,1),byrow=T,nrow=3)
} else if (type == "t") {
x = matrix(c(LMSr[1,1],LMSr[2,1],
LMSw[1,1],LMSw[2,1]),byrow=T,nrow=2)
y = matrix(c(LMSr[3,1],LMSw[3,1]),nrow=2)
ab = solve(x) %*% y
C = matrix(c(1,0,0,0,1,0,ab[1,1],ab[2,1],0),byrow=T,nrow=3)
} else if (type == "a" | type == "g") {
C = matrix(c(0.2126,0.7152,0.0722,
0.2126,0.7152,0.0722,
0.2126,0.7152,0.0722),byrow=TRUE,nrow=3)
}
return(C)
}

# rgb is a column vector
convertcolor = function(rgb,LMS=LMSD65,type="d",g=gamma) {
C = getcorrection(LMS,type)
if(type == "a" | type == "g") {
T = SA
} else {
M = LMS %*% XYZ
Minv = solve(M)
T = Minv %*% C %*% M
}
print(T)
rgb_converted = T %*% apply(rgb,1:2,linearize,g)
return(apply(rgb_converted,1:2,delinearize,g))
}

# This function implements the method by Vienot, Brettel, Mollon 1999.
# The approach is the same, just the values are different.
# http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf
convertcolor2 = function(rgb,type="d",g=2.2) {
xyz = matrix(c(40.9568, 35.5041, 17.9167,
21.3389, 70.6743, 7.98680,
1.86297, 11.4620, 91.2367),byrow=T,nrow=3)
lms = matrix(c(0.15514, 0.54312, -0.03286,
-0.15514, 0.45684,0.03286,
0,0,0.01608),byrow=T,nrow=3)
rgb = (rgb/255)**g
if(type=="p") {
S = matrix(c(0,2.02344,-2.52581,0,1,0,0,0,1),byrow=T,nrow=3)
rgb = 0.992052*rgb+0.003974
} else if(type=="d") {
S = matrix(c(1,0,0,0.494207,0,1.24827,0,0,1),byrow=T,nrow=3)
rgb = 0.957237*rgb+0.0213814
} else {
stop("Only type p,d defined for this function.")
}
M = lms %*% xyz
T = solve(M) %*% S %*% M
print(T)
rgb = T %*% rgb
rgb = 255*rgb**(1/g)
return(rgb)
}

###############################################
# RGB to Lab
rgb2lab = function(rgb,g=gamma) {
rgb = apply(rgb,1:2,linearize,g)
xyz = XYZ %*% rgb
delta = 6/29
xyz = xyz / (c(95.0489,100,108.8840)/100)
f = function(t) {
if(t > delta**3) {
return(t**(1/3))
} else {
return (t/(3*delta**2) + 4/29)
}
}
L = 116*f(xyz[2]) - 16
a = 500*(f(xyz[1]) - f(xyz[2]))
b = 200*(f(xyz[2]) - f(xyz[3]))
return(matrix(c(L,a,b),nrow=3))
}

# CIE76 (https://en.wikipedia.org/wiki/Color_difference)
deltaE = function(rgb1,rgb2) {
lab1 = rgb2lab(rgb1)
lab2 = rgb2lab(rgb2)
return(sqrt(sum((lab1-lab2)**2)))
}

clip = function(v) {
return(max(min(v,1),0))
}

###############################################
# RGB to/from linear RGB
#https://en.wikipedia.org/wiki/SRGB
linearize = function(v,g=gamma) {
if(v <= 0.04045) {
return(v/255/12.92)
} else {
return(((v/255 + 0.055)/1.055)**g)
}
}

delinearize = function(v,g=gamma) {
if(v <= 0.003130805) {
return(255*12.92*clip(v))
} else {
return(255*clip(1.055*(clip(v)**(1/g))-0.055))
}
}
pretty = function(x) {
noquote(formatC(x,digits=10,format="f",width=9))
}

# a dark red
rgb1 = matrix(c(0,209,253),nrow=3)
# dark green
rgb2 = matrix(c(60,135,0),nrow=3)
# simulate deuteranopia
convertcolor(rgb1,type="d")
convertcolor(rgb2,type="d")
# get color distance before and after simulation
deltaE(rgb1,rgb2)
deltaE(convertcolor(rgb1,type="d"),convertcolor(rgb2,type="d"))
# transformation matrices for each color blindness type
M = LMSD65 %*% XYZ
pretty(solve(M) %*% getcorrection(LMSD65,"p") %*% M)
pretty(solve(M) %*% getcorrection(LMSD65,"d") %*% M)
pretty(solve(M) %*% getcorrection(LMSD65,"t") %*% M)
pretty(SA)
# method by Vienot, Brettel, Mollon, 1999
convertcolor2(rgb1,type="d",g=2.2)
convertcolor2(rgb2,type="d",g=2.2)
{r}

library(tidyverse)
library(colorscience)
printf <- function(...) invisible(print(sprintf(...)))

# let's get grey
#rgbg    = matrix(c(120,120,120),nrow=3)
#XYZgrey = XYZ %*% rgbg
#xyYgrey = XYZgrey/sum(XYZgrey)

# define an (x,y,Y) point
#x = xyYgrey[1,1]
#y = xyYgrey[2,1]
#Y = xyYgrey[3,1]
# convert to XYZ
#X = x/y*Y
#Y = Y
#Z = (1-x-y)*Y/y
# find combination of eigenvectors that solves this
#Q = solve(ev,c(X,Y,Z))
# now we can add any amount of ev3 to this and still have the same answer

palette = c(S="#333333",
p="#a0d848",
d="#f15a24",
t="#29abe2",
V="#8cc63f",
C="#ed1e79")
aspect = 1
p = ggplot()

# copunctal point
for(type in c("p","d")) {
M = solve(LMSD65) %*% getcorrection(LMSD65,type) %*% LMSD65
ev = eigen(M)\$vectors
xyp = (ev[,3]/sum(ev[,3]))[1:2]
#for(angle in seq(0,360,by=1)) {
for(b in seq(-0.1,1.1,by=0.05)) {
# pick any xy point
m = (xyp[2]-b)/xyp[1]
#m = tan(angle*pi/180)
#b = xyp[2] - m*xyp[1]
if(b < 0 | b > 1.2) {
#next
}
# the line of xy points between these two points is the confusion line
p = p + geom_abline(slope=m,intercept=b,color=palette[type])
}
}
#p = p + scale_x_continuous(lim=c(0,2.5))
#p = p + scale_y_continuous(lim=c(-1.5,1))
p = p + scale_x_continuous(lim=c(0,0.8))
p = p + scale_y_continuous(lim=c(0,0.8))
p
dev.copy2pdf(file = "fig1.pdf",useDingbats=FALSE,width=4,height=4)


$# a dark red rgb1 = matrix(c(225,0,30),nrow=3) # dark green rgb2 = matrix(c(60,135,0),nrow=3) # simulate deuteranopia convertcolor(rgb1,type="d") [,1] [1,] 136.7002 [2,] 136.7002 [3,] 0.0000 convertcolor(rgb2,type="d") [,1] [1,] 116.76071 [2,] 116.76071 [3,] 16.73263 # get color distance before and after simulation deltaE(rgb1,rgb2) [1] 116.9496 deltaE(convertcolor(rgb1,type="d"),convertcolor(rgb2,type="d")) [1] 12.72204 # transformation matrices for each color blindness type M = LMSD65 %*% XYZ pretty(solve(M) %*% getcorrection(LMSD65,"p") %*% M) [,1] [,2] [,3] [1,] 0.1705569911 0.8294430089 0.0000000000 [2,] 0.1705569911 0.8294430089 -0.0000000000 [3,] -0.0045171442 0.0045171442 1.0000000000 pretty(solve(M) %*% getcorrection(LMSD65,"d") %*% M) [,1] [,2] [,3] [1,] 0.3306600735 0.6693399265 -0.0000000000 [2,] 0.3306600735 0.6693399265 0.0000000000 [3,] -0.0278553826 0.0278553826 1.0000000000 pretty(solve(M) %*% getcorrection(LMSD65,"t") %*% M) [,1] [,2] [,3] [1,] 1.0000000000 0.1273988634 -0.1273988634 [2,] -0.0000000000 0.8739092990 0.1260907010 [3,] 0.0000000000 0.8739092990 0.1260907010 pretty(SA) [,1] [,2] [,3] [1,] 0.2126000000 0.7152000000 0.0722000000 [2,] 0.2126000000 0.7152000000 0.0722000000 [3,] 0.2126000000 0.7152000000 0.0722000000 # method by Vienot, Brettel, Mollon, 1999 convertcolor2(rgb1,type="d",g=2.2) [,1] [,2] [,3] [1,] 0.29275003 0.70724967 -2.978356e-08 [2,] 0.29275015 0.70724997 1.232823e-08 [3,] -0.02233659 0.02233658 1.000000e+00 [,1] [1,] 131.81223 [2,] 131.81226 [3,] 36.37274 convertcolor2(rgb2,type="d",g=2.2) [,1] [,2] [,3] [1,] 0.29275003 0.70724967 -2.978356e-08 [2,] 0.29275015 0.70724997 1.232823e-08 [3,] -0.02233659 0.02233658 1.000000e+00 [,1] [1,] 122.71798 [2,] 122.71801 [3,] 48.34316$

# Graphical Abstract Design Guidelines

Fri 13-11-2020

Clear, concise, legible and compelling.

Making a scientific graphical abstract? Refer to my practical design guidelines and redesign examples to improve organization, design and clarity of your graphical abstracts.

Graphical Abstract Design Guidelines — Clear, concise, legible and compelling.

# "This data might give you a migrane"

Tue 06-10-2020

An in-depth look at my process of reacting to a bad figure — how I design a poster and tell data stories.

A poster of high BMI and obesity prevalence for 185 countries.

# He said, he said — a word analysis of the 2020 Presidential Debates

Thu 01-10-2020

Building on the method I used to analyze the 2008, 2012 and 2016 U.S. Presidential and Vice Presidential debates, I explore word usagein the 2020 Debates between Donald Trump and Joe Biden.

Analysis of word usage by parts of speech for Trump and Biden reveals insight into each candidate.

# Points of Significance celebrates 50th column

Mon 24-08-2020

We are celebrating the publication of our 50th column!

To all our coauthors — thank you and see you in the next column!

Nature Methods Points of Significance: Celebrating 50 columns of clear explanations of statistics. (read)

# Uncertainty and the management of epidemics

Mon 24-08-2020

When modelling epidemics, some uncertainties matter more than others.

Public health policy is always hampered by uncertainty. During a novel outbreak, nearly everything will be uncertain: the mode of transmission, the duration and population variability of latency, infection and protective immunity and, critically, whether the outbreak will fade out or turn into a major epidemic.

The uncertainty may be structural (which model?), parametric (what is $R_0$?), and/or operational (how well do masks work?).

This month, we continue our exploration of epidemiological models and look at how uncertainty affects forecasts of disease dynamics and optimization of intervention strategies.

Nature Methods Points of Significance column: Uncertainty and the management of epidemics. (read)

We show how the impact of the uncertainty on any choice in strategy can be expressed using the Expected Value of Perfect Information (EVPI), which is the potential improvement in outcomes that could be obtained if the uncertainty is resolved before making a decision on the intervention strategy. In other words, by how much could we potentially increase effectiveness of our choice (e.g. lowering total disease burden) if we knew which model best reflects reality?

This column has an interactive supplemental component (download code) that allows you to explore the impact of uncertainty in $R_0$ and immunity duration on timing and size of epidemic waves and the total burden of the outbreak and calculate EVPI for various outbreak models and scenarios.

Nature Methods Points of Significance column: Uncertainty and the management of epidemics. (Interactive supplemental materials)

Bjørnstad, O.N., Shea, K., Krzywinski, M. & Altman, N. (2020) Points of significance: Uncertainty and the management of epidemics. Nature Methods 17.