Chapter 7 Basic Plotting

7.1 Using Plot wiht Coordinate Vectors

# set up x values
foo <- c(1.1,2,3.5,3.9,4.2)
# set up y values
bar <- c(2,2.2,-1.3,0,0.2)
# output command
plot(foo,bar)

# you can also setup a plot using a matrix
foo
[1] 1.1 2.0 3.5 3.9 4.2
bar
[1]  2.0  2.2 -1.3  0.0  0.2
baz<-cbind(foo,bar)
baz
     foo  bar
[1,] 1.1  2.0
[2,] 2.0  2.2
[3,] 3.5 -1.3
[4,] 3.9  0.0
[5,] 4.2  0.2

And we get the same plot using a matrix

plot(baz)

To know more about the plot command: ?plot.default

7.2 Graphical Parameters

Here are some of the different parameters that you can alter. type tells r how to plot the supplied coordinates main,xlab, ylab adds title, axis labels col sets color pch sets point characther cex sets character expansion lty sets line type lwd sets line width xlim, ylim sets limits for horizontal range and vertical ranges.

7.2.1 Automatic Plot Types

INstead of default (p) for point, you can specify l as in letter l to produce a line chart

bar
[1]  2.0  2.2 -1.3  0.0  0.2
foo
[1] 1.1 2.0 3.5 3.9 4.2
plot(foo,bar,type="l")

Both line and points

plot(foo,bar,type="b")

Option “n” produces no plots and is useful for complicated plots that must bre constructed in steps.

plot(foo,bar,type="n")

7.2.2 Title and Axis Labels

To add title and more descriptive axis labels.

foo
[1] 1.1 2.0 3.5 3.9 4.2
bar
[1]  2.0  2.2 -1.3  0.0  0.2
plot(foo,bar,type="b",main="My lovely plot", xlab="x axis label",ylab="location y")

Use the escape sequence /n to create on next line

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y")

7.2.3 Color

Color makes data much clearer by distinguishing factor levels or empahsizing important numeric limits. You can set colors with the col paramaeter in a number of ways.

The simplest is to use an integer selector or character string. There are a number of color string values recognized by R which you can see by enetrin color() at the prompt. 1=black.

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",col=2)

Set color to Green

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y", col="seagreen4")

7.2.4 Line and Point Appearance

Pch (point character) is use to alter appearance of the plotted points lty (line type) is used to alter the lines cex (character expansion) is used to control the size of the plotted points lwd (line width)is used to control the thickness of the lines.

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",
     ,pch=8)

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",
     ,lty=2)

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",
     ,cex=3.3)

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",
     ,lwd=3.3
  )

Putting it all together:

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",
     col=4,pch=8,lty=2,cex=2.3,lwd=3.3)

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",
     col=6,pch=15,lty=3,cex=.7,lwd=2)

7.2.5 Plotting Region Limits

You can specify a single character to use for each point or you can specify a value between 1 and 25 Use xlim and ylim to set the custom plotting area limits.

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     xlim=c(3,5),ylim=c(-0.5,0.2))

plot(foo,bar,type="b",main="My lovely plot \n by wilson chua", xlab="x axis label",ylab="location y",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     xlim=c(-10,5),ylim=c(-3,3))

7.3 Adding Points, Lines and Text to an Existing PLot

Some ready to use functions in R that will add to a plot wihtout refreshing or clearing the window Point ->add points lines, abline, segments -> add lines text -> writes text arrows -> adds arrows legend -> adds a legend

First we create a basic plot

x <-1:20
y <-c(-1.49,3.37,2.59,-2.78,-3.98,-.92,6.43,8.51,3.41,-8.23,-12.01,-6.58,2.87,14.12,9.63,-4.58,-14.78,-11.67,1.17,15.62)
plot(x,y)

We add lines by using the type=“b” (both line and dots)

plot(x,y,type="b",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     )

NOw we add the reference lines using the abline function and color it red, line type (lty is dashed) and line width (lwd) is set to 2

plot(x,y,type="b",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     )
abline(h=c(-5,5),col="red",lty=2,lwd=2)

We use the segments command to set up two verticle lines in the segment (not the entire line)

plot(x,y,type="b",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     )
abline(h=c(-5,5),col="red",lty=2,lwd=2)
segments(x0=c(5,15),y0=c(-5,-5),x1=c(5,15),y1=c(5,5),col="red",lty=3,lwd=2)

Use points to add specific coordinates from x and y to the plots.

plot(x,y,type="b",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     )
abline(h=c(-5,5),col="red",lty=2,lwd=2)
segments(x0=c(5,15),y0=c(-5,-5),x1=c(5,15),y1=c(5,5),col="red",lty=3,lwd=2)
# new code
points(x[y>=5],y[y>=5],pch=3,col="darkmagenta",cex=3)
points(x[y<=-5],y[y<=-5],pch=3,col="darkblue",cex=3)

NOw identify the sweet spot in blue and other points in black.

plot(x,y,type="b",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     )
abline(h=c(-5,5),col="red",lty=2,lwd=2)
segments(x0=c(5,15),y0=c(-5,-5),x1=c(5,15),y1=c(5,5),col="red",lty=3,lwd=2)
points(x[y>=5],y[y>=5],pch=3,col="darkmagenta",cex=3)
points(x[y<=-5],y[y<=-5],pch=3,col="darkblue",cex=3)
# new code to find the sweet spot
points(x[(x>5&x<=15)&(y>-5&y<5)],y[(x>5&x<=15)&(y>-5&y<5)],pch=19,col="blue")
points(x[(x<5|x>15)&(y>-5&y<5)],y[(x<5|x>15)&(y>-5&y<5)],pch=19,col=1)

