# 1D Plots Tutorial¶

This tutorial is for creating 1D lines plot using CDAT's VCS.

Â© Software was developed by Charles Doutriaux and CDAT team, and tutorial was written by Charles Doutriaux (January 2018)

## Create VCS canvas¶

(Top)

In [1]:
import vcs
x = vcs.init(bg=True,geometry=(800,600))


## Prepare input data¶

(Top)

In [2]:
import numpy
angle = numpy.arange(0, 360, 10) # in degrees
s = numpy.sin(angle/180.*numpy.pi) # sin takes radians as input


## Very Basic Plot¶

(Top)

In its most basic form VCS does not need anything else to plot:

In [3]:
x.plot(s)

Out[3]:

## Basic Controls ¶

(Top)

Let's change the color of the line and size aspect and size of the markers.

For this we will need to create a 1D graphic method and alter some of its attributes

The following is list of available markers

In [4]:
line = vcs.create1d()
line.list()  # List what we can change

---------- Yxvsx (GYx) member (attribute) listings ----------
graphics method = G1d
name = __1d_263737865552086
projection = linear
xticlabels1 = *
xticlabels2 = *
xmtics1 =
xmtics2 =
yticlabels1 = *
yticlabels2 = *
ymtics1 =
ymtics2 =
datawc_x1 = 1e+20
datawc_y1 =  1e+20
datawc_x2 =  1e+20
datawc_y2 =  1e+20
datawc_timeunits =  days since 2000
datawc_calendar =  135441
xaxisconvert =  linear
yaxisconvert =  linear
linetype =  solid
linecolor =  [0.0, 0.0, 0.0, 100.0]
linewidth =  1
marker =  dot
markercolor =  [0.0, 0.0, 0.0, 100.0]
markersize =  1
flip =  False

In [5]:
line.linecolor = "red"  # Red color obviously
line.linewidth = 2.  # A bit thicker
line.marker = "circle"  #
line.markersize = 1.25  # A bit bigger
x.clear() # Let's clear the first plot
x.switchfonts("default","Clarendon")
x.plot(s,line)

Out[5]:

## Altering X Axis¶

(Top)

We would like the axis to be shown in radians, since s is a pure array the x axis is seen by vcs as 0 to 35

Let's create a dictionary to show a few X points

0 -> 0 45degrees = 4.5 in our units = $\pi/4$

In [6]:
angles = {0:'0',9:r'$\pi/2$',18:r'$\pi$', 27:r'$3\pi/2$',36:r'$2\pi$'}
line.xticlabels1 = angles
x.clear()
x.plot(s,line)

Out[6]:

But we would like to have the axis labeled "angle" rather than axis_0 so we need to make s a transient variable

In [7]:
import MV2
s = MV2.array(s)
s.id = "sine"
xaxis = s.getAxis(0)
xaxis.id = "angle"
# let's make them radians as well
xaxis[:] = xaxis[:]/18.*numpy.pi
# That means we need to match or symbols to new values
angles = {0:'0',numpy.pi/2.:r'$\pi/2$',numpy.pi:r'$\pi$', 3*numpy.pi/2.:r'$3\pi/2$',2*numpy.pi:r'$2\pi$'}
line.xticlabels1 = angles
x.clear()
x.plot(s,line)

Out[7]:

The last point being exactly 2$pi$ it is not drawn let's extend our x axis a bit Also by default it is using the first and last value to determine the x values, this can be an issue when plotting multiple line (with different x ref for example).

We recommend setting the x range manually

In [8]:
line.datawc_x1 = -0.1
line.datawc_x2 = numpy.pi*2.000001
x.clear()
x.plot(s,line)

Out[8]:

## Altering Y Axis¶

(Top)

We can also tweak the y axis, by default it is using the max and min of the data it is plotting. If you have mutliple line plot this can be an issue as min/max will change with each plot.

We recommend setting the y range manually

In [9]:
line.datawc_y1 = -1.1
line.datawc_y2 = 1.1
line.yticlabels1 = {-1.:"-1",-.5:"-0.5",0:"0",.5:"0.5",1:"1"}
x.clear()
x.plot(s,line)

Out[9]:

## Beautifying the plot some more via templates¶

(Top)

Let's draw thick line at tickmarks and dotted ones in between

In [10]:
tmpl = vcs.createtemplate()

In [11]:
thick = vcs.createline()  # for thick ticks
thick.width = 1.5  # A bit thicker
thick.color = [[56,56,56]]
dots = vcs.createline()  # for thin/sub ticks
dots.type = ["dot"]
dots.color = [[78,78,78]]
tmpl.xtic1.y2 = tmpl.data.y2  # Ticks extends all the way accross the data section
tmpl.xtic1.line = thick
tmpl.xmintic1.y2 = tmpl.data.y2  # Ticks extends all the way accross the data section
tmpl.xmintic1.priority = 1
tmpl.xmintic1.line = dots
tmpl.ytic1.x2 = tmpl.data.x2  # Ticks extends all the way accross the data section
tmpl.ytic1.line = thick
tmpl.ymintic1.x2 = tmpl.data.x2  # Ticks extends all the way accross the data section
tmpl.ymintic1.priority = 1
tmpl.ymintic1.line = dots
line.xmtics1 = {numpy.pi/4.:"",3*numpy.pi/4:"",5*numpy.pi/4:"",7*numpy.pi/4:""}
line.ymtics1 = {-.75:"", -.25:"", .25:"", .75:""}
x.clear()
x.plot(s,line,tmpl)

