Remember, before you can use the tidyverse, you need to load the package.

library(tidyverse)

First Steps

More plots with the mpg dataset

(Taken form R4DS)

  1. Run ggplot(data = mpg). What do you see?
  2. How many rows are in mpg? How many columns?
  3. What does the drv variable describe? You may want to use ?mpg to find out
  4. Make a scatter plot of hwy vs cyl
  5. What happens if you make a scatter plot of class vs drv? Why is the plot not useful?

Plots with other datasets

  1. Take a look at the iris dataset. What are its dimensions? What do its columns represent?
  2. What are the ranges of each of the numeric columns. The summary() function might help you here
  3. Make a plot of sepal width vs sepal length, and set all of the points to be green
  4. Repeat the previous plot but colour each point by the species of the flower

Remaking plots

  1. Take a look at the first and last few rows of the mtcars dataset
  2. Access the cyl column of the dataset. Is this variable categorical, discrete, or continuous?
  3. What steps would you go about to remake the following plot?

More Aesthetics

Size, Transparency, and Shape

  1. Using the mpg dataset, make a plot of city mileage vs highway mileage where the size of each point is determined by engine size (displ)
  2. Plot sepal length vs sepal width using the iris dataset and control the transparency (alpha) of each point using the species variable.
  3. Have a play with the Orange data set (note the capital ‘O’). Make a scatter plot of circumference against age where the shape of each point is determined by which tree the observation belongs to
  4. Remake the standard hwy vs displ plot using the mpg data set but make all of the points hollow diamonds. How about solid triangles?

Choosing Appropriate Aesthetics

(Q1/2 form R4DS)

  1. Which variables in mpg are categorical? Which are continuous/discrete? (The data set help file may be of use)
  2. Map a continuous variable to colour, size, and shape. How does this differ from when you map a categorical variable?
  3. Plot the standard hwy vs displ graph using mpg and map the variable class to the size aesthetic. Was this a good idea?
  4. Have a discussion with a partner or think for yourself: Which of the aesthetics you know are the clearest for displaying categorical data and which are best for continuous?
  5. In your own opinion, order the following aesthetics by how clear they are in representing a continuous variable: size, colour, transparency

Common Problems

  1. Using the mpg data set, make a plot of city milage against engine size. Map the variable class to the aesthetic shape. Is everything as you would expect?
  2. Type the following code into the console. Why do you recieve an error message?
ggplot(iris) +
  geom_point(x = Sepal.Length, y = Petal.Length)
  1. Take a look at the airquality dataset. Type the following code into the console. Is the plot as you expected?
ggplot(airquality) +
  geom_point(aes(x = Wind, y = Temp, col = Month))
  1. Why are the points in this plot not blue?
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, colour = 'blue'))

  1. What happens when you map a variable to multiple aesthetics (say colour and size)? (It’s okay to answer, “nothing”, to this question but make sure you verify that first!)

Facetting

Basic Faceting

(Taken form R4DS)

  1. What happens when you facet a continuous variable?
  2. What do the empty cells in a plot with facet_grid(drv ~ cyl) mean? How do they relate to this plot?
ggplot(mpg) +
  geom_point(aes(x = drv, y = cyl))
  1. What plots does the following code make? What does the . do?
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy)) +
  facet_grid(drv ~ .)

ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy)) +
  facet_grid(. ~ cyl)
  1. Take the first faceted plot from the presentation:
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy)) +
  facet_wrap(~ class, nrow = 2)

What are the advantages of faceting instead of the colour aesthetic? What are the disadvantages? How might the balance change if you had a larger data set?

  1. Read ?facet_wrap. What does nrow do? What does ncol do? What other options control the layout of the individual panels? Why doesn’t facet_grid() have nrow and ncol parameters?
  2. When using facet_grid() you should usually put the variable with more unique levels in the columns. Why?

Combining Facets with Aesthetics

  1. Create a scatter plot of petal length vs petal width using the iris dataset and facet by species
  2. Repeat the above plot whilst also colouring the species. Don’t forget to hide the colour legend
  3. Using the mpg dataset, plot hwy vs cty, map displ to the size aesthetic, map class to point colour, and facet columns by cyl and rows by drv. This plot is ridiculous but it does demonstrate the flexibilty of ggplot2

Going Beyond

