Taylor Diagram Tutorial

This turorial is for creating a Taylor Diagram using CDAT's VCS.

Taylor diagrams are mathematical diagrams designed to graphically indicate which of several approximate representations (or models) of a system, process, or phenomenon is most realistic. This diagram, invented by Karl E. Taylor in 1994 (published in 2001) facilitates the comparative assessment of different models. It is used to quantify the degree of correspondence between the modeled and observed behavior in terms of three statistics: the Pearson correlation coefficient, the root-mean-square error (RMSE), and the standard deviation. Taylor diagrams have been used widely to evaluate models designed to study climate and other aspects of Earth’s environment. [See Wiki and Taylor (2001) for details.]

Reference: Taylor, K. E. 2001: Summarizing multiple aspects of model performance in a single diagram. Journal of Geophysical Research, 106(D7): 7183-7192

The CDAT software was developed by LLNL. This tutorial was written by Charles Doutriaux and Jiwoo Lee (18 Sep. 2017). This work was performed under the auspices of the U.S. Department of Energy by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344.

Environment versions used in this tutorial:

  • cdat 2.12
  • vcs 2.12
  • mesalib 17.2.0

Download the Jupyter Notebook

Create VCS canvas

Back to Top

In [1]:
from __future__ import print_function

import vcs
x = vcs.init()

Prepare input data

(Back to Top)

Standard deviation and correlation values are required. The following creates hypothetical input named "data" for testing.

In [2]:
# Create 7 dummy data points representing 6 different models and 1 reference (observational) data point.
import MV2
corr = [.2, .5, .7, .85, .9, .95, .99]
std = [1.6, 1.7, 1.5, 1.2 , .8, .9, .98]

data_tmp1 = list(zip(std, corr))
data_tmp2 = list(data_tmp1)
In [3]:
data = MV2.array(data_tmp2)
data.id = "My Taylor Diagram Data"

print('data:\n', data)
print('data shape:', data.shape)
data:
 [[1.6  0.2 ]
 [1.7  0.5 ]
 [1.5  0.7 ]
 [1.2  0.85]
 [0.8  0.9 ]
 [0.9  0.95]
 [0.98 0.99]]
data shape: (7, 2)

Plot the initial version using VCS module. "vcs.createtaylordiagram" is for creating the template.

In [4]:
taylor = vcs.createtaylordiagram()
x.plot(data,taylor)
Out[4]:

Reference Line

(Back to Top)

The curved line in the plot indicates a reference line. Let's say your reference data (i.e. your observations) has a standard deviation of 1.2. You may want to move the line to cross 1.2, as below.

In [5]:
# Reference point
taylor.referencevalue=1.2
x.clear()
x.plot(data,taylor)
Out[5]:

Markers

(Back to Top)

You may want to distinguish the data points from each other and label them. You can adjust the marker as a shape and/or string, and create a legend.

In [6]:
# Markers attributes
ids = ["A1","A2","A3","B1","C1","C2","C3"]
id_sizes = [2., 1.5, 1.5, 1.5, 1.5, 1.5, 1.5,]
id_colors = ["red","orange","green","cyan","blue","purple","black"]
symbols = ["square","dot","circle","triangle_right","triangle_left","triangle_up","triangle_down"]
colors = ["red","orange","green","cyan","blue","purple","black"]
sizes = [2., .5, 2., 2., 2., 2., 2.,]

For text strings:

  • ids: Data id. It could be model or dataset names
  • id_sizes: Sizes of text strings
  • id_colors: Colors of text strings

For symbols:

  • symbols: Shapes of markers
  • colors: Colors of markers
  • sizes: Sizes of markers

"id_colors" and "colors" do not need to be identical.

In [7]:
taylor = vcs.createtaylordiagram()
for i in range(len(data)):
    taylor.addMarker(id=ids[i],
                     id_size=id_sizes[i],
                     id_color=id_colors[i],
                     symbol=symbols[i],
                     color=colors[i],
                     size=sizes[i])
x.clear()
x.plot(data,taylor)
Out[7]:

Adjust the position of text strings to avoid overlapping the symbol by using "xoffset" and "yoffset", which gives the relative position from each of the (x, y) points.

In [8]:
taylor = vcs.createtaylordiagram()
for i in range(len(data)):
    taylor.addMarker(id=ids[i],
                     id_size=id_sizes[i],
                     id_color=id_colors[i],
                     symbol=symbols[i],
                     color=colors[i],
                     size=sizes[i],
                     xoffset=-2.5,
                     yoffset=2.5)
