# VCS Templates ¶

This turorial describes how to use CDAT's VCS's templates.

The CDAT software was developed by LLNL. This tutorial was written by Charles Doutriaux (18 Jan. 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.

In the VCS model, the data display is defined by a trio of named object sets, designated the “primary objects” (or “primary elements”). These include:

• Data Ingestion: The data, which drives the visualization, is ingested into the system via cdms2 or other numeric modules such as numpy.
• Graphics Method: The graphics method, which specifies the display technique.
• Template: The picture template, which determines the appearance of each segment of the display. Tables for manipulating these primary objects are stored in VCS for later recall and possible use.

This tutorial explains how to control the template and its relation to VCS's other primary objects.

## Template elements¶

### Generalities¶

The template object allows the user to control where various elements of the plots are being drawn.

The following picture shows the various elements of a VCS image and the associated VCS template's atrribute:

To create a text object simply use the createtemplate function.

In [1]:
from __future__ import print_function  # For Python 2 compatibility
import vcs
x = vcs.init(bg=True)
template = vcs.createtemplate()
# the name is some bad random name:
print("template name:", template.name)
# If you want you can name your template object for easier retrieval later
# but keep in mind the name must be unique
try:
template = vcs.createtemplate("vcs_is_easy")
except Exception:
print("Ooops already have a template named like this")

print("Nice named template:", template.name)
# fails on second try
try:
template = vcs.createtemplate("vcs_is_easy")
print("It worked")
except Exception:
print("Second try: Ooops already have a template named like this")


template name: __template_341325303621890
Nice named template: vcs_is_easy
Second try: Ooops already have a template named like this


You can also list all of your existing templates and use one of them as a starting point.

In [2]:
mytemplates = vcs.listelements("template")
print("Existing templates:", mytemplates)  # notice the randomly named ones
template = vcs.createtemplate(source="vcs_is_easy")

Existing templates: ['ASD', 'ASD_dud', 'BL_of6_1legend', 'BLof6', 'BR_of6_1legend', 'BRof6', 'LLof4', 'LLof4_dud', 'LRof4', 'LRof4_dud', 'ML_of6', 'ML_of6_1legend', 'MR_of6', 'MR_of6_1legend', 'UL_of6_1legend', 'ULof4', 'ULof4_dud', 'ULof6', 'UR_of6', 'UR_of6_1legend', 'URof4', 'URof4_dud', '__template_341325303621890', 'bold_mid_of3', 'bold_top_of3', 'boldbot_of3_l', 'boldmid_of3_l', 'boldtop_of3_l', 'bot_of2', 'default', 'deftaylor', 'hovmuller', 'mollweide2', 'no_legend', 'polar', 'por_botof3', 'por_botof3_dud', 'por_midof3', 'por_midof3_dud', 'por_topof3', 'por_topof3_dud', 'quick', 'top_of2', 'vcs_is_easy']


Now in order to use this template either pass the template object to the vcs plot function.

In [3]:
# Get some data to plot
import cdms2
import os
with cdms2.open(os.path.join(vcs.sample_data,"ta_ncep_87-6-88-4.nc")) as f:
data = f("ta")
# we need
x.plot(data, template)

MD5: /home/nadeau1/.cache/Python-Eggs/vcs-v8.1_9_g266121be-py3.7.egg-tmp/share/vcs/sample_files.txt

Out[3]:

Now let's learn how to customize template objects.

To see the list of available attributes on a template (and their own attributes/values) use the list() function.

In [4]:
template.list()

---------- Template (P) member (attribute) listings ----------
method = P
name = __template_77340719414112
orientation = 0
member =  file
priority = 1
x = 0.0500000007451
y = 0.0130000002682
texttable = default
textorientation = default
member =  function
priority = 1
x = 0.0500000007451
y = 0.0130000002682
texttable = default
textorientation = default
priority = 1
x = 0.0500000007451
y = 0.0329999998212
texttable = default
textorientation = default
member =  transformation
priority = 1
x = 0.0500000007451
y = 0.0529999993742
texttable = default
textorientation = default
member =  source
priority = 1
x = 0.0500000007451
y = 0.941999971867
texttable = default
textorientation = default
member =  dataname
priority = 1
x = 0.0500000007451
y = 0.922999978065
texttable = default
textorientation = default
member =  title
priority = 1
x = 0.15000000596
y = 0.922999978065
texttable = default
textorientation = default
member =  units
priority = 1
x = 0.670000016689
y = 0.922999978065
texttable = default
textorientation = default
member =  crdate
priority = 1
x = 0.75
y = 0.922999978065
texttable = default
textorientation = default
member =  crtime
priority = 1
x = 0.850000023842
y = 0.922999978065
texttable = default
textorientation = default
member =  comment1
priority = 1
x = 0.10000000149
y = 0.954999983311
texttable = default
textorientation = default
member =  comment2
priority = 1
x = 0.10000000149
y = 0.975000023842
texttable = default
textorientation = default
member =  comment3
priority = 1
x = 0.10000000149
y = 0.995000004768
texttable = default
textorientation = default
member =  comment4
priority = 1
x = 0.10000000149
y = 0.999000012875
texttable = default
textorientation = default
member =  xname
priority = 1
x = 0.5
y = 0.21
texttable = default
textorientation = defcenter
member =  yname
priority = 1
x = 0.006
y = 0.56
texttable = default
textorientation = defup
member =  zname
priority = 0
x = 0.0
y = 0.995000004768
texttable = default
textorientation = default
member =  tname
priority = 0
x = 0.0
y = 0.995000004768
texttable = default
textorientation = default
member =  xunits
priority = 0
x = 0.600000023842
y = 0.21
texttable = default
textorientation = default
member =  yunits
priority = 0
x = 0.006
y = 0.658999979496
texttable = default
textorientation = defup
member =  zunits
priority = 0
x = 0.0
y = 0.995000004768
texttable = default
textorientation = default
member =  tunits
priority = 0
x = 0.0
y = 0.995000004768
texttable = default
textorientation = default
member =  xvalue
priority = 0
x = 0.800000011921
y = 0.941999971867
format = default
texttable = default
textorientation = default
member =  yvalue
priority = 0
x = 0.800000011921
y = 0.922999978065
format = default
texttable = default
textorientation = default
member =  zvalue
priority = 1
x = 0.800000011921
y = 0.902999997139
format = default
texttable = default
textorientation = default
member =  tvalue
priority = 0
x = 0.800000011921
y = 0.883000016212
format = default
texttable = default
textorientation = default
member =  mean
priority = 1
x = 0.0500000007451
y = 0.899999976158
format = default
texttable = default
textorientation = default
member =  min
priority = 1
x = 0.449999988079
y = 0.899999976158
format = default
texttable = default
textorientation = default
member =  max
priority = 1
x = 0.25
y = 0.899999976158
format = default
texttable = default
textorientation = default
member =  xtic1
priority = 1
y1 = 0.259999990463
y2 = 0.24699999392
line = default
member =  xtic2
priority = 1
y1 = 0.860000014305
y2 = 0.871999979019
line = default
member =  xmintic1
priority = 0
y1 = 0.259999990463
y2 = 0.248999999285
line = default
member =  xmintic2
priority = 0
y1 = 0.860000014305
y2 = 0.868000014305
line = default
member =  ytic1
priority = 1
x1 = 0.0500000007451
x2 = 0.0399999991059
line = default
member =  ytic2
priority = 1
x1 = 0.949999988079
x2 = 0.959999978542
line = default
member =  ymintic1
priority = 0
x1 = 0.0500000007451
x2 = 0.0450000017881
line = default
member =  ymintic2
priority = 0
x1 = 0.949999988079
x2 = 0.954999983311
line = default
member =  xlabel1
priority = 1
y = 0.234999999404
texttable = default
textorientation = defcenter
member =  xlabel2
priority = 0
y = 0.880000004768
texttable = default
textorientation = defcenter
member =  ylabel1
priority = 1
x = 0.0399999991059
texttable = default
textorientation = defright
member =  ylabel2
priority = 0
x = 0.959999978542
texttable = default
textorientation = default
member =  box1
priority = 1
x1 = 0.0500000007451
y1 = 0.259999990463
x2 = 0.949999988079
y2 = 0.860000014305
line = default
member =  box2
priority = 0
x1 = 0.0
y1 = 0.300000011921
x2 = 0.920000016689
y2 = 0.879999995232
line = default
member =  box3
priority = 0
x1 = 0.0
y1 = 0.319999992847
x2 = 0.910000026226
y2 = 0.860000014305
line = default
member =  box4
priority = 0
x1 = 0.0
y1 = 0.0
x2 = 0.0
y2 = 0.0
line = default
member =  line1
priority = 0
x1 = 0.0500000007451
y1 = 0.560000002384
x2 = 0.949999988079
y2 = 0.560000002384
line = default
member =  line2
priority = 0
x1 = 0.5
y1 = 0.259999990463
x2 = 0.5
y2 = 0.860000014305
line = default
member =  line3
priority = 0
x1 = 0.0
y1 = 0.52999997139
x2 = 0.899999976158
y2 = 0.52999997139
line = default
member =  line4
priority = 0
x1 = 0.0
y1 = 0.990000009537
x2 = 0.899999976158
y2 = 0.990000009537
line = default
member =  legend
priority = 1
x1 = 0.0500000007451
y1 = 0.129999995232
x2 = 0.949999988079
y2 = 0.159999996424
line = default
texttable = default
textorientation = defcenter
offset = 0.01
member =  data
priority = 1
x1 = 0.0500000007451
y1 = 0.259999990463
x2 = 0.949999988079
y2 = 0.860000014305


### Data attribute¶

One of the most important attributes is the data attribute. It controls where the data will be drawn.

Note that changing the data attribute alone is not sufficient; other attributes will need to be moved as well. See the latter part of this tutorial for utility functions to help you manipulate everything at once.

Let's try to move the data to the upper left part of the canvas.

All units are in percentage (%) of the canvas; the 0 representing the lower/left corner of the canvas and 1 the upper/right corner).