Labelling

  1. Run the following code. What does the extra labs(...) layer do?
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, colour = class)) +
  labs(x = "Engine Displacment (litres)", y = "Highway Milage (miles/gallon)",
       colour = "Car Type",
       title = "A scatter plot of engine displacment vs highway milage",
       subtitle = "Coloured by car type",
       caption = "Source: EPA (http://fueleconomy.gov)")
  1. Use this to take the plot from the ‘Remaking plots’ section and beautify it
  2. Pick any plot of your choosing an give it appropriate axis labels, a title, and - if possible - a data source

Diamonds and Overplotting

  1. Have a look at the diamonds dataset
  2. Make a scatter plot of price against caret (this may take a long time to run). Is this plot easy to read?
  3. How could you fix this problem? (perhaps you could manually set a certain aesthetic)

Explanatory and Response variables

  1. How do you decide which variable to map to the x-axis and which to plot to the y-axis?
  2. If you are unsure, web-search for the phrase “explanatory and response variables”

Positional Arguments

Begin with the following code

ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, colour = factor(class)))

  1. Try removing x = and y = from your geom_point call. Does everything still work?
  2. Try removing colour = from your geom_point call. Does everything still work?
  3. Take the original plot and specify the aesthetics in a different order, say y then colour then x. Does everything still work?
LS0tCnRpdGxlOiAiSW50byB0aGUgVGlkeXZlcnNlIgpzdWJ0aXRsZTogIlNlc3Npb24gT25lIEV4ZXJjaXNlcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKUmVtZW1iZXIsIGJlZm9yZSB5b3UgY2FuIHVzZSB0aGUgdGlkeXZlcnNlLCB5b3UgbmVlZCB0byBsb2FkIHRoZSBwYWNrYWdlLgoKYGBge3IgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyMgRmlyc3QgU3RlcHMKCiMjIyBNb3JlIHBsb3RzIHdpdGggdGhlIG1wZyBkYXRhc2V0CgooKipUYWtlbiBmb3JtIFI0RFMqKikKCjEuIFJ1biBgZ2dwbG90KGRhdGEgPSBtcGcpYC4gV2hhdCBkbyB5b3Ugc2VlPwoyLiBIb3cgbWFueSByb3dzIGFyZSBpbiBtcGc/IEhvdyBtYW55IGNvbHVtbnM/CjMuIFdoYXQgZG9lcyB0aGUgYGRydmAgdmFyaWFibGUgZGVzY3JpYmU/IFlvdSBtYXkgd2FudCB0byB1c2UgYD9tcGdgIHRvIGZpbmQgb3V0CjQuIE1ha2UgYSBzY2F0dGVyIHBsb3Qgb2YgYGh3eWAgdnMgYGN5bGAKNS4gV2hhdCBoYXBwZW5zIGlmIHlvdSBtYWtlIGEgc2NhdHRlciBwbG90IG9mIGBjbGFzc2AgdnMgYGRydmA/IFdoeSBpcyB0aGUgcGxvdCBub3QgdXNlZnVsPwoKIyMjIFBsb3RzIHdpdGggb3RoZXIgZGF0YXNldHMKCjEuIFRha2UgYSBsb29rIGF0IHRoZSBgaXJpc2AgZGF0YXNldC4gV2hhdCBhcmUgaXRzIGRpbWVuc2lvbnM/IFdoYXQgZG8gaXRzIGNvbHVtbnMgcmVwcmVzZW50PwoyLiBXaGF0IGFyZSB0aGUgcmFuZ2VzIG9mIGVhY2ggb2YgdGhlIG51bWVyaWMgY29sdW1ucy4gVGhlIGBzdW1tYXJ5KClgIGZ1bmN0aW9uIG1pZ2h0IGhlbHAgeW91IGhlcmUKMy4gTWFrZSBhIHBsb3Qgb2Ygc2VwYWwgd2lkdGggdnMgc2VwYWwgbGVuZ3RoLCBhbmQgc2V0IGFsbCBvZiB0aGUgcG9pbnRzIHRvIGJlIGdyZWVuCjQuIFJlcGVhdCB0aGUgcHJldmlvdXMgcGxvdCBidXQgY29sb3VyIGVhY2ggcG9pbnQgYnkgdGhlIHNwZWNpZXMgb2YgdGhlIGZsb3dlcgoKIyMjIFJlbWFraW5nIHBsb3RzCgoxLiBUYWtlIGEgbG9vayBhdCB0aGUgZmlyc3QgYW5kIGxhc3QgZmV3IHJvd3Mgb2YgdGhlIGBtdGNhcnNgIGRhdGFzZXQKMi4gQWNjZXNzIHRoZSBgY3lsYCBjb2x1bW4gb2YgdGhlIGRhdGFzZXQuIElzIHRoaXMgdmFyaWFibGUgY2F0ZWdvcmljYWwsIGRpc2NyZXRlLCBvciBjb250aW51b3VzPwozLiBXaGF0IHN0ZXBzIHdvdWxkIHlvdSBnbyBhYm91dCB0byByZW1ha2UgdGhlIGZvbGxvd2luZyBwbG90PwoKYGBge3IgZWNobz1GQUxTRX0KZ2dwbG90KG10Y2FycykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwLCB5ID0gaHAsIGNvbG91ciA9IGZhY3RvcihjeWwpKSkKYGBgCgojIyBNb3JlIEFlc3RoZXRpY3MgCgojIyMgU2l6ZSwgVHJhbnNwYXJlbmN5LCBhbmQgU2hhcGUKCjEuIFVzaW5nIHRoZSBgbXBnYCBkYXRhc2V0LCBtYWtlIGEgcGxvdCBvZiBjaXR5IG1pbGVhZ2UgdnMgaGlnaHdheSBtaWxlYWdlIHdoZXJlIHRoZSBzaXplIG9mIGVhY2ggcG9pbnQgaXMgZGV0ZXJtaW5lZCBieSBlbmdpbmUgc2l6ZSAoYGRpc3BsYCkKMi4gUGxvdCBzZXBhbCBsZW5ndGggdnMgc2VwYWwgd2lkdGggdXNpbmcgdGhlIGBpcmlzYCBkYXRhc2V0IGFuZCBjb250cm9sIHRoZSB0cmFuc3BhcmVuY3kgKGBhbHBoYWApIG9mIGVhY2ggcG9pbnQgdXNpbmcgdGhlIGBzcGVjaWVzYCB2YXJpYWJsZS4KMy4gSGF2ZSBhIHBsYXkgd2l0aCB0aGUgYE9yYW5nZWAgZGF0YSBzZXQgKG5vdGUgdGhlIGNhcGl0YWwgJ08nKS4gTWFrZSBhIHNjYXR0ZXIgcGxvdCBvZiBjaXJjdW1mZXJlbmNlIGFnYWluc3QgYWdlIHdoZXJlIHRoZSBzaGFwZSBvZiBlYWNoIHBvaW50IGlzIGRldGVybWluZWQgYnkgd2hpY2ggdHJlZSB0aGUgb2JzZXJ2YXRpb24gYmVsb25ncyB0bwo0LiBSZW1ha2UgdGhlIHN0YW5kYXJkIGBod3lgIHZzIGBkaXNwbGAgcGxvdCB1c2luZyB0aGUgYG1wZ2AgZGF0YSBzZXQgYnV0IG1ha2UgYWxsIG9mIHRoZSBwb2ludHMgaG9sbG93IGRpYW1vbmRzLiBIb3cgYWJvdXQgc29saWQgdHJpYW5nbGVzPwoKIyMjIENob29zaW5nIEFwcHJvcHJpYXRlIEFlc3RoZXRpY3MKCigqKlExLzIgZm9ybSBSNERTKiopCgoxLiBXaGljaCB2YXJpYWJsZXMgaW4gYG1wZ2AgYXJlIGNhdGVnb3JpY2FsPyBXaGljaCBhcmUgY29udGludW91cy9kaXNjcmV0ZT8gKFRoZSBkYXRhIHNldCBoZWxwIGZpbGUgbWF5IGJlIG9mIHVzZSkKMi4gTWFwIGEgY29udGludW91cyB2YXJpYWJsZSB0byBjb2xvdXIsIHNpemUsIGFuZCBzaGFwZS4gSG93IGRvZXMgdGhpcyBkaWZmZXIgZnJvbSB3aGVuIHlvdSBtYXAgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZT8KMy4gUGxvdCB0aGUgc3RhbmRhcmQgYGh3eWAgdnMgYGRpc3BsYCBncmFwaCB1c2luZyBgbXBnYCBhbmQgbWFwIHRoZSB2YXJpYWJsZSBgY2xhc3NgIHRvIHRoZSBgc2l6ZWAgYWVzdGhldGljLiBXYXMgdGhpcyBhIGdvb2QgaWRlYT8KNC4gSGF2ZSBhIGRpc2N1c3Npb24gd2l0aCBhIHBhcnRuZXIgb3IgdGhpbmsgZm9yIHlvdXJzZWxmOiBXaGljaCBvZiB0aGUgYWVzdGhldGljcyB5b3Uga25vdyBhcmUgdGhlIGNsZWFyZXN0IGZvciBkaXNwbGF5aW5nIGNhdGVnb3JpY2FsIGRhdGEgYW5kIHdoaWNoIGFyZSBiZXN0IGZvciBjb250aW51b3VzPyAKNS4gSW4geW91ciBvd24gb3Bpbmlvbiwgb3JkZXIgdGhlIGZvbGxvd2luZyBhZXN0aGV0aWNzIGJ5IGhvdyBjbGVhciB0aGV5IGFyZSBpbiByZXByZXNlbnRpbmcgYSBjb250aW51b3VzIHZhcmlhYmxlOiBzaXplLCBjb2xvdXIsIHRyYW5zcGFyZW5jeQoKIyMjIENvbW1vbiBQcm9ibGVtcwoKMS4gVXNpbmcgdGhlIGBtcGdgIGRhdGEgc2V0LCBtYWtlIGEgcGxvdCBvZiBjaXR5IG1pbGFnZSBhZ2FpbnN0IGVuZ2luZSBzaXplLiBNYXAgdGhlIHZhcmlhYmxlIGBjbGFzc2AgdG8gdGhlIGFlc3RoZXRpYyBgc2hhcGVgLiBJcyBldmVyeXRoaW5nIGFzIHlvdSB3b3VsZCBleHBlY3Q/CjIuIFR5cGUgdGhlIGZvbGxvd2luZyBjb2RlIGludG8gdGhlIGNvbnNvbGUuIFdoeSBkbyB5b3UgcmVjaWV2ZSBhbiBlcnJvciBtZXNzYWdlPwoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QoaXJpcykgKwogIGdlb21fcG9pbnQoeCA9IFNlcGFsLkxlbmd0aCwgeSA9IFBldGFsLkxlbmd0aCkKYGBgCgozLiBUYWtlIGEgbG9vayBhdCB0aGUgYGFpcnF1YWxpdHlgIGRhdGFzZXQuIFR5cGUgdGhlIGZvbGxvd2luZyBjb2RlIGludG8gdGhlIGNvbnNvbGUuIElzIHRoZSBwbG90IGFzIHlvdSBleHBlY3RlZD8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KGFpcnF1YWxpdHkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gV2luZCwgeSA9IFRlbXAsIGNvbCA9IE1vbnRoKSkKYGBgCgo0LiBXaHkgYXJlIHRoZSBwb2ludHMgaW4gdGhpcyBwbG90IG5vdCBibHVlPwoKYGBge3IgbWVzc2FnZSA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvdXIgPSAnYmx1ZScpKQpgYGAKCjUuIFdoYXQgaGFwcGVucyB3aGVuIHlvdSBtYXAgYSB2YXJpYWJsZSB0byBtdWx0aXBsZSBhZXN0aGV0aWNzIChzYXkgY29sb3VyIGFuZCBzaXplKT8gKEl0J3Mgb2theSB0byBhbnN3ZXIsICJub3RoaW5nIiwgdG8gdGhpcyBxdWVzdGlvbiBidXQgbWFrZSBzdXJlIHlvdSB2ZXJpZnkgdGhhdCBmaXJzdCEpCgojIyBGYWNldHRpbmcKCiMjIyBCYXNpYyBGYWNldGluZwoKKCoqVGFrZW4gZm9ybSBSNERTKiopCgoxLiBXaGF0IGhhcHBlbnMgd2hlbiB5b3UgZmFjZXQgYSBjb250aW51b3VzIHZhcmlhYmxlPwoyLiBXaGF0IGRvIHRoZSBlbXB0eSBjZWxscyBpbiBhIHBsb3Qgd2l0aCBgZmFjZXRfZ3JpZChkcnYgfiBjeWwpYCBtZWFuPyBIb3cgZG8gdGhleSByZWxhdGUgdG8gdGhpcyBwbG90PwoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRydiwgeSA9IGN5bCkpCmBgYAoKMy4gV2hhdCBwbG90cyBkb2VzIHRoZSBmb2xsb3dpbmcgY29kZSBtYWtlPyBXaGF0IGRvZXMgdGhlIGAuYCBkbz8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KG1wZykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsKICBmYWNldF9ncmlkKGRydiB+IC4pCgpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKwogIGZhY2V0X2dyaWQoLiB+IGN5bCkKYGBgCgo0LiBUYWtlIHRoZSBmaXJzdCBmYWNldGVkIHBsb3QgZnJvbSB0aGUgcHJlc2VudGF0aW9uOgoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKwogIGZhY2V0X3dyYXAofiBjbGFzcywgbnJvdyA9IDIpCmBgYAoKV2hhdCBhcmUgdGhlIGFkdmFudGFnZXMgb2YgZmFjZXRpbmcgaW5zdGVhZCBvZiB0aGUgY29sb3VyIGFlc3RoZXRpYz8gV2hhdCBhcmUgdGhlIGRpc2FkdmFudGFnZXM/IEhvdyBtaWdodCB0aGUgYmFsYW5jZSBjaGFuZ2UgaWYgeW91IGhhZCBhIGxhcmdlciBkYXRhIHNldD8KCjUuIFJlYWQgYD9mYWNldF93cmFwYC4gV2hhdCBkb2VzIGBucm93YCBkbz8gV2hhdCBkb2VzIGBuY29sYCBkbz8gV2hhdCBvdGhlciBvcHRpb25zIGNvbnRyb2wgdGhlIGxheW91dCBvZiB0aGUgaW5kaXZpZHVhbCBwYW5lbHM/IFdoeSBkb2Vzbid0IGBmYWNldF9ncmlkKClgIGhhdmUgYG5yb3dgIGFuZCBgbmNvbGAgcGFyYW1ldGVycz8KNi4gV2hlbiB1c2luZyBgZmFjZXRfZ3JpZCgpYCB5b3Ugc2hvdWxkIHVzdWFsbHkgcHV0IHRoZSB2YXJpYWJsZSB3aXRoIG1vcmUgdW5pcXVlIGxldmVscyBpbiB0aGUgY29sdW1ucy4gV2h5PwoKCiMjIyBDb21iaW5pbmcgRmFjZXRzIHdpdGggQWVzdGhldGljcwoKMS4gQ3JlYXRlIGEgc2NhdHRlciBwbG90IG9mIHBldGFsIGxlbmd0aCB2cyBwZXRhbCB3aWR0aCB1c2luZyB0aGUgYGlyaXNgIGRhdGFzZXQgYW5kIGZhY2V0IGJ5IHNwZWNpZXMKMi4gUmVwZWF0IHRoZSBhYm92ZSBwbG90IHdoaWxzdCBhbHNvIGNvbG91cmluZyB0aGUgc3BlY2llcy4gRG9uJ3QgZm9yZ2V0IHRvIGhpZGUgdGhlIGNvbG91ciBsZWdlbmQKMy4gVXNpbmcgdGhlIGBtcGdgIGRhdGFzZXQsIHBsb3QgYGh3eWAgdnMgYGN0eWAsIG1hcCBgZGlzcGxgIHRvIHRoZSBgc2l6ZWAgYWVzdGhldGljLCBtYXAgYGNsYXNzYCB0byBwb2ludCBjb2xvdXIsIGFuZCBmYWNldCBjb2x1bW5zIGJ5IGBjeWxgIGFuZCByb3dzIGJ5IGBkcnZgLiBUaGlzIHBsb3QgaXMgcmlkaWN1bG91cyBidXQgaXQgZG9lcyBkZW1vbnN0cmF0ZSB0aGUgZmxleGliaWx0eSBvZiBgZ2dwbG90MmAKCiMjIEdvaW5nIEJleW9uZAoKIyMjIExhYmVsbGluZwoKMS4gUnVuIHRoZSBmb2xsb3dpbmcgY29kZS4gV2hhdCBkb2VzIHRoZSBleHRyYSBgbGFicyguLi4pYCBsYXllciBkbz8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KG1wZykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwbCwgeSA9IGh3eSwgY29sb3VyID0gY2xhc3MpKSArCiAgbGFicyh4ID0gIkVuZ2luZSBEaXNwbGFjbWVudCAobGl0cmVzKSIsIHkgPSAiSGlnaHdheSBNaWxhZ2UgKG1pbGVzL2dhbGxvbikiLAogICAgICAgY29sb3VyID0gIkNhciBUeXBlIiwKICAgICAgIHRpdGxlID0gIkEgc2NhdHRlciBwbG90IG9mIGVuZ2luZSBkaXNwbGFjbWVudCB2cyBoaWdod2F5IG1pbGFnZSIsCiAgICAgICBzdWJ0aXRsZSA9ICJDb2xvdXJlZCBieSBjYXIgdHlwZSIsCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogRVBBIChodHRwOi8vZnVlbGVjb25vbXkuZ292KSIpCmBgYAoKMi4gVXNlIHRoaXMgdG8gdGFrZSB0aGUgcGxvdCBmcm9tIHRoZSAnUmVtYWtpbmcgcGxvdHMnIHNlY3Rpb24gYW5kIGJlYXV0aWZ5IGl0CjMuIFBpY2sgYW55IHBsb3Qgb2YgeW91ciBjaG9vc2luZyBhbiBnaXZlIGl0IGFwcHJvcHJpYXRlIGF4aXMgbGFiZWxzLCBhIHRpdGxlLCBhbmQgLSBpZiBwb3NzaWJsZSAtIGEgZGF0YSBzb3VyY2UKCiMjIyBEaWFtb25kcyBhbmQgT3ZlcnBsb3R0aW5nCgoxLiBIYXZlIGEgbG9vayBhdCB0aGUgYGRpYW1vbmRzYCBkYXRhc2V0CjIuIE1ha2UgYSBzY2F0dGVyIHBsb3Qgb2YgYHByaWNlYCBhZ2FpbnN0IGBjYXJldGAgKHRoaXMgbWF5IHRha2UgYSBsb25nIHRpbWUgdG8gcnVuKS4gSXMgdGhpcyBwbG90IGVhc3kgdG8gcmVhZD8KMy4gSG93IGNvdWxkIHlvdSBmaXggdGhpcyBwcm9ibGVtPyAocGVyaGFwcyB5b3UgY291bGQgbWFudWFsbHkgc2V0IGEgY2VydGFpbiBhZXN0aGV0aWMpCgojIyMgRXhwbGFuYXRvcnkgYW5kIFJlc3BvbnNlIHZhcmlhYmxlcwoKMS4gSG93IGRvIHlvdSBkZWNpZGUgd2hpY2ggdmFyaWFibGUgdG8gbWFwIHRvIHRoZSB4LWF4aXMgYW5kIHdoaWNoIHRvIHBsb3QgdG8gdGhlIHktYXhpcz8KMi4gSWYgeW91IGFyZSB1bnN1cmUsIHdlYi1zZWFyY2ggZm9yIHRoZSBwaHJhc2UgImV4cGxhbmF0b3J5IGFuZCByZXNwb25zZSB2YXJpYWJsZXMiCgojIyMgUG9zaXRpb25hbCBBcmd1bWVudHMKCkJlZ2luIHdpdGggdGhlIGZvbGxvd2luZyBjb2RlCgpgYGB7ciBldmFsIEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvdXIgPSBmYWN0b3IoY2xhc3MpKSkKYGBgCgoxLiBUcnkgcmVtb3ZpbmcgYHggPSBgIGFuZCBgeSA9IGAgZnJvbSB5b3VyIGBnZW9tX3BvaW50YCBjYWxsLiBEb2VzIGV2ZXJ5dGhpbmcgc3RpbGwgd29yaz8KMi4gVHJ5IHJlbW92aW5nIGBjb2xvdXIgPSBgIGZyb20geW91ciBgZ2VvbV9wb2ludGAgY2FsbC4gRG9lcyBldmVyeXRoaW5nIHN0aWxsIHdvcms/CjMuIFRha2UgdGhlIG9yaWdpbmFsIHBsb3QgYW5kIHNwZWNpZnkgdGhlIGFlc3RoZXRpY3MgaW4gYSBkaWZmZXJlbnQgb3JkZXIsIHNheSBgeWAgdGhlbiBgY29sb3VyYCB0aGVuIGB4YC4gRG9lcyBldmVyeXRoaW5nIHN0aWxsIHdvcms/Cg==