x.clear()
x.plot(data,taylor)
Out[8]:

Alternative way of setting makers

(Back to Top)

Instead of using a "for" loop and the "taylor.addMarker" function, you can store those pre-defined values in the Taylor diagram template directly.

In [9]:
# Other way to set marker attributes
taylor = vcs.createtaylordiagram()
taylor.Marker.id = ids
taylor.Marker.id_size = id_sizes
taylor.Marker.id_color = id_colors
taylor.Marker.symbol = symbols
taylor.Marker.color = colors
taylor.Marker.size = sizes
taylor.Marker.xoffset = [-2.5,]*len(data)
taylor.Marker.yoffset = [2.5]*len(data)
x.clear()
x.plot(data,taylor)
Out[9]:

Create a connecting line between dots

(Back to Top)

If needed, you can draw connecting lines between individual data points. In the example below, the line connects all the data dots in the order they occur in the data.

In [10]:
taylor.Marker.line = ["tail","line","line","line","line","line","head"]
taylor.Marker.line_type = ["solid",]*len(data)
taylor.Marker.line_color = ["dark grey",]*len(data)
taylor.Marker.line_size = [5.,5.,5.,5.,5.,5.,5.]
x.clear()
x.plot(data,taylor)
Out[10]:

Grouping by splitting lines

(Back to Top)

Let's assume that you want to group your data. You can split a line in two by giving "None" for one of data points.

In [11]:
# Let's split the line into 2 sets of lines with an empty marker in between.
# The first line is dashed.
taylor.Marker.line =  ['tail', 'line', 'head', None, 'tail', 'line', 'head']
taylor.Marker.line_type = ["dash","dash","dash","solid","solid","solid","solid"]
x.clear()
x.plot(data,taylor)
Out[11]:

Legend

(Back to Top)

Instead of the legend at the bottom (the default position), you can move it where you want.

  • x1, x2, y1, y2 mark the four corners of the legend box and their values are a decimal fraction of the full page width (x) and length/height (y) which is 1.
In [12]:
# Legend positioning for quadrant 1
x.clear()
template = vcs.createtemplate(source="deftaylor")
template.legend.x1 = .5
template.legend.x2 = .6
template.legend.y1 = .2
template.legend.y2 = .65
template.legend.line = "black"
x.plot(data,taylor,template)
Out[12]:

Additional Axes

(Back to Top)

In [13]:
#Skill scores
x.clear()
x.plot(data,taylor,skill=taylor.defaultSkillFunction)
Out[13]:
In [14]:
import numpy
def mySkill(s,r):
    return (4*numpy.ma.power(1+r,4))/(numpy.power(s+1./s,2)*numpy.power(1+r*2.,4))
x.clear()
x.plot(data,taylor,skill=mySkill)
Out[14]:

Two quadrants Taylor Diagram

(Back to Top)

In [15]:
# Negative correlation: Two quadrants
taylor.quadrans = 2 # default: 1

# Tweak input data to have negative number
data2 = data.copy()
data2[0,1] = -data2[0,1]

# Plot
x.clear()
x.plot(data2,taylor)
Out[15]:

Controllable components

(Back to Top)

"taylor.list()" allows you to check all the components that you can control.

In [16]:
taylor = vcs.createtaylordiagram()
taylor.list()
---------- Taylordiagram (Gtd) member (attribute) listings ----------
graphic method = Gtd
name = __taylordiagram_695619144847565
detail = 75
max = None
quadrans = 1
skillValues = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95]
skillColor = (74.50980392156863, 74.50980392156863, 74.50980392156863, 100.0)
skillDrawLabels = y
skillCoefficient = [1.0, 1.0, 1.0]
idsLocation = 0
referencevalue = 1.0
arrowlength = 0.05
arrowangle = 20.0
arrowbase = 0.75
xticlabels1 = *
xmtics1 = *
yticlabels1 = *
ymtics1 = *
cticlabels1 = *
cmtics1 = *
Marker
    status =  []
    line =  []
    id =  []
    id_size =  []
    id_color =  []
    id_font =  []
    id_location =  []
    symbol =  []
    color =  []
    size =  []
    xoffset =  []
    yoffset =  []
    line_color =  []
    line_size =  []
    line_type =  []

test