Slides for this and other Data Science courses may be found at github https://github.com/DataScienceSpecialization/courses/. If you care to use them, they must be downloaded as a zip file and viewed locally. This lesson corresponds to 04_ExploratoryAnalysis/PlottingSystems.


In this lesson, we’ll give you a brief overview of the three plotting systems in R, their differences, strengths, and weaknesses. We’ll only cover the basics here to give you a general idea of the systems and in later lessons we’ll cover each system in more depth.


Base Plotting System

The first plotting system is the Base Plotting System which comes with R. It’s the oldest system which uses a simple “Artist’s palette” model. What this means is that you start with a blank canvas and build your plot up from there, step by step.

Usually you start with a plot function (or something similar), then you use annotation functions to add to or modify your plot. R provides many annotating functions such as text, lines, points, and axis. R provides documentation for each of these. They all add to an already existing plot.

What do you think is a disadvantage of the Base Plotting System?

  1. A complicated plot is a series of simple R commands
  2. It mirrors how we think of building plots and analyzing data
  3. It’s intuitive and exploratory
  4. You can’t go back once a plot has started

Yes! The base system is very intuitive and easy to use when you’re starting to do exploratory graphing and looking for a research direction. You can’t go backwards, though, say, if you need to readjust margins or fix a misspelled a caption. A finished plot will be a series of R commands, so it’s difficult to translate a finished plot into a different system.

We’ve loaded the dataset cars for you to demonstrate how easy it is to plot. First, use the R command head with cars as an argument to see what the data looks like.

head(cars)

So the dataset collates the speeds and distances needed to stop for 50 cars. This data was recorded in the 1920’s.

We’ll use the R command with which takes two arguments. The first specifies a dataset or environment in which to run the second argument, an R expression. This will save us a bit of typing. Try running the command with now using cars as the first argument and a call to plot as the second. The call to plot will take two arguments, speed and dist. Please specify them in that order.

with(cars, plot(speed, dist))

Simple, right? You can see the relationship between the two variables, speed and distance. The first variable is plotted along the x-axis and the second along the y-axis.

Now we’ll show you what the function text does. Run the command text with three arguments. The first two, x and y coordinates, specify the placement of the third argument, the text to be added to the plot. Let the first argument be mean(cars$speed), the second max(cars$dist), and the third the string "SWIRL rules!". Try it now.

with(cars, plot(speed, dist))
text(mean(cars$speed), max(cars$dist), "SWIRL rules!")

Ain’t it the truth?


Lattice System

Now we’ll move on to the second plotting system, the Lattice System which comes in the package of the same name. Unlike the Base System, lattice plots are created with a single function call such as xyplot or bwplot. Margins and spacing are set automatically because the entire plot is specified at once.

The lattice system is most useful for conditioning types of plots which display how y changes with x across levels of z. The variable z might be a categorical variable of your data. This system is also good for putting many plots on a screen at once.

The lattice system has several disadvantages. First, it is sometimes awkward to specify an entire plot in a single function call. Annotating a plot may not be especially intuitive. Second, using panel functions and subscripts is somewhat difficult and requires preparation. Finally, you cannot “add” to the plot once it is created as you can with the base system.

As before, we’ve loaded some data for you in the variable state. This data comes with the lattice package and it concerns various characteristics of the 50 states in the U.S. Use the R command head to see the first few entries of state now.

head(state)

As you can see state holds 9 pieces of information for each of the 50 states. The last variable, region, specifies a category for each state. Run the R command table with the argument state$region to see how many categories there are and how many states are in each.

table(state$region)

    Northeast         South North Central          West 
            9            16            12            13 

So there are 4 categories and the 50 states are sorted into them appropriately. Let’s use the lattice command ‘xyplot’ to see how life expectancy varies with income in each of the four regions.

To do this we’ll give xyplot 3 arguments. The first is the most complicated. It is this R formula, Life.Exp ~ Income | region, which indicates we’re plotting life expectancy as it depends on income for each region. The second argument, data, is set equal to state. This allows us to use Life.Exp and Income in the formula instead of specifying the dataset state for each term (as in state$Income). The third argument, layout, is set equal to the two-long vector c(4,1). Run xyplot now with these three arguments.

xyplot(Life.Exp ~ Income | region, data = state, layout = c(4, 1))

We see the data for each of the 4 regions plotted in one row. Based on this plot, which region of the U.S. seems to have the shortest life expectancy?

1: North Central 2: West 3: Northeast 4: South

Just for fun rerun the xyplot and this time set layout to the vector c(2,2). To save typing use the up arrow to recover the previous xyplot command.

xyplot(Life.Exp ~ Income | region, data = state, layout = c(2, 2))

See how the plot changed? No need for you to worry about margins or labels. The package took care of all that for you.


ggplot2

Now for the last plotting system, ggplot2, which is a hybrid of the base and lattice systems. It automatically deals with spacing, text, titles (as Lattice does) but also allows you to annotate by “adding” to a plot (as Base does), so it’s the best of both worlds.

Although ggplot2 bears a superficial similarity to lattice, it’s generally easier and more intuitive to use. Its default mode makes many choices for you but you can still customize a lot. The package is based on a “grammar of graphics” (hence the gg in the name), so you can control the aesthetics of your plots. For instance, you can plot conditioning graphs and panel plots as we did in the lattice example.

We’ll see an example now of ggplot2 with a simple (single) command. As before, we’ve loaded a dataset for you from the ggplot2 package. This mpg data holds fuel economy data between 1999 and 2008 for 38 different models of cars. Run head with mpg as an argument so you get an idea of what the data looks like.

head(mpg)

Looks complicated. Run dim with the argument mpg to see how big the dataset is.

dim(mpg)
[1] 234  11

Holy cow! That’s a lot of information for just 38 models of cars. Run the R command table with the argument mpg$model. This will tell us how many models of cars we’re dealing with.

table(mpg$model)

           4runner 4wd                     a4             a4 quattro             a6 quattro 
                     6                      7                      8                      3 
                altima     c1500 suburban 2wd                  camry           camry solara 
                     6                      5                      7                      7 
           caravan 2wd                  civic                corolla               corvette 
                    11                      9                      5                      5 
     dakota pickup 4wd            durango 4wd         expedition 2wd           explorer 4wd 
                     9                      7                      3                      6 
       f150 pickup 4wd           forester awd     grand cherokee 4wd             grand prix 
                     7                      6                      8                      5 
                   gti            impreza awd                  jetta        k1500 tahoe 4wd 
                     5                      8                      9                      4 
land cruiser wagon 4wd                 malibu                 maxima        mountaineer 4wd 
                     2                      5                      3                      4 
               mustang          navigator 2wd             new beetle                 passat 
                     9                      3                      6                      7 
        pathfinder 4wd    ram 1500 pickup 4wd            range rover                 sonata 
                     4                     10                      4                      7 
               tiburon      toyota tacoma 4wd 
                     7                      7 

Oh, there are 38 models. We’re interested in the effect engine displacement (displ) has on highway gas mileage (hwy), so we’ll use the ggplot2 command qplot to display this relationship. Run qplot now with three arguments. The first two are the variables displ and hwy we want to plot, and the third is the argument data set equal to mpg. As before, this allows us to avoid using the mpg$variable notation for the first two arguments.

qplot(displ, hwy, data = mpg)

Not surprisingly we see that the bigger the engine displacement the lower the gas mileage.



Let’s review!

Which R plotting system is based on an artist’s palette?

  1. ggplot2
  2. base
  3. Winsor&Newton
  4. lattice

Which R plotting system does NOT allow you to annotate plots with separate calls?

  1. base
  2. ggplot2
  3. lattice
  4. Winsor&Newton

Which R plotting system combines the best features of the other two?

  1. Winsor&Newton
  2. lattice
  3. ggplot2
  4. base

Which R plotting system uses a graphics grammar?

  1. Winsor&Newton
  2. base
  3. ggplot2
  4. lattice

Which R plotting system forces you to make your entire plot with one call?

  1. Winsor&Newton
  2. lattice
  3. base
  4. ggplot2

Which of the following sells high quality artists’ brushes?

  1. base
  2. ggplot2
  3. lattice
  4. Winsor&Newton

Congrats! You’ve concluded this plotting lesson. We hope you didn’t find it plodding.




END



LS0tDQp0aXRsZTogIlBsb3R0aW5nIFN5c3RlbXMiDQpzdWJ0aXRsZTogIlN3aXJsIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMgTGVzc29uIDQiDQphdXRob3I6ICJSb2dlciBELiBQZW5nIChjb21waWxlZCBhbmQgZWRpdGVkIGJ5OiBOdW5ubyBOdWdyb2hvKSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCjwvYnI+DQoNCipTbGlkZXMgZm9yIHRoaXMgYW5kIG90aGVyIERhdGEgU2NpZW5jZSBjb3Vyc2VzIG1heSBiZSBmb3VuZCBhdCBnaXRodWIgaHR0cHM6Ly9naXRodWIuY29tL0RhdGFTY2llbmNlU3BlY2lhbGl6YXRpb24vY291cnNlcy8uIElmIHlvdSBjYXJlIHRvIHVzZSB0aGVtLCB0aGV5IG11c3QgYmUgZG93bmxvYWRlZCBhcyBhIHppcCBmaWxlIGFuZCB2aWV3ZWQgbG9jYWxseS4gVGhpcyBsZXNzb24gY29ycmVzcG9uZHMgdG8gMDRfRXhwbG9yYXRvcnlBbmFseXNpcy9QbG90dGluZ1N5c3RlbXMuKg0KDQo8L2JyPg0KDQpJbiB0aGlzIGxlc3Nvbiwgd2UnbGwgZ2l2ZSB5b3UgYSBicmllZiBvdmVydmlldyBvZiB0aGUgdGhyZWUgcGxvdHRpbmcgc3lzdGVtcyBpbiBSLCB0aGVpciBkaWZmZXJlbmNlcywgc3RyZW5ndGhzLCBhbmQgd2Vha25lc3Nlcy4gV2UnbGwgb25seSBjb3ZlciB0aGUgYmFzaWNzIGhlcmUgdG8gZ2l2ZSB5b3UgYSBnZW5lcmFsIGlkZWEgb2YgdGhlIHN5c3RlbXMgYW5kIGluIGxhdGVyIGxlc3NvbnMgd2UnbGwgY292ZXIgZWFjaCBzeXN0ZW0gaW4gbW9yZSBkZXB0aC4NCg0KPC9icj4NCg0KPGgzPkJhc2UgUGxvdHRpbmcgU3lzdGVtPC9oMz4NCg0KVGhlIGZpcnN0IHBsb3R0aW5nIHN5c3RlbSBpcyB0aGUgKipCYXNlIFBsb3R0aW5nIFN5c3RlbSoqIHdoaWNoIGNvbWVzIHdpdGggUi4gSXQncyB0aGUgb2xkZXN0IHN5c3RlbSB3aGljaCB1c2VzIGEgc2ltcGxlICJBcnRpc3QncyBwYWxldHRlIiBtb2RlbC4gV2hhdCB0aGlzIG1lYW5zIGlzIHRoYXQgeW91IHN0YXJ0IHdpdGggYSBibGFuayBjYW52YXMgYW5kIGJ1aWxkIHlvdXIgcGxvdCB1cCBmcm9tIHRoZXJlLCBzdGVwIGJ5IHN0ZXAuDQoNClVzdWFsbHkgeW91IHN0YXJ0IHdpdGggYSBgcGxvdGAgZnVuY3Rpb24gKG9yIHNvbWV0aGluZyBzaW1pbGFyKSwgdGhlbiB5b3UgdXNlIGFubm90YXRpb24gZnVuY3Rpb25zIHRvIGFkZCB0byBvciBtb2RpZnkgeW91ciBwbG90LiBSIHByb3ZpZGVzIG1hbnkgYW5ub3RhdGluZyBmdW5jdGlvbnMgc3VjaCBhcyB0ZXh0LCBsaW5lcywgcG9pbnRzLCBhbmQgYXhpcy4gUiBwcm92aWRlcyBkb2N1bWVudGF0aW9uIGZvciBlYWNoIG9mIHRoZXNlLiBUaGV5IGFsbCBhZGQgdG8gYW4gYWxyZWFkeSBleGlzdGluZyBwbG90Lg0KDQpXaGF0IGRvIHlvdSB0aGluayBpcyBhIGRpc2FkdmFudGFnZSBvZiB0aGUgQmFzZSBQbG90dGluZyBTeXN0ZW0/DQoNCjEuIEEgY29tcGxpY2F0ZWQgcGxvdCBpcyBhIHNlcmllcyBvZiBzaW1wbGUgUiBjb21tYW5kcw0KMi4gSXQgbWlycm9ycyBob3cgd2UgdGhpbmsgb2YgYnVpbGRpbmcgcGxvdHMgYW5kIGFuYWx5emluZyBkYXRhDQozLiBJdCdzIGludHVpdGl2ZSBhbmQgZXhwbG9yYXRvcnkNCjQuICoqWW91IGNhbid0IGdvIGJhY2sgb25jZSBhIHBsb3QgaGFzIHN0YXJ0ZWQqKg0KDQpZZXMhIFRoZSBiYXNlIHN5c3RlbSBpcyB2ZXJ5IGludHVpdGl2ZSBhbmQgZWFzeSB0byB1c2Ugd2hlbiB5b3UncmUgc3RhcnRpbmcgdG8gZG8gZXhwbG9yYXRvcnkgZ3JhcGhpbmcgYW5kIGxvb2tpbmcgZm9yIGEgcmVzZWFyY2ggZGlyZWN0aW9uLiBZb3UgY2FuJ3QgZ28gYmFja3dhcmRzLCB0aG91Z2gsIHNheSwgaWYgeW91IG5lZWQgdG8gcmVhZGp1c3QgbWFyZ2lucyBvciBmaXggYSBtaXNzcGVsbGVkIGEgY2FwdGlvbi4gQSBmaW5pc2hlZCBwbG90IHdpbGwgYmUgYSBzZXJpZXMgb2YgUiBjb21tYW5kcywgc28gaXQncyBkaWZmaWN1bHQgdG8gdHJhbnNsYXRlIGEgZmluaXNoZWQgcGxvdCBpbnRvIGEgZGlmZmVyZW50IHN5c3RlbS4NCg0KV2UndmUgbG9hZGVkIHRoZSBkYXRhc2V0IGBjYXJzYCBmb3IgeW91IHRvIGRlbW9uc3RyYXRlIGhvdyBlYXN5IGl0IGlzIHRvIHBsb3QuIEZpcnN0LCB1c2UgdGhlIFIgY29tbWFuZCBgaGVhZGAgd2l0aCBgY2Fyc2AgYXMgYW4gYXJndW1lbnQgdG8gc2VlIHdoYXQgdGhlIGRhdGEgbG9va3MgbGlrZS4NCg0KYGBge3J9DQpoZWFkKGNhcnMpDQpgYGANCg0KU28gdGhlIGRhdGFzZXQgY29sbGF0ZXMgdGhlIHNwZWVkcyBhbmQgZGlzdGFuY2VzIG5lZWRlZCB0byBzdG9wIGZvciA1MCBjYXJzLiBUaGlzIGRhdGEgd2FzIHJlY29yZGVkIGluIHRoZSAxOTIwJ3MuDQoNCldlJ2xsIHVzZSB0aGUgUiBjb21tYW5kIGB3aXRoYCB3aGljaCB0YWtlcyB0d28gYXJndW1lbnRzLiBUaGUgZmlyc3Qgc3BlY2lmaWVzIGEgZGF0YXNldCBvciBlbnZpcm9ubWVudCBpbiB3aGljaCB0byBydW4gdGhlIHNlY29uZCBhcmd1bWVudCwgYW4gUiBleHByZXNzaW9uLiBUaGlzIHdpbGwgc2F2ZSB1cyBhIGJpdCBvZiB0eXBpbmcuIFRyeSBydW5uaW5nIHRoZSBjb21tYW5kIGB3aXRoYCBub3cgdXNpbmcgYGNhcnNgIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBhbmQgYSBjYWxsIHRvIGBwbG90YCBhcyB0aGUgc2Vjb25kLiBUaGUgY2FsbCB0byBgcGxvdGAgd2lsbCB0YWtlIHR3byBhcmd1bWVudHMsIGBzcGVlZGAgYW5kIGBkaXN0YC4gUGxlYXNlIHNwZWNpZnkgdGhlbSBpbiB0aGF0IG9yZGVyLg0KDQpgYGB7cn0NCndpdGgoY2FycywgcGxvdChzcGVlZCwgZGlzdCkpDQpgYGANCg0KU2ltcGxlLCByaWdodD8gWW91IGNhbiBzZWUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzLCBgc3BlZWRgIGFuZCBgZGlzdGFuY2VgLiBUaGUgZmlyc3QgdmFyaWFibGUgaXMgcGxvdHRlZCBhbG9uZyB0aGUgeC1heGlzIGFuZCB0aGUgc2Vjb25kIGFsb25nIHRoZSB5LWF4aXMuDQoNCk5vdyB3ZSdsbCBzaG93IHlvdSB3aGF0IHRoZSBmdW5jdGlvbiBgdGV4dGAgZG9lcy4gUnVuIHRoZSBjb21tYW5kIGB0ZXh0YCB3aXRoIHRocmVlIGFyZ3VtZW50cy4gVGhlIGZpcnN0IHR3bywgeCBhbmQgeSBjb29yZGluYXRlcywgc3BlY2lmeSB0aGUgcGxhY2VtZW50IG9mIHRoZSB0aGlyZCBhcmd1bWVudCwgdGhlIHRleHQgdG8gYmUgYWRkZWQgdG8gdGhlIHBsb3QuIExldCB0aGUgZmlyc3QgYXJndW1lbnQgYmUgYG1lYW4oY2FycyRzcGVlZClgLCB0aGUgc2Vjb25kIGBtYXgoY2FycyRkaXN0KWAsIGFuZCB0aGUgdGhpcmQgdGhlIHN0cmluZyBgIlNXSVJMIHJ1bGVzISJgLiBUcnkgaXQgbm93Lg0KDQpgYGB7cn0NCndpdGgoY2FycywgcGxvdChzcGVlZCwgZGlzdCkpDQp0ZXh0KG1lYW4oY2FycyRzcGVlZCksIG1heChjYXJzJGRpc3QpLCAiU1dJUkwgcnVsZXMhIikNCmBgYA0KDQpBaW4ndCBpdCB0aGUgdHJ1dGg/DQoNCjwvYnI+DQoNCjxoMz5MYXR0aWNlIFN5c3RlbTwvaDM+DQoNCk5vdyB3ZSdsbCBtb3ZlIG9uIHRvIHRoZSBzZWNvbmQgcGxvdHRpbmcgc3lzdGVtLCB0aGUgKipMYXR0aWNlIFN5c3RlbSoqIHdoaWNoIGNvbWVzIGluIHRoZSBwYWNrYWdlIG9mIHRoZSBzYW1lIG5hbWUuIFVubGlrZSB0aGUgQmFzZSBTeXN0ZW0sIGxhdHRpY2UgcGxvdHMgYXJlIGNyZWF0ZWQgd2l0aCBhIHNpbmdsZSBmdW5jdGlvbiBjYWxsIHN1Y2ggYXMgYHh5cGxvdGAgb3IgYGJ3cGxvdGAuIE1hcmdpbnMgYW5kIHNwYWNpbmcgYXJlIHNldCBhdXRvbWF0aWNhbGx5IGJlY2F1c2UgdGhlIGVudGlyZSBwbG90IGlzIHNwZWNpZmllZCBhdCBvbmNlLg0KDQpUaGUgbGF0dGljZSBzeXN0ZW0gaXMgbW9zdCB1c2VmdWwgZm9yIGNvbmRpdGlvbmluZyB0eXBlcyBvZiBwbG90cyB3aGljaCBkaXNwbGF5IGhvdyB5IGNoYW5nZXMgd2l0aCB4IGFjcm9zcyBsZXZlbHMgb2Ygei4gVGhlIHZhcmlhYmxlIHogbWlnaHQgYmUgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBvZiB5b3VyIGRhdGEuIFRoaXMgc3lzdGVtIGlzIGFsc28gZ29vZCBmb3IgcHV0dGluZyBtYW55IHBsb3RzIG9uIGEgc2NyZWVuIGF0IG9uY2UuDQoNClRoZSBsYXR0aWNlIHN5c3RlbSBoYXMgc2V2ZXJhbCBkaXNhZHZhbnRhZ2VzLiBGaXJzdCwgaXQgaXMgc29tZXRpbWVzIGF3a3dhcmQgdG8gc3BlY2lmeSBhbiBlbnRpcmUgcGxvdCBpbiBhIHNpbmdsZSBmdW5jdGlvbiBjYWxsLiBBbm5vdGF0aW5nIGEgcGxvdCBtYXkgbm90IGJlIGVzcGVjaWFsbHkgaW50dWl0aXZlLiBTZWNvbmQsIHVzaW5nIHBhbmVsIGZ1bmN0aW9ucyBhbmQgc3Vic2NyaXB0cyBpcyBzb21ld2hhdCBkaWZmaWN1bHQgYW5kIHJlcXVpcmVzIHByZXBhcmF0aW9uLiBGaW5hbGx5LCB5b3UgY2Fubm90ICJhZGQiIHRvIHRoZSBwbG90IG9uY2UgaXQgaXMgY3JlYXRlZCBhcyB5b3UgY2FuIHdpdGggdGhlIGJhc2Ugc3lzdGVtLg0KDQpBcyBiZWZvcmUsIHdlJ3ZlIGxvYWRlZCBzb21lIGRhdGEgZm9yIHlvdSBpbiB0aGUgdmFyaWFibGUgYHN0YXRlYC4gVGhpcyBkYXRhIGNvbWVzIHdpdGggdGhlIGxhdHRpY2UgcGFja2FnZSBhbmQgaXQgY29uY2VybnMgdmFyaW91cyBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIDUwIHN0YXRlcyBpbiB0aGUgVS5TLiBVc2UgdGhlIFIgY29tbWFuZCBgaGVhZGAgdG8gc2VlIHRoZSBmaXJzdCBmZXcgZW50cmllcyBvZiBzdGF0ZSBub3cuDQoNCmBgYHtyfQ0KaGVhZChzdGF0ZSkNCmBgYA0KDQpBcyB5b3UgY2FuIHNlZSBgc3RhdGVgIGhvbGRzIDkgcGllY2VzIG9mIGluZm9ybWF0aW9uIGZvciBlYWNoIG9mIHRoZSA1MCBzdGF0ZXMuIFRoZSBsYXN0IHZhcmlhYmxlLCBgcmVnaW9uYCwgc3BlY2lmaWVzIGEgY2F0ZWdvcnkgZm9yIGVhY2ggc3RhdGUuIFJ1biB0aGUgUiBjb21tYW5kIGB0YWJsZWAgd2l0aCB0aGUgYXJndW1lbnQgYHN0YXRlJHJlZ2lvbmAgdG8gc2VlIGhvdyBtYW55IGNhdGVnb3JpZXMgdGhlcmUgYXJlIGFuZCBob3cgbWFueSBzdGF0ZXMgYXJlIGluIGVhY2guDQoNCmBgYHtyfQ0KdGFibGUoc3RhdGUkcmVnaW9uKQ0KYGBgDQoNClNvIHRoZXJlIGFyZSA0IGNhdGVnb3JpZXMgYW5kIHRoZSA1MCBzdGF0ZXMgYXJlIHNvcnRlZCBpbnRvIHRoZW0gYXBwcm9wcmlhdGVseS4gTGV0J3MgdXNlIHRoZSBsYXR0aWNlIGNvbW1hbmQgJ3h5cGxvdCcgdG8gc2VlIGhvdyBsaWZlIGV4cGVjdGFuY3kgdmFyaWVzIHdpdGggaW5jb21lIGluIGVhY2ggb2YgdGhlIGZvdXIgcmVnaW9ucy4NCg0KVG8gZG8gdGhpcyB3ZSdsbCBnaXZlIGB4eXBsb3RgIDMgYXJndW1lbnRzLiBUaGUgZmlyc3QgaXMgdGhlIG1vc3QgY29tcGxpY2F0ZWQuIEl0IGlzIHRoaXMgUiBmb3JtdWxhLCBgTGlmZS5FeHAgfiBJbmNvbWUgfCByZWdpb25gLCB3aGljaCBpbmRpY2F0ZXMgd2UncmUgcGxvdHRpbmcgbGlmZSBleHBlY3RhbmN5IGFzIGl0IGRlcGVuZHMgb24gaW5jb21lIGZvciBlYWNoIHJlZ2lvbi4gVGhlIHNlY29uZCBhcmd1bWVudCwgYGRhdGFgLCBpcyBzZXQgZXF1YWwgdG8gYHN0YXRlYC4gVGhpcyBhbGxvd3MgdXMgdG8gdXNlIGBMaWZlLkV4cGAgYW5kIGBJbmNvbWVgIGluIHRoZSBmb3JtdWxhIGluc3RlYWQgb2Ygc3BlY2lmeWluZyB0aGUgZGF0YXNldCBgc3RhdGVgIGZvciBlYWNoIHRlcm0gKGFzIGluIGBzdGF0ZSRJbmNvbWVgKS4gVGhlIHRoaXJkIGFyZ3VtZW50LCBgbGF5b3V0YCwgaXMgc2V0IGVxdWFsIHRvIHRoZSB0d28tbG9uZyB2ZWN0b3IgYGMoNCwxKWAuIFJ1biBgeHlwbG90YCBub3cgd2l0aCB0aGVzZSB0aHJlZSBhcmd1bWVudHMuDQoNCmBgYHtyfQ0KeHlwbG90KExpZmUuRXhwIH4gSW5jb21lIHwgcmVnaW9uLCBkYXRhID0gc3RhdGUsIGxheW91dCA9IGMoNCwgMSkpDQpgYGANCg0KV2Ugc2VlIHRoZSBkYXRhIGZvciBlYWNoIG9mIHRoZSA0IHJlZ2lvbnMgcGxvdHRlZCBpbiBvbmUgcm93LiBCYXNlZCBvbiB0aGlzIHBsb3QsIHdoaWNoIHJlZ2lvbiBvZiB0aGUgVS5TLiBzZWVtcyB0byBoYXZlIHRoZSBzaG9ydGVzdCBsaWZlIGV4cGVjdGFuY3k/DQoNCjE6IE5vcnRoIENlbnRyYWwNCjI6IFdlc3QNCjM6IE5vcnRoZWFzdA0KKio0OiBTb3V0aCoqDQoNCkp1c3QgZm9yIGZ1biByZXJ1biB0aGUgYHh5cGxvdGAgYW5kIHRoaXMgdGltZSBzZXQgYGxheW91dGAgdG8gdGhlIHZlY3RvciBgYygyLDIpYC4gVG8gc2F2ZSB0eXBpbmcgdXNlIHRoZSB1cCBhcnJvdyB0byByZWNvdmVyIHRoZSBwcmV2aW91cyBgeHlwbG90YCBjb21tYW5kLg0KDQpgYGB7cn0NCnh5cGxvdChMaWZlLkV4cCB+IEluY29tZSB8IHJlZ2lvbiwgZGF0YSA9IHN0YXRlLCBsYXlvdXQgPSBjKDIsIDIpKQ0KYGBgDQoNClNlZSBob3cgdGhlIHBsb3QgY2hhbmdlZD8gTm8gbmVlZCBmb3IgeW91IHRvIHdvcnJ5IGFib3V0IG1hcmdpbnMgb3IgbGFiZWxzLiBUaGUgcGFja2FnZSB0b29rIGNhcmUgb2YgYWxsIHRoYXQgZm9yIHlvdS4NCg0KPC9icj4NCg0KPGgzPmdncGxvdDI8L2gzPg0KDQpOb3cgZm9yIHRoZSBsYXN0IHBsb3R0aW5nIHN5c3RlbSwgKipnZ3Bsb3QyKiosIHdoaWNoIGlzIGEgaHlicmlkIG9mIHRoZSBiYXNlIGFuZCBsYXR0aWNlIHN5c3RlbXMuIEl0IGF1dG9tYXRpY2FsbHkgZGVhbHMgd2l0aCBzcGFjaW5nLCB0ZXh0LCB0aXRsZXMgKGFzIExhdHRpY2UgZG9lcykgYnV0IGFsc28gYWxsb3dzIHlvdSB0byBhbm5vdGF0ZSBieSAiYWRkaW5nIiB0byBhIHBsb3QgKGFzIEJhc2UgZG9lcyksIHNvIGl0J3MgdGhlIGJlc3Qgb2YgYm90aCB3b3JsZHMuDQoNCkFsdGhvdWdoIGdncGxvdDIgYmVhcnMgYSBzdXBlcmZpY2lhbCBzaW1pbGFyaXR5IHRvIGxhdHRpY2UsIGl0J3MgZ2VuZXJhbGx5IGVhc2llciBhbmQgbW9yZSBpbnR1aXRpdmUgdG8gdXNlLiBJdHMgZGVmYXVsdCBtb2RlIG1ha2VzIG1hbnkgY2hvaWNlcyBmb3IgeW91IGJ1dCB5b3UgY2FuIHN0aWxsIGN1c3RvbWl6ZSBhIGxvdC4gVGhlIHBhY2thZ2UgaXMgYmFzZWQgb24gYSAiZ3JhbW1hciBvZiBncmFwaGljcyIgKGhlbmNlIHRoZSBnZyBpbiB0aGUgbmFtZSksIHNvIHlvdSBjYW4gY29udHJvbCB0aGUgYWVzdGhldGljcyBvZiB5b3VyIHBsb3RzLiBGb3IgaW5zdGFuY2UsIHlvdSBjYW4gcGxvdCBjb25kaXRpb25pbmcgZ3JhcGhzIGFuZCBwYW5lbCBwbG90cyBhcyB3ZSBkaWQgaW4gdGhlIGxhdHRpY2UgZXhhbXBsZS4NCg0KV2UnbGwgc2VlIGFuIGV4YW1wbGUgbm93IG9mIGdncGxvdDIgd2l0aCBhIHNpbXBsZSAoc2luZ2xlKSBjb21tYW5kLiBBcyBiZWZvcmUsIHdlJ3ZlIGxvYWRlZCBhIGRhdGFzZXQgZm9yIHlvdSBmcm9tIHRoZSBnZ3Bsb3QyIHBhY2thZ2UuIFRoaXMgYG1wZ2AgZGF0YSBob2xkcyBmdWVsIGVjb25vbXkgZGF0YSBiZXR3ZWVuIDE5OTkgYW5kIDIwMDggZm9yIDM4IGRpZmZlcmVudCBtb2RlbHMgb2YgY2Fycy4gUnVuIGBoZWFkYCB3aXRoIGBtcGdgIGFzIGFuIGFyZ3VtZW50IHNvIHlvdSBnZXQgYW4gaWRlYSBvZiB3aGF0IHRoZSBkYXRhIGxvb2tzIGxpa2UuDQoNCmBgYHtyfQ0KaGVhZChtcGcpDQpgYGANCg0KTG9va3MgY29tcGxpY2F0ZWQuIFJ1biBgZGltYCB3aXRoIHRoZSBhcmd1bWVudCBgbXBnYCB0byBzZWUgaG93IGJpZyB0aGUgZGF0YXNldCBpcy4NCg0KYGBge3J9DQpkaW0obXBnKQ0KYGBgDQoNCkhvbHkgY293ISBUaGF0J3MgYSBsb3Qgb2YgaW5mb3JtYXRpb24gZm9yIGp1c3QgMzggbW9kZWxzIG9mIGNhcnMuIFJ1biB0aGUgUiBjb21tYW5kIGB0YWJsZWAgd2l0aCB0aGUgYXJndW1lbnQgYG1wZyRtb2RlbGAuIFRoaXMgd2lsbCB0ZWxsIHVzIGhvdyBtYW55IG1vZGVscyBvZiBjYXJzIHdlJ3JlIGRlYWxpbmcgd2l0aC4NCg0KYGBge3J9DQp0YWJsZShtcGckbW9kZWwpDQpgYGANCg0KT2gsIHRoZXJlIGFyZSAzOCBtb2RlbHMuIFdlJ3JlIGludGVyZXN0ZWQgaW4gdGhlIGVmZmVjdCBlbmdpbmUgZGlzcGxhY2VtZW50IChgZGlzcGxgKSBoYXMgb24gaGlnaHdheSBnYXMgbWlsZWFnZSAoYGh3eWApLCBzbyB3ZSdsbCB1c2UgdGhlIGdncGxvdDIgY29tbWFuZCBgcXBsb3RgIHRvIGRpc3BsYXkgdGhpcyByZWxhdGlvbnNoaXAuIFJ1biBgcXBsb3RgIG5vdyB3aXRoIHRocmVlIGFyZ3VtZW50cy4gVGhlIGZpcnN0IHR3byBhcmUgdGhlIHZhcmlhYmxlcyBgZGlzcGxgIGFuZCBgaHd5YCB3ZSB3YW50IHRvIHBsb3QsIGFuZCB0aGUgdGhpcmQgaXMgdGhlIGFyZ3VtZW50IGBkYXRhYCBzZXQgZXF1YWwgdG8gYG1wZ2AuIEFzIGJlZm9yZSwgdGhpcyBhbGxvd3MgdXMgdG8gYXZvaWQgdXNpbmcgdGhlIGBtcGckdmFyaWFibGVgIG5vdGF0aW9uIGZvciB0aGUgZmlyc3QgdHdvIGFyZ3VtZW50cy4NCg0KYGBge3J9DQpxcGxvdChkaXNwbCwgaHd5LCBkYXRhID0gbXBnKQ0KYGBgDQoNCk5vdCBzdXJwcmlzaW5nbHkgd2Ugc2VlIHRoYXQgdGhlIGJpZ2dlciB0aGUgZW5naW5lIGRpc3BsYWNlbWVudCB0aGUgbG93ZXIgdGhlIGdhcyBtaWxlYWdlLg0KDQo8L2JyPg0KDQotLS0NCg0KTGV0J3MgcmV2aWV3IQ0KDQpXaGljaCBSIHBsb3R0aW5nIHN5c3RlbSBpcyBiYXNlZCBvbiBhbiBhcnRpc3QncyBwYWxldHRlPw0KDQoxLiBnZ3Bsb3QyDQoyLiAqKmJhc2UqKg0KMy4gV2luc29yJk5ld3Rvbg0KNC4gbGF0dGljZQ0KDQoNCldoaWNoIFIgcGxvdHRpbmcgc3lzdGVtIGRvZXMgTk9UIGFsbG93IHlvdSB0byBhbm5vdGF0ZSBwbG90cyB3aXRoIHNlcGFyYXRlIGNhbGxzPw0KDQoxLiBiYXNlDQoyLiBnZ3Bsb3QyDQozLiAqKmxhdHRpY2UqKg0KNC4gV2luc29yJk5ld3Rvbg0KDQoNCldoaWNoIFIgcGxvdHRpbmcgc3lzdGVtIGNvbWJpbmVzIHRoZSBiZXN0IGZlYXR1cmVzIG9mIHRoZSBvdGhlciB0d28/DQoNCjEuIFdpbnNvciZOZXd0b24NCjIuIGxhdHRpY2UNCjMuICoqZ2dwbG90MioqDQo0LiBiYXNlDQoNCg0KV2hpY2ggUiBwbG90dGluZyBzeXN0ZW0gdXNlcyBhIGdyYXBoaWNzIGdyYW1tYXI/DQoNCjEuIFdpbnNvciZOZXd0b24NCjIuIGJhc2UNCjMuICoqZ2dwbG90MioqDQo0LiBsYXR0aWNlDQoNCg0KV2hpY2ggUiBwbG90dGluZyBzeXN0ZW0gZm9yY2VzIHlvdSB0byBtYWtlIHlvdXIgZW50aXJlIHBsb3Qgd2l0aCBvbmUgY2FsbD8NCg0KMS4gV2luc29yJk5ld3Rvbg0KMi4gKipsYXR0aWNlKioNCjMuIGJhc2UNCjQuIGdncGxvdDINCg0KDQpXaGljaCBvZiB0aGUgZm9sbG93aW5nIHNlbGxzIGhpZ2ggcXVhbGl0eSBhcnRpc3RzJyBicnVzaGVzPw0KDQoxLiBiYXNlDQoyLiBnZ3Bsb3QyDQozLiBsYXR0aWNlDQo0LiAqKldpbnNvciZOZXd0b24qKg0KDQoNCkNvbmdyYXRzISBZb3UndmUgY29uY2x1ZGVkIHRoaXMgcGxvdHRpbmcgbGVzc29uLiBXZSBob3BlIHlvdSBkaWRuJ3QgZmluZCBpdCBwbG9kZGluZy4NCg0KPC9icj4NCg0KLS0tDQoNCjwvYnI+DQoNCjxjZW50ZXI+RU5EPC9jZW50ZXI+DQoNCjwvYnI+DQoNCi0tLQ==