Put an arrow to point to the sweet spot:

plot(x,y,type="b",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     )
abline(h=c(-5,5),col="red",lty=2,lwd=2)
segments(x0=c(5,15),y0=c(-5,-5),x1=c(5,15),y1=c(5,5),col="red",lty=3,lwd=2)
points(x[y>=5],y[y>=5],pch=3,col="darkmagenta",cex=3)
points(x[y<=-5],y[y<=-5],pch=3,col="darkblue",cex=3)
points(x[(x>5&x<=15)&(y>-5&y<5)],y[(x>5&x<=15)&(y>-5&y<5)],pch=19,col="blue")
points(x[(x<5|x>15)&(y>-5&y<5)],y[(x<5|x>15)&(y>-5&y<5)],pch=19,col=1)
# new code
arrows(x0=8,y0=14,x1=11,y1=2.5)

Then put in the label

plot(x,y,type="b",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     )
abline(h=c(-5,5),col="red",lty=2,lwd=2)
segments(x0=c(5,15),y0=c(-5,-5),x1=c(5,15),y1=c(5,5),col="red",lty=3,lwd=2)
points(x[y>=5],y[y>=5],pch=3,col="darkmagenta",cex=3)
points(x[y<=-5],y[y<=-5],pch=3,col="darkblue",cex=3)
points(x[(x>5&x<=15)&(y>-5&y<5)],y[(x>5&x<=15)&(y>-5&y<5)],pch=19,col="blue")
points(x[(x<5|x>15)&(y>-5&y<5)],y[(x<5|x>15)&(y>-5&y<5)],pch=19,col=1)
arrows(x0=8,y0=14,x1=11,y1=2.5)
# new code
text(x=8,y=15,labels="sweet spot")      

Then we add a legend function

plot(x,y,type="b",
     col=6,pch=15,lty=3,cex=.7,lwd=2,
     )
abline(h=c(-5,5),col="red",lty=2,lwd=2)
segments(x0=c(5,15),y0=c(-5,-5),x1=c(5,15),y1=c(5,5),col="red",lty=3,lwd=2)
points(x[y>=5],y[y>=5],pch=3,col="darkmagenta",cex=3)
points(x[y<=-5],y[y<=-5],pch=3,col="darkblue",cex=3)
points(x[(x>5&x<=15)&(y>-5&y<5)],y[(x>5&x<=15)&(y>-5&y<5)],pch=19,col="blue")
points(x[(x<5|x>15)&(y>-5&y<5)],y[(x<5|x>15)&(y>-5&y<5)],pch=19,col=1)
arrows(x0=8,y0=14,x1=11,y1=2.5)
text(x=8,y=15,labels="sweet spot")  
# new code
legend("bottomleft",
       legend=c("overall process","sweet","standard",
                "too big","too small","sweet y range","sweet x range"),
                pch=c(NA,19,1,4,3,NA,NA),lty=c(4,NA,NA,NA,NA,2,3),
                col=c("black","blue","black","darkmagenta","darkgreen","red","red"),
                lwd=c(1,NA,NA,NA,NA,2,2),pt.cex=c(NA,1,1,2,2,NA,NA))

7.4 The ggplot2 Package

gg stands for grammar of graphics. Created by Hadley Wickham.

7.4.1 A Qucik plot with qplot

library("ggplot2")
foo
[1] 1.1 2.0 3.5 3.9 4.2
bar
[1]  2.0  2.2 -1.3  0.0  0.2
qplot(foo,bar)

Add title and axis labels

qplot(foo,bar,main="My lovely qplot",xlab="x axis label", ylab="Y axis label")

One difference between plot and qplot is that in qplot the graph is an object

baz<-plot(foo,bar)

baz
NULL
qux<-qplot(foo,bar)
qux

7.4.2 Setting Appearance Constants with Geoms

Since the qplot outputs to an object, you can work with and alter the object directly rather than using a long list of arguments or secondary functions executed sperately.

wls=qplot(foo,bar,geom="blank")+geom_point()+ geom_line()
wls=wls+geom_point(size=3,shape=6,color="blue")
wls

wls=wls+geom_line(color="red",linetype=2)
wls

wls=qplot(foo,bar,geom="blank")+geom_point()+ geom_line()
wls=wls+geom_point(shape=7,size=4)
wls

7.4.3 Aethetic Mapping with Geomst

Working with factors, in ggplot2, factors are treated as variables and can automatically apply particular styles to different categories.

Let us create the categories to hold the standard, sweet, too small, or too big.

# review the data in x and y
x
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
y
 [1]  -1.49   3.37   2.59  -2.78  -3.98  -0.92   6.43   8.51   3.41  -8.23 -12.01  -6.58   2.87  14.12   9.63
[16]  -4.58 -14.78 -11.67   1.17  15.62
# 
ptype<- rep(NA, length(x=x))
ptype[y>=5] <-"too big"
ptype[y<=-5]<-"too small"
ptype[(x>5&x<=15)&(y>-5&y<5)]<-"sweet"
ptype[(x<5|x>15)&(y>-5&y<5)]<-"standard"
ptype<-factor(x=ptype)
ptype
 [1] standard  standard  standard  standard  <NA>      sweet     too big   too big   sweet     too small too small
[12] too small sweet     too big   too big   standard  too small too small standard  too big  
Levels: standard sweet too big too small

NOw qplot this

qplot(x,y,color=ptype,shape=ptype)

Now lets make it visually better

qplot(x,y,color=ptype,shape=ptype)+
  geom_point(size=4)+
  geom_line(mapping=aes(group=1),color="black",lty=2)+
  geom_hline(mapping=aes(yintercept=c(-5,5)),color="red")+
  geom_segment(mapping=aes(x=5,y=-5,xend=5,yend=5),color="red",lty=3)+
  geom_segment(mapping=aes(x=15,y=-5,xend=15,yend=5),color="red",lty=3)

LS0tDQp0aXRsZTogQ2hhcHRlciA3IEJhc2ljIFBsb3R0aW5nIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KPGgxPkNoYXB0ZXIgNyBCYXNpYyBQbG90dGluZyA8L2gxPg0KPGgyPjcuMSBVc2luZyBQbG90IHdpaHQgQ29vcmRpbmF0ZSBWZWN0b3JzPC9oMj4NCmBgYHtyfQ0KIyBzZXQgdXAgeCB2YWx1ZXMNCmZvbyA8LSBjKDEuMSwyLDMuNSwzLjksNC4yKQ0KIyBzZXQgdXAgeSB2YWx1ZXMNCmJhciA8LSBjKDIsMi4yLC0xLjMsMCwwLjIpDQojIG91dHB1dCBjb21tYW5kDQpwbG90KGZvbyxiYXIpDQoNCmBgYA0KDQpgYGB7cn0NCiMgeW91IGNhbiBhbHNvIHNldHVwIGEgcGxvdCB1c2luZyBhIG1hdHJpeA0KZm9vDQpiYXINCmJhejwtY2JpbmQoZm9vLGJhcikNCmJheg0KDQpgYGANCg0KQW5kIHdlIGdldCB0aGUgc2FtZSBwbG90IHVzaW5nIGEgbWF0cml4DQoNCg0KDQpgYGB7cn0NCnBsb3QoYmF6KQ0KYGBgDQpUbyBrbm93IG1vcmUgYWJvdXQgdGhlIHBsb3QgY29tbWFuZDoNCj9wbG90LmRlZmF1bHQNCg0KPGgyPjcuMiBHcmFwaGljYWwgUGFyYW1ldGVyczwvaDI+DQpIZXJlIGFyZSBzb21lIG9mIHRoZSBkaWZmZXJlbnQgcGFyYW1ldGVycyB0aGF0IHlvdSBjYW4gYWx0ZXIuDQp0eXBlIHRlbGxzIHIgaG93IHRvIHBsb3QgdGhlIHN1cHBsaWVkIGNvb3JkaW5hdGVzDQptYWluLHhsYWIsIHlsYWIgYWRkcyB0aXRsZSwgYXhpcyBsYWJlbHMNCmNvbCBzZXRzIGNvbG9yDQpwY2ggc2V0cyBwb2ludCBjaGFyYWN0aGVyDQpjZXggc2V0cyBjaGFyYWN0ZXIgZXhwYW5zaW9uDQpsdHkgc2V0cyBsaW5lIHR5cGUNCmx3ZCBzZXRzIGxpbmUgd2lkdGgNCnhsaW0sIHlsaW0gc2V0cyBsaW1pdHMgZm9yIGhvcml6b250YWwgcmFuZ2UgYW5kIHZlcnRpY2FsIHJhbmdlcy4NCg0KDQo8aDM+Ny4yLjEgQXV0b21hdGljIFBsb3QgVHlwZXM8L2gzPg0KSU5zdGVhZCBvZiBkZWZhdWx0IChwKSBmb3IgcG9pbnQsIHlvdSBjYW4gc3BlY2lmeSBsIGFzIGluIGxldHRlciBsIHRvIHByb2R1Y2UgYSBsaW5lIGNoYXJ0DQpgYGB7cn0NCg0KYmFyDQpmb28NCnBsb3QoZm9vLGJhcix0eXBlPSJsIikNCg0KYGBgDQpCb3RoIGxpbmUgYW5kIHBvaW50cw0KYGBge3J9DQpwbG90KGZvbyxiYXIsdHlwZT0iYiIpDQoNCmBgYA0KT3B0aW9uICJuIiBwcm9kdWNlcyBubyBwbG90cyBhbmQgaXMgdXNlZnVsIGZvciBjb21wbGljYXRlZCBwbG90cyB0aGF0IG11c3QgYnJlIGNvbnN0cnVjdGVkIGluIHN0ZXBzLg0KDQpgYGB7cn0NCnBsb3QoZm9vLGJhcix0eXBlPSJuIikNCmBgYA0KDQo8aDM+Ny4yLjIgVGl0bGUgYW5kIEF4aXMgTGFiZWxzPC9oMz4NClRvIGFkZCB0aXRsZSBhbmQgbW9yZSBkZXNjcmlwdGl2ZSBheGlzIGxhYmVscy4NCmBgYHtyfQ0KZm9vDQpiYXINCnBsb3QoZm9vLGJhcix0eXBlPSJiIixtYWluPSJNeSBsb3ZlbHkgcGxvdCIsIHhsYWI9InggYXhpcyBsYWJlbCIseWxhYj0ibG9jYXRpb24geSIpDQoNCmBgYA0KVXNlIHRoZSBlc2NhcGUgc2VxdWVuY2UgL24gdG8gY3JlYXRlIG9uIG5leHQgbGluZQ0KDQpgYGB7cn0NCnBsb3QoZm9vLGJhcix0eXBlPSJiIixtYWluPSJNeSBsb3ZlbHkgcGxvdCBcbiBieSB3aWxzb24gY2h1YSIsIHhsYWI9InggYXhpcyBsYWJlbCIseWxhYj0ibG9jYXRpb24geSIpDQpgYGANCg0KPGgzPjcuMi4zIENvbG9yIDwvaDM+DQpDb2xvciBtYWtlcyBkYXRhIG11Y2ggY2xlYXJlciBieSBkaXN0aW5ndWlzaGluZyBmYWN0b3IgbGV2ZWxzIG9yIGVtcGFoc2l6aW5nIGltcG9ydGFudCBudW1lcmljIGxpbWl0cy4NCllvdSBjYW4gc2V0IGNvbG9ycyB3aXRoIHRoZSBjb2wgcGFyYW1hZXRlciBpbiBhIG51bWJlciBvZiB3YXlzLg0KDQpUaGUgc2ltcGxlc3QgaXMgdG8gdXNlIGFuIGludGVnZXIgc2VsZWN0b3Igb3IgY2hhcmFjdGVyIHN0cmluZy4gVGhlcmUgYXJlIGEgbnVtYmVyIG9mIGNvbG9yIHN0cmluZyB2YWx1ZXMgcmVjb2duaXplZCBieSBSIHdoaWNoIHlvdSBjYW4gc2VlIGJ5IGVuZXRyaW4gY29sb3IoKSBhdCB0aGUgcHJvbXB0Lg0KMT1ibGFjay4NCmBgYHtyfQ0KcGxvdChmb28sYmFyLHR5cGU9ImIiLG1haW49Ik15IGxvdmVseSBwbG90IFxuIGJ5IHdpbHNvbiBjaHVhIiwgeGxhYj0ieCBheGlzIGxhYmVsIix5bGFiPSJsb2NhdGlvbiB5Iixjb2w9MikNCg0KYGBgDQoNClNldCBjb2xvciB0byBHcmVlbg0KYGBge3J9DQoNCnBsb3QoZm9vLGJhcix0eXBlPSJiIixtYWluPSJNeSBsb3ZlbHkgcGxvdCBcbiBieSB3aWxzb24gY2h1YSIsIHhsYWI9InggYXhpcyBsYWJlbCIseWxhYj0ibG9jYXRpb24geSIsIGNvbD0ic2VhZ3JlZW40IikNCmBgYA0KDQo8aDM+Ny4yLjQgTGluZSBhbmQgUG9pbnQgQXBwZWFyYW5jZTwvaDM+DQpQY2ggKHBvaW50IGNoYXJhY3RlcikgaXMgdXNlIHRvIGFsdGVyIGFwcGVhcmFuY2Ugb2YgdGhlIHBsb3R0ZWQgcG9pbnRzDQpsdHkgKGxpbmUgdHlwZSkgaXMgdXNlZCB0byBhbHRlciB0aGUgbGluZXMgDQpjZXggKGNoYXJhY3RlciBleHBhbnNpb24pIGlzIHVzZWQgdG8gY29udHJvbCB0aGUgc2l6ZSBvZiB0aGUgcGxvdHRlZCBwb2ludHMNCmx3ZCAobGluZSB3aWR0aClpcyB1c2VkIHRvIGNvbnRyb2wgdGhlIHRoaWNrbmVzcyBvZiB0aGUgbGluZXMuDQoNCmBgYHtyfQ0KcGxvdChmb28sYmFyLHR5cGU9ImIiLG1haW49Ik15IGxvdmVseSBwbG90IFxuIGJ5IHdpbHNvbiBjaHVhIiwgeGxhYj0ieCBheGlzIGxhYmVsIix5bGFiPSJsb2NhdGlvbiB5IiwNCiAgICAgLHBjaD04KQ0KYGBgDQpgYGB7cn0NCnBsb3QoZm9vLGJhcix0eXBlPSJiIixtYWluPSJNeSBsb3ZlbHkgcGxvdCBcbiBieSB3aWxzb24gY2h1YSIsIHhsYWI9InggYXhpcyBsYWJlbCIseWxhYj0ibG9jYXRpb24geSIsDQogICAgICxsdHk9MikNCmBgYA0KYGBge3J9DQpwbG90KGZvbyxiYXIsdHlwZT0iYiIsbWFpbj0iTXkgbG92ZWx5IHBsb3QgXG4gYnkgd2lsc29uIGNodWEiLCB4bGFiPSJ4IGF4aXMgbGFiZWwiLHlsYWI9ImxvY2F0aW9uIHkiLA0KICAgICAsY2V4PTMuMykNCmBgYA0KYGBge3J9DQoNCnBsb3QoZm9vLGJhcix0eXBlPSJiIixtYWluPSJNeSBsb3ZlbHkgcGxvdCBcbiBieSB3aWxzb24gY2h1YSIsIHhsYWI9InggYXhpcyBsYWJlbCIseWxhYj0ibG9jYXRpb24geSIsDQogICAgICxsd2Q9My4zDQogICkNCmBgYA0KUHV0dGluZyBpdCBhbGwgdG9nZXRoZXI6DQoNCmBgYHtyfQ0KcGxvdChmb28sYmFyLHR5cGU9ImIiLG1haW49Ik15IGxvdmVseSBwbG90IFxuIGJ5IHdpbHNvbiBjaHVhIiwgeGxhYj0ieCBheGlzIGxhYmVsIix5bGFiPSJsb2NhdGlvbiB5IiwNCiAgICAgY29sPTQscGNoPTgsbHR5PTIsY2V4PTIuMyxsd2Q9My4zKQ0KYGBgDQpgYGB7cn0NCnBsb3QoZm9vLGJhcix0eXBlPSJiIixtYWluPSJNeSBsb3ZlbHkgcGxvdCBcbiBieSB3aWxzb24gY2h1YSIsIHhsYWI9InggYXhpcyBsYWJlbCIseWxhYj0ibG9jYXRpb24geSIsDQogICAgIGNvbD02LHBjaD0xNSxsdHk9MyxjZXg9LjcsbHdkPTIpDQpgYGANCg0KPGgzPjcuMi41IFBsb3R0aW5nIFJlZ2lvbiBMaW1pdHM8L2gzPg0KDQpZb3UgY2FuIHNwZWNpZnkgYSBzaW5nbGUgY2hhcmFjdGVyIHRvIHVzZSBmb3IgZWFjaCBwb2ludCBvciB5b3UgY2FuIHNwZWNpZnkgYSB2YWx1ZSBiZXR3ZWVuIDEgYW5kIDI1DQpVc2UgeGxpbSBhbmQgeWxpbSB0byBzZXQgdGhlIGN1c3RvbSBwbG90dGluZyBhcmVhIGxpbWl0cy4NCmBgYHtyfQ0KcGxvdChmb28sYmFyLHR5cGU9ImIiLG1haW49Ik15IGxvdmVseSBwbG90IFxuIGJ5IHdpbHNvbiBjaHVhIiwgeGxhYj0ieCBheGlzIGxhYmVsIix5bGFiPSJsb2NhdGlvbiB5IiwNCiAgICAgY29sPTYscGNoPTE1LGx0eT0zLGNleD0uNyxsd2Q9MiwNCiAgICAgeGxpbT1jKDMsNSkseWxpbT1jKC0wLjUsMC4yKSkNCmBgYA0KYGBge3J9DQpwbG90KGZvbyxiYXIsdHlwZT0iYiIsbWFpbj0iTXkgbG92ZWx5IHBsb3QgXG4gYnkgd2lsc29uIGNodWEiLCB4bGFiPSJ4IGF4aXMgbGFiZWwiLHlsYWI9ImxvY2F0aW9uIHkiLA0KICAgICBjb2w9NixwY2g9MTUsbHR5PTMsY2V4PS43LGx3ZD0yLA0KICAgICB4bGltPWMoLTEwLDUpLHlsaW09YygtMywzKSkNCmBgYA0KDQoNCjxoMj4gNy4zIEFkZGluZyBQb2ludHMsIExpbmVzIGFuZCBUZXh0IHRvIGFuIEV4aXN0aW5nIFBMb3QgPC9oMj4NCg0KU29tZSByZWFkeSB0byB1c2UgZnVuY3Rpb25zIGluIFIgdGhhdCB3aWxsIGFkZCB0byBhIHBsb3Qgd2lodG91dCByZWZyZXNoaW5nIG9yIGNsZWFyaW5nIHRoZSB3aW5kb3cNClBvaW50IC0+YWRkIHBvaW50cw0KbGluZXMsIGFibGluZSwgc2VnbWVudHMgLT4gYWRkIGxpbmVzDQp0ZXh0IC0+IHdyaXRlcyB0ZXh0DQphcnJvd3MgLT4gYWRkcyBhcnJvd3MNCmxlZ2VuZCAtPiBhZGRzIGEgbGVnZW5kDQoNCg0KRmlyc3Qgd2UgY3JlYXRlIGEgYmFzaWMgcGxvdA0KYGBge3J9DQp4IDwtMToyMA0KeSA8LWMoLTEuNDksMy4zNywyLjU5LC0yLjc4LC0zLjk4LC0uOTIsNi40Myw4LjUxLDMuNDEsLTguMjMsLTEyLjAxLC02LjU4LDIuODcsMTQuMTIsOS42MywtNC41OCwtMTQuNzgsLTExLjY3LDEuMTcsMTUuNjIpDQpwbG90KHgseSkNCg0KYGBgDQpXZSBhZGQgbGluZXMgYnkgdXNpbmcgdGhlIHR5cGU9ImIiIChib3RoIGxpbmUgYW5kIGRvdHMpDQoNCg0KYGBge3J9DQpwbG90KHgseSx0eXBlPSJiIiwNCiAgICAgY29sPTYscGNoPTE1LGx0eT0zLGNleD0uNyxsd2Q9MiwNCiAgICAgKQ0KYGBgDQpOT3cgd2UgYWRkIHRoZSByZWZlcmVuY2UgbGluZXMgdXNpbmcgdGhlIGFibGluZSBmdW5jdGlvbiBhbmQgY29sb3IgaXQgcmVkLCBsaW5lIHR5cGUgKGx0eSBpcyBkYXNoZWQpDQphbmQgbGluZSB3aWR0aCAobHdkKSBpcyBzZXQgdG8gMg0KDQpgYGB7cn0NCnBsb3QoeCx5LHR5cGU9ImIiLA0KICAgICBjb2w9NixwY2g9MTUsbHR5PTMsY2V4PS43LGx3ZD0yLA0KICAgICApDQphYmxpbmUoaD1jKC01LDUpLGNvbD0icmVkIixsdHk9Mixsd2Q9MikNCmBgYA0KDQoNCldlIHVzZSB0aGUgc2VnbWVudHMgY29tbWFuZCB0byBzZXQgdXAgdHdvIHZlcnRpY2xlIGxpbmVzIGluIHRoZSBzZWdtZW50IChub3QgdGhlIGVudGlyZSBsaW5lKQ0KDQpgYGB7cn0NCnBsb3QoeCx5LHR5cGU9ImIiLA0KICAgICBjb2w9NixwY2g9MTUsbHR5PTMsY2V4PS43LGx3ZD0yLA0KICAgICApDQojIG5ldyBjb2RlDQphYmxpbmUoaD1jKC01LDUpLGNvbD0icmVkIixsdHk9Mixsd2Q9MikNCnNlZ21lbnRzKHgwPWMoNSwxNSkseTA9YygtNSwtNSkseDE9Yyg1LDE1KSx5MT1jKDUsNSksY29sPSJyZWQiLGx0eT0zLGx3ZD0yKQ0KYGBgDQpVc2UgcG9pbnRzIHRvIGFkZCBzcGVjaWZpYyBjb29yZGluYXRlcyBmcm9tIHggYW5kIHkgdG8gdGhlIHBsb3RzLg0KDQpgYGB7cn0NCnBsb3QoeCx5LHR5cGU9ImIiLA0KICAgICBjb2w9NixwY2g9MTUsbHR5PTMsY2V4PS43LGx3ZD0yLA0KICAgICApDQphYmxpbmUoaD1jKC01LDUpLGNvbD0icmVkIixsdHk9Mixsd2Q9MikNCnNlZ21lbnRzKHgwPWMoNSwxNSkseTA9YygtNSwtNSkseDE9Yyg1LDE1KSx5MT1jKDUsNSksY29sPSJyZWQiLGx0eT0zLGx3ZD0yKQ0KIyBuZXcgY29kZQ0KcG9pbnRzKHhbeT49NV0seVt5Pj01XSxwY2g9Myxjb2w9ImRhcmttYWdlbnRhIixjZXg9MykNCnBvaW50cyh4W3k8PS01XSx5W3k8PS01XSxwY2g9Myxjb2w9ImRhcmtibHVlIixjZXg9MykNCg0KYGBgDQpOT3cgaWRlbnRpZnkgdGhlIHN3ZWV0IHNwb3QgaW4gYmx1ZSBhbmQgb3RoZXIgcG9pbnRzIGluIGJsYWNrLg0KDQpgYGB7cn0NCnBsb3QoeCx5LHR5cGU9ImIiLA0KICAgICBjb2w9NixwY2g9MTUsbHR5PTMsY2V4PS43LGx3ZD0yLA0KICAgICApDQphYmxpbmUoaD1jKC01LDUpLGNvbD0icmVkIixsdHk9Mixsd2Q9MikNCnNlZ21lbnRzKHgwPWMoNSwxNSkseTA9YygtNSwtNSkseDE9Yyg1LDE1KSx5MT1jKDUsNSksY29sPSJyZWQiLGx0eT0zLGx3ZD0yKQ0KcG9pbnRzKHhbeT49NV0seVt5Pj01XSxwY2g9Myxjb2w9ImRhcmttYWdlbnRhIixjZXg9MykNCnBvaW50cyh4W3k8PS01XSx5W3k8PS01XSxwY2g9Myxjb2w9ImRhcmtibHVlIixjZXg9MykNCiMgbmV3IGNvZGUgdG8gZmluZCB0aGUgc3dlZXQgc3BvdA0KDQpwb2ludHMoeFsoeD41Jng8PTE1KSYoeT4tNSZ5PDUpXSx5Wyh4PjUmeDw9MTUpJih5Pi01Jnk8NSldLHBjaD0xOSxjb2w9ImJsdWUiKQ0KcG9pbnRzKHhbKHg8NXx4PjE1KSYoeT4tNSZ5PDUpXSx5Wyh4PDV8eD4xNSkmKHk+LTUmeTw1KV0scGNoPTE5LGNvbD0xKQ0KDQoNCmBgYA0KDQpQdXQgYW4gYXJyb3cgdG8gcG9pbnQgdG8gdGhlIHN3ZWV0IHNwb3Q6DQpgYGB7cn0NCnBsb3QoeCx5LHR5cGU9ImIiLA0KICAgICBjb2w9NixwY2g9MTUsbHR5PTMsY2V4PS43LGx3ZD0yLA0KICAgICApDQphYmxpbmUoaD1jKC01LDUpLGNvbD0icmVkIixsdHk9Mixsd2Q9MikNCnNlZ21lbnRzKHgwPWMoNSwxNSkseTA9YygtNSwtNSkseDE9Yyg1LDE1KSx5MT1jKDUsNSksY29sPSJyZWQiLGx0eT0zLGx3ZD0yKQ0KcG9pbnRzKHhbeT49NV0seVt5Pj01XSxwY2g9Myxjb2w9ImRhcmttYWdlbnRhIixjZXg9MykNCnBvaW50cyh4W3k8PS01XSx5W3k8PS01XSxwY2g9Myxjb2w9ImRhcmtibHVlIixjZXg9MykNCnBvaW50cyh4Wyh4PjUmeDw9MTUpJih5Pi01Jnk8NSldLHlbKHg+NSZ4PD0xNSkmKHk+LTUmeTw1KV0scGNoPTE5LGNvbD0iYmx1ZSIpDQpwb2ludHMoeFsoeDw1fHg+MTUpJih5Pi01Jnk8NSldLHlbKHg8NXx4PjE1KSYoeT4tNSZ5PDUpXSxwY2g9MTksY29sPTEpDQojIG5ldyBjb2RlDQoNCmFycm93cyh4MD04LHkwPTE0LHgxPTExLHkxPTIuNSkNCg0KYGBgDQpUaGVuIHB1dCBpbiB0aGUgbGFiZWwNCg0KYGBge3J9DQpwbG90KHgseSx0eXBlPSJiIiwNCiAgICAgY29sPTYscGNoPTE1LGx0eT0zLGNleD0uNyxsd2Q9MiwNCiAgICAgKQ0KYWJsaW5lKGg9YygtNSw1KSxjb2w9InJlZCIsbHR5PTIsbHdkPTIpDQpzZWdtZW50cyh4MD1jKDUsMTUpLHkwPWMoLTUsLTUpLHgxPWMoNSwxNSkseTE9Yyg1LDUpLGNvbD0icmVkIixsdHk9Myxsd2Q9MikNCnBvaW50cyh4W3k+PTVdLHlbeT49NV0scGNoPTMsY29sPSJkYXJrbWFnZW50YSIsY2V4PTMpDQpwb2ludHMoeFt5PD0tNV0seVt5PD0tNV0scGNoPTMsY29sPSJkYXJrYmx1ZSIsY2V4PTMpDQpwb2ludHMoeFsoeD41Jng8PTE1KSYoeT4tNSZ5PDUpXSx5Wyh4PjUmeDw9MTUpJih5Pi01Jnk8NSldLHBjaD0xOSxjb2w9ImJsdWUiKQ0KcG9pbnRzKHhbKHg8NXx4PjE1KSYoeT4tNSZ5PDUpXSx5Wyh4PDV8eD4xNSkmKHk+LTUmeTw1KV0scGNoPTE5LGNvbD0xKQ0KYXJyb3dzKHgwPTgseTA9MTQseDE9MTEseTE9Mi41KQ0KIyBuZXcgY29kZQ0KdGV4dCh4PTgseT0xNSxsYWJlbHM9InN3ZWV0IHNwb3QiKSAgICAgIA0KYGBgDQpUaGVuIHdlIGFkZCBhIGxlZ2VuZCBmdW5jdGlvbg0KDQpgYGB7cn0NCnBsb3QoeCx5LHR5cGU9ImIiLA0KICAgICBjb2w9NixwY2g9MTUsbHR5PTMsY2V4PS43LGx3ZD0yLA0KICAgICApDQphYmxpbmUoaD1jKC01LDUpLGNvbD0icmVkIixsdHk9Mixsd2Q9MikNCnNlZ21lbnRzKHgwPWMoNSwxNSkseTA9YygtNSwtNSkseDE9Yyg1LDE1KSx5MT1jKDUsNSksY29sPSJyZWQiLGx0eT0zLGx3ZD0yKQ0KcG9pbnRzKHhbeT49NV0seVt5Pj01XSxwY2g9Myxjb2w9ImRhcmttYWdlbnRhIixjZXg9MykNCnBvaW50cyh4W3k8PS01XSx5W3k8PS01XSxwY2g9Myxjb2w9ImRhcmtibHVlIixjZXg9MykNCnBvaW50cyh4Wyh4PjUmeDw9MTUpJih5Pi01Jnk8NSldLHlbKHg+NSZ4PD0xNSkmKHk+LTUmeTw1KV0scGNoPTE5LGNvbD0iYmx1ZSIpDQpwb2ludHMoeFsoeDw1fHg+MTUpJih5Pi01Jnk8NSldLHlbKHg8NXx4PjE1KSYoeT4tNSZ5PDUpXSxwY2g9MTksY29sPTEpDQphcnJvd3MoeDA9OCx5MD0xNCx4MT0xMSx5MT0yLjUpDQp0ZXh0KHg9OCx5PTE1LGxhYmVscz0ic3dlZXQgc3BvdCIpICANCiMgbmV3IGNvZGUNCmxlZ2VuZCgiYm90dG9tbGVmdCIsDQogICAgICAgbGVnZW5kPWMoIm92ZXJhbGwgcHJvY2VzcyIsInN3ZWV0Iiwic3RhbmRhcmQiLA0KICAgICAgICAgICAgICAgICJ0b28gYmlnIiwidG9vIHNtYWxsIiwic3dlZXQgeSByYW5nZSIsInN3ZWV0IHggcmFuZ2UiKSwNCiAgICAgICAgICAgICAgICBwY2g9YyhOQSwxOSwxLDQsMyxOQSxOQSksbHR5PWMoNCxOQSxOQSxOQSxOQSwyLDMpLA0KICAgICAgICAgICAgICAgIGNvbD1jKCJibGFjayIsImJsdWUiLCJibGFjayIsImRhcmttYWdlbnRhIiwiZGFya2dyZWVuIiwicmVkIiwicmVkIiksDQogICAgICAgICAgICAgICAgbHdkPWMoMSxOQSxOQSxOQSxOQSwyLDIpLHB0LmNleD1jKE5BLDEsMSwyLDIsTkEsTkEpKQ0KDQpgYGANCg0KPGgyPiA3LjQgVGhlIGdncGxvdDIgUGFja2FnZSA8L2gyPg0KZ2cgc3RhbmRzIGZvciBncmFtbWFyIG9mIGdyYXBoaWNzLiBDcmVhdGVkIGJ5IEhhZGxleSBXaWNraGFtLg0KDQo8aDM+Ny40LjEgQSBRdWNpayBwbG90IHdpdGggcXBsb3Q8L2gzPg0KYGBge3J9DQpsaWJyYXJ5KCJnZ3Bsb3QyIikNCmZvbw0KYmFyDQpxcGxvdChmb28sYmFyKQ0KYGBgDQpBZGQgdGl0bGUgYW5kIGF4aXMgbGFiZWxzIA0KYGBge3J9DQpxcGxvdChmb28sYmFyLG1haW49Ik15IGxvdmVseSBxcGxvdCIseGxhYj0ieCBheGlzIGxhYmVsIiwgeWxhYj0iWSBheGlzIGxhYmVsIikNCmBgYA0KT25lIGRpZmZlcmVuY2UgYmV0d2VlbiBwbG90IGFuZCBxcGxvdCBpcyB0aGF0IGluIHFwbG90IHRoZSBncmFwaCBpcyBhbiBvYmplY3QNCmBgYHtyfQ0KYmF6PC1wbG90KGZvbyxiYXIpDQpiYXoNCnF1eDwtcXBsb3QoZm9vLGJhcikNCnF1eA0KYGBgDQoNCg0KPGgzPjcuNC4yIFNldHRpbmcgQXBwZWFyYW5jZSBDb25zdGFudHMgd2l0aCBHZW9tczwvaDM+DQpTaW5jZSB0aGUgcXBsb3Qgb3V0cHV0cyB0byBhbiBvYmplY3QsIHlvdSBjYW4gd29yayB3aXRoIGFuZCBhbHRlciB0aGUgb2JqZWN0IGRpcmVjdGx5DQpyYXRoZXIgdGhhbiB1c2luZyBhIGxvbmcgbGlzdCBvZiBhcmd1bWVudHMgb3Igc2Vjb25kYXJ5IGZ1bmN0aW9ucyBleGVjdXRlZCBzcGVyYXRlbHkuDQoNCmBgYHtyfQ0Kd2xzPXFwbG90KGZvbyxiYXIsZ2VvbT0iYmxhbmsiKStnZW9tX3BvaW50KCkrIGdlb21fbGluZSgpDQp3bHM9d2xzK2dlb21fcG9pbnQoc2l6ZT0zLHNoYXBlPTYsY29sb3I9ImJsdWUiKQ0Kd2xzDQp3bHM9d2xzK2dlb21fbGluZShjb2xvcj0icmVkIixsaW5ldHlwZT0yKQ0Kd2xzDQpgYGANCmBgYHtyfQ0Kd2xzPXFwbG90KGZvbyxiYXIsZ2VvbT0iYmxhbmsiKStnZW9tX3BvaW50KCkrIGdlb21fbGluZSgpDQp3bHM9d2xzK2dlb21fcG9pbnQoc2hhcGU9NyxzaXplPTQpDQp3bHMNCmBgYA0KDQo8aDM+Ny40LjMgQWV0aGV0aWMgTWFwcGluZyB3aXRoIEdlb21zdDwvaDM+DQpXb3JraW5nIHdpdGggZmFjdG9ycywgaW4gZ2dwbG90MiwgZmFjdG9ycyBhcmUgdHJlYXRlZCBhcyB2YXJpYWJsZXMgYW5kIGNhbiBhdXRvbWF0aWNhbGx5IGFwcGx5IHBhcnRpY3VsYXIgc3R5bGVzIHRvIGRpZmZlcmVudCBjYXRlZ29yaWVzLg0KDQpMZXQgdXMgY3JlYXRlIHRoZSBjYXRlZ29yaWVzIHRvIGhvbGQgdGhlIHN0YW5kYXJkLCBzd2VldCwgdG9vIHNtYWxsLCBvciB0b28gYmlnLg0KDQpgYGB7cn0NCiMgcmV2aWV3IHRoZSBkYXRhIGluIHggYW5kIHkNCngNCnkNCiMgDQpwdHlwZTwtIHJlcChOQSwgbGVuZ3RoKHg9eCkpDQpwdHlwZVt5Pj01XSA8LSJ0b28gYmlnIg0KcHR5cGVbeTw9LTVdPC0idG9vIHNtYWxsIg0KcHR5cGVbKHg+NSZ4PD0xNSkmKHk+LTUmeTw1KV08LSJzd2VldCINCnB0eXBlWyh4PDV8eD4xNSkmKHk+LTUmeTw1KV08LSJzdGFuZGFyZCINCnB0eXBlPC1mYWN0b3IoeD1wdHlwZSkNCnB0eXBlDQpgYGANCk5PdyBxcGxvdCB0aGlzDQpgYGB7cn0NCnFwbG90KHgseSxjb2xvcj1wdHlwZSxzaGFwZT1wdHlwZSkNCmBgYA0KTm93IGxldHMgbWFrZSBpdCB2aXN1YWxseSBiZXR0ZXINCmBgYHtyfQ0KcXBsb3QoeCx5LGNvbG9yPXB0eXBlLHNoYXBlPXB0eXBlKSsNCiAgZ2VvbV9wb2ludChzaXplPTQpKw0KICBnZW9tX2xpbmUobWFwcGluZz1hZXMoZ3JvdXA9MSksY29sb3I9ImJsYWNrIixsdHk9MikrDQogIGdlb21faGxpbmUobWFwcGluZz1hZXMoeWludGVyY2VwdD1jKC01LDUpKSxjb2xvcj0icmVkIikrDQogIGdlb21fc2VnbWVudChtYXBwaW5nPWFlcyh4PTUseT0tNSx4ZW5kPTUseWVuZD01KSxjb2xvcj0icmVkIixsdHk9MykrDQogIGdlb21fc2VnbWVudChtYXBwaW5nPWFlcyh4PTE1LHk9LTUseGVuZD0xNSx5ZW5kPTUpLGNvbG9yPSJyZWQiLGx0eT0zKQ0KDQpgYGANCg0K