The data attribute has 5 sub-attributes:

• priority: the priority represents the layer on which the attribute will be drawn. A higher number means the attribute will be drawn on top of attributes with lower numbers.
• x1: The lower left corner horizontal location (in %).
• x2: The upper right corner horizontal location (in %).
• y1: The lower left corner vertical location (in %).
• y2: The upper right corner vertical location (in %).
In [5]:
template.data.x1 = .1 # 10% from left
template.data.x2 = .45  # 45% from left
template.data.y1 = .45  # 45% from bottom
template.data.y2 = .85  # 15% from top (or 85% from bottom)

x.clear()
x.plot(data,template)

Out[5]:

As mentioned, other attributes need to be moved as well. First let's move the box around the data area. It is controlled via box1 which has the following attributes:

In [6]:
template.box1.list()

member =  box1
priority = 1
x1 = 0.0500000007451
y1 = 0.259999990463
x2 = 0.949999988079
y2 = 0.860000014305
line = default


The new attribute here is the line attribute. You can use any line object from vcs (or create one).

In [7]:
print(vcs.listelements("line"))
template.box1.line = "red"
# let's copy
template.box1.x1 = template.data.x1
template.box1.x2 = template.data.x2
template.box1.y1 = template.data.y1
template.box1.y2 = template.data.y2

x.clear()
x.plot(data,template)

['black', 'blue', 'brown', 'continents', 'cyan', 'default', 'deftaylordot', 'green', 'ltblue', 'navy', 'pink', 'purple', 'red', 'solid', 'std', 'thick', 'white']

Out[7]:

### Tick Marks¶

Now let's move the tick marks. There are two types of tick marks: "major" and "min". The main difference is that "major" tick marks have text associated with them.

There are tick marks for the x axis and for the y axis. Each axis has two sets of tick marks. By default 1 is for the left/bottom tick marks while 2 is for the right/top ones.

With this in mind, the tickmark attributes are:

xtic1, xtic2, xmintic1, xmintic2, ytic1, ytic2, ymintic1, ymintic2,

#### Major Ticks¶

For example, for xtic1 the attributes are:

In [8]:
template.xtic1.list()

member =  xtic1
priority = 1
y1 = 0.259999990463
y2 = 0.24699999392
line = default

• priority: the priority represents the layer on which the attribute will be drawn. A higher number means the attribute will be drawn on top of attributes with lower numbers.
• y1: start of tick line in the vertical direction (in % of canvas).
• y2: end of tick line in the vertical direction (in % of canvas).
• line: a vcs line object (or name) to use for the line.

Similarly for the y ticks:

In [9]:
template.ytic1.list()

member =  ytic1
priority = 1
x1 = 0.0500000007451
x2 = 0.0399999991059
line = default

• priority: the priority represents the layer on which the attribute will be drawn. A higher number means the attribute will be drawn on top of attributes with lower numbers.
• x1: start of tick line in the horizontal direction (in % of canvas).
• x2: end of tick line in the horizontal direction (in % of canvas).
• line: a vcs line object (or name) to use for the line.

Note that a template only controls the extent of the tick marks, not their location/values. This is controlled via the graphic method's [x/y]ticlabels[1/2] and [x/y]mtics[1/2] attributes.

Let's set the tick marks properly.

##### First set of major ticks (x/y)¶
In [10]:
# x major tick marks for first set of tick marks (1) drawn all the way across with grey lines
template.xtic1.y1 = template.data.y1
template.xtic1.y2 = template.data.y2
grey = vcs.createline()
grey.color = ['grey',]
grey.width = [2]
template.xtic1.line = grey  # uses line object

# y major for first set of tick marks (1) drawn all the way across with darker grey lines
template.ytic1.x1 = template.data.x1
template.ytic1.x2 = template.data.x2
grey2 = vcs.createline()
grey2.color = [(40, 40, 40),]
grey2.width = [2,]
template.ytic1.line = grey2.name  # uses line name

x.clear()
x.plot(data, template)

Out[10]:
##### Second set of major ticks (x/y)¶
In [11]:
# x major tick marks for second set of tick marks (2) drawn outward in red
template.xtic2.priority=1  # turn on
template.xtic2.y1 = template.data.y2
template.xtic2.y2 = template.data.y2 + .01 # extend a bit further
template.xtic2.line="red"

# y major for second set of tick marks (2) drawn outward in red
template.ytic2.priority=1  # turn on
template.ytic2.x1 = template.data.x2
template.ytic2.x2 = template.data.x2 + .01 # extends a bit past it
template.ytic2.line = "red"
x.clear()
x.plot(data, template)

Out[11]:

#### Minor ticks (x/y)¶

Let's do the same for the minor tics or mintics, except using dotted lines and not extending them as far.

In [12]:
# x minor tick marks (set 1) drawn all the way across with grey lines
template.xmintic1.priority = 1
template.xmintic1.y1 = template.data.y1
template.xmintic1.y2 = template.data.y2
grey = vcs.createline(source=grey.name)
grey.type= ["dot",]
template.xmintic1.line = grey  # re-uses line object

# y minor (set 1) drawn all the way across using darker grey lines
template.ymintic1.priority = 1
template.ymintic1.x1 = template.data.x1
template.ymintic1.x2 = template.data.x2
grey2 = vcs.createline(source=grey2.name)
grey2.type= ["dot",]
template.ymintic1.line = grey2.name  # uses line name

# x minor tick marks (set 2) drawn outward in red (a bit less)
template.xmintic2.priority=1  # turn on
template.xmintic2.y1 = template.data.y2
template.xmintic2.y2 = template.data.y2 + .005 # extend a bit further
template.xmintic2.line="red"

# y minor (set 2) drawn outward in red
template.ymintic2.priority=1  # turn on
template.ymintic2.x1 = template.data.x2
template.ymintic2.x2 = template.data.x2 + .005 # extends a bit past it
template.ymintic2.line = "red"

x.clear()
x.plot(data, template)

Out[12]:
In [13]:
# too many tics; let's reduce their number
box = vcs.createboxfill()
box.xticlabels1 = {-180:"180W", -90:"90W", 0:"0", 90:"90E", 180:"180E", 270:"270E", 360:"0"}
box.xticlabels2 = box.xticlabels1 # same on both ends
box.yticlabels1 = {-90:"90S", -60:"60S", 0:"Eq", 60:"60N", 90:"90N"}
box.yticlabels2 = box.yticlabels1

# min ticks
box.xmtics1 = {-135:"135W", -45:"45W", 45:"45E", 135:"135E", 315:"315E"}
box.xmtics2 = box.xmtics1
box.ymtics1 = {-45:"45S", 45:"45N"}  # text does not matter as not drawn
box.ymtics2 = box.ymtics1

x.clear()
x.plot(data, box, template)

Out[13]: