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:
This tutorial explains how to control the template and its relation to VCS's other primary objects.
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.
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")
You can also list all of your existing templates and use one of them as a starting point.
mytemplates = vcs.listelements("template")
print("Existing templates:", mytemplates) # notice the randomly named ones
template = vcs.createtemplate(source="vcs_is_easy")
Now in order to use this template either pass the template object to the vcs plot function.
# Get some data to plot
vcs.download_sample_data_files()
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)
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.
template.list()
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 %).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)
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:
template.box1.list()
The new attribute here is the line
attribute. You can use any line object from vcs (or create one).
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)
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
,
For example, for xtic1
the attributes are:
template.xtic1.list()
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:
template.ytic1.list()
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.
# 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)
# 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)
Let's do the same for the minor tics or mintics, except using dotted lines and not extending them as far.
# 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)
# 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)