Out[11]:
In [12]:
black = vcs.createline()
black.width = 2.
tmpl.ymintic2.line = black
tmpl.ymintic2.x1 = tmpl.data.x1
tmpl.ymintic2.x2 = tmpl.data.x2
tmpl.ymintic2.priority = 2  # To be sure it's on top
tmpl.xmintic2.line = black
tmpl.xmintic2.y1 = tmpl.data.y1
tmpl.xmintic2.y2 = tmpl.data.y2
tmpl.xmintic2.priority = 2  # To be sure it's on top
line.ymtics2 = {0:""}
line.xmtics2 = {0:""}
tmpl.box1.line = black  # make outer box match thick line
x.clear()
x.plot(s, tmpl, line)

Out[12]:

## Multiple Lines¶

(Top)

Let's plot multiple lines

In [13]:
c = MV2.cos(angle/180.*numpy.pi)
c.id = "cosine"
c.setAxis(0,xaxis)

x.clear()
x.plot(s,tmpl,line)
x.plot(c,line,tmpl)  # order does not matter

Out[13]:

We are almost there but we need to blank a few attributes on template (name, min, max, etc.. and legend) Also we need a different color for the cosine

In [14]:
tmpl.blank(["dataname","min","mean","max"])
line_cos = vcs.create1d(source=line)
line_cos.linecolor = "blue"
line_cos.marker = "diamond"
line_cos.markersize = 1.5
line_cos.markercolor = "black"
x.clear()
x.plot(s,tmpl,line)
x.plot(c,tmpl,line_cos)

Out[14]:

Ok now we still have to tweak the legend, templates have a built in function for this

In [15]:
# First let's blank the legend default
x.clear()
tmpl.legend.priority=1  # Make sure it is on
tmpl.drawLinesAndMarkersLegend(x, [line.linecolor, line_cos.linecolor],
[line.linetype, line_cos.linetype],
[line.linewidth,line_cos.linewidth],
[line.markercolor, line_cos.markercolor],
[line.marker, line_cos.marker],
[line.markersize, line_cos.markersize],
[s.id, c.id])
tmpl.legend.priority=0
x.plot(s,tmpl,line)
x.plot(c,tmpl,line_cos)

Out[15]:

And finally let's use to template to beautify a bit more

In [16]:
x2 = .7
tmpl.data.x2 = x2
# We also need to move the other things linked to it
tmpl.box1.x2= x2
tmpl.ymintic1.x2 = x2
tmpl.ymintic2.x2 = x2
tmpl.ytic1.x2 = x2
tmpl.ytic2.x1 = x2
tmpl.ytic2.x2 = x2+.01

# Let's move the legend
tmpl.legend.x1 = x2+.05
tmpl.legend.x2 = .9
tmpl.legend.y1 = .45
tmpl.legend.y2 = .55

x.clear()
tmpl.legend.priority=1  # Make sure it is on
# Let's stack it vertically now
tmpl.drawLinesAndMarkersLegend(x, [line.linecolor, line_cos.linecolor],
[line.linetype, line_cos.linetype],
[line.linewidth,line_cos.linewidth],
[line.markercolor, line_cos.markercolor],
[line.marker, line_cos.marker],
[line.markersize, line_cos.markersize],
[s.id, c.id],
stacking="vertical")
tmpl.legend.priority=0
x.plot(s,tmpl,line)
x.plot(c,tmpl,line_cos)

Out[16]:

## Other types of 1D plots¶

(Top)

### Flipping axes (aka x(y) vs y or xyvsy)

In [17]:
line_flip = vcs.create1d(source=line)
line_flip.flip = True
# Note that f = vcs.createxyvsy() creates a 1d plot with flip = True
def flip(gm, attr):
tmp = getattr(gm, "x"+attr)
setattr(gm, "x"+attr, getattr(gm,"y"+attr))
setattr(gm, "y"+attr, tmp)

for att in ["mtics","ticlabels"]:
for number in ["1", "2"]:
flip(line_flip, att + number)

line_flip.datawc_x1 = -1.1
line_flip.datawc_x2 = 1.1
line_flip.datawc_y1 = -.1
line_flip.datawc_y2 = numpy.pi*2.1
x.clear()
x.plot(s,line_flip, tmpl)


Out[17]:

### Scatter plots aka y vs x

Let's plot cosine vs sine

In [18]:
scatter = vcs.create1d(source=line)
scatter.datawc_x1 = -2.2
scatter.datawc_x2 = 2.2
scatter.xmtics1 = scatter.ymtics1
scatter.xmtics2 = scatter.ymtics2
scatter.xticlabels1 = scatter.yticlabels1
scatter.xticlabels2 = scatter.yticlabels2
x.clear()
# x values passed first
x.plot(2*s,c,scatter)

Out[18]:

Let's turn off the lines

In [19]:
scatter.linecolor= [0,0,0,0]  # no opacity = transparent
x.clear()
# x values passed first
x.plot(2*s,c,scatter)

Out[19]:

Or turn off the markers

In [20]:
scatter.linecolor = "red"
scatter.markercolor = [0,0,0,0]
x.clear()
# x values passed first
x.plot(2*s,c,scatter)

Out[20]: