Introduction:
In this lab we will learn:
- how to compute and interpret summary statistics
- how to create basic visuals/graphs
Part 1: Summary statistics
Exercise 1: Load the mouse.csv file (found on Canvas) in the code
chunk below, call the data frame “mouse”:
mouse <- read.csv('~/Desktop/BIN510-files/mouse.csv')
The mouse dataset looks at how individual mice develop certain types
of cancer based on treatments. The primary numerical variable is days
until cancer appears.
Often, we work with data where we don’t necessarily know each
column/variable or the types they are, we can write code to help provide
insight into how these sets look.
str(mouse)
'data.frame': 181 obs. of 5 variables:
$ rownames: int 1 2 3 4 5 6 7 8 9 10 ...
$ trt : chr "Control" "Control" "Control" "Control" ...
$ days : int 159 189 191 198 200 207 220 235 245 250 ...
$ outcome : chr "thymic lymphoma" "thymic lymphoma" "thymic lymphoma" "thymic lymphoma" ...
$ id : int 1 2 3 4 5 6 7 8 9 10 ...
R also has many other built in tools to explore data, here are some
examples:
Size: dim() - returns a vector with the number of rows in the first
element, and the number of columns as the second element (the dimensions
of the object) nrow() - returns the number of rows ncol() - returns the
number of columns
Content: head() - shows the first 6 rows tail() - shows the last 6
rows
Names: names() - returns the column names (synonym of colnames() for
data.frame objects) rownames() - returns the row names
Summary: str() - structure of the object and information about the
class, length and content of each column summary() - summary statistics
for each column
Exercise 1: for the mouse dataset, please use the code chunk below
to use code and determine the following:
How many rows are in this dataset? How many columns are in
this dataset? What type of variable is “trt”? What is the mean
of the “days” column?
nrow(mouse)
[1] 181
ncol(mouse)
[1] 5
str(mouse$trt)
chr [1:181] "Control" "Control" "Control" "Control" "Control" "Control" "Control" "Control" ...
mean(mouse$days)
[1] 514.768
Basic built-in functions in R also allow for calculating specific
summary statistics: mean() - calculates the mean of a numerical/integer
column median() - calculates the median of a numerical/integer column
sd() - calculates the standard deviation of a numerical/integer
column
Exercise 2:please use the code chunk below to use code and determine
the following:
What is the median of the “days” column? What is the sd of
the “days” column?
median(mouse$days)
[1] 554
sd(mouse$days)
[1] 232.6566
While calculating the mean of a column is useful, we often want to
determine how summary statistics differ among variables or groups. We
can create code that calculates the mean of a numerical variable by
specific categorical variables using the tapply() code:
tapply(mouse$days, mouse$outcome, mean)
other reticulum cell sarcoma thymic lymphoma
565.7792 631.1321 316.8235
QUESTION: how would you describe what the code above does? Answer
below:
The code above shows the means of days for each of the outcomes
(other, reticulum, and thymic.)
Exercise 3: using the code chunk below, use the tapply() code to
calculate the following:
What is the mean of the “days” column by the “trt” column?
What is the sd of the “days” column by the “trt” column?
tapply(mouse$days, mouse$trt, mean)
Control Germ-free
456.596 585.000
tapply(mouse$days, mouse$trt, sd)
Control Germ-free
195.9897 254.3301
We can take tapply() a step further, what if we wanted to break up
summary statistics by more than one group?? For this we would use the
aggregate() code:
aggregate(mouse$days, by = list(mouse$outcome, mouse$trt), mean)
NOTE: you can swap in other functions if needed
QUESTION: what do you notice about the output of the aggregate code?
Answer below:
I noticed that the output table has both the means for outcome and
trt based on days.
Exercise 4: can you turn the aggregate output into a new dataframe
with new column names? HINT: step 1 would be give a variable name to the
aggregate code (kind of like we do for the read.table() codes…)
newmouse <- aggregate(mouse$days, by = list(mouse$outcome, mouse$trt), mean)
Why do we want to do this? We often need means and standard
deviations to create certain types of plots, having these stored in
their own dataframe makes this easy!
Quick visuals
R can also quickly generate visualizations using commands like
hist(), boxplot(), and plot(). We
will explore these, as well as more statistical summaries, over the next
two weeks. For now, let’s try to develop an intuition via examples
Exercise 4:
For each code chunk below, run the code and look at the output.
Try to explain how the code works in your own words, as well as what the
code generates.
hist(mouse$days,col='red')

Answer:
This code creates a histogram based on the number of mice that
survived a certain number of days. ****
boxplot(days~ trt, data = mouse, col='blue')

boxplot(days~ trt, data = mouse, col=c('blue', "green"))

Answer:
This code creates a boxplot comparing the number of days for each of
the treatment types; control (blue), and Germ-free (green).This can show
if treatments effect how long the mice survived. ****
plot(days ~ id, data = mouse, col='black',
main="Days by ID")

plot(days ~ id, data = mouse, pch = 4, col='black',
main="Days by ID")

Answer:
The first code is used to show how long each mouse (by id) survived.
The second code just changes the circles into an X. ****
Exercise 5: create a boxplot for “days” by “outcome”, this plot
should include the following
unique colors for each outcome a plot title
boxplot(days~outcome,
data= mouse,
col= c("pink","turquoise", "skyblue"),
main= "Number of Days by Outcome",
xlab="Outcome",
ylab="Days")

Exercise 6: looking at summaries of categorical variables
We previously looked at the mean, median, and standard deviation of
the numerical “days” variable, but other variables are still of interest
to researchers, such as cancer type or “outcome”, we can’t however,
calculate means of categories, so instead let’s look at some other
summary information we can obtain…
The code chunk below shows how we can extract a table of
counts/frequencies for cancer outcomes:
table(mouse$outcome)
other reticulum cell sarcoma thymic lymphoma
77 53 51
One common practice in biological statistics is to standardize values
(usually done by creating percentages), this allows us to better make
comparisons between groups or data. In order for us to take the counts
that are output in the code above and turn them into percentages or
proportions, we need to divide by the total number of cases, in this
case, that’s the total number of rows in the dataset.
The code below does the following: it creates and stores a variable
to represent the total number of rows, then it divides our table counts
by that value - what gets output is the proportion.
n <- length(mouse$outcome)
table(mouse$outcome)/n
other reticulum cell sarcoma thymic lymphoma
0.4254144 0.2928177 0.2817680
CHALLENGE: create a code that calculates the PERCENT of each cancer
type - use the code chunk below:
prop.table(table(mouse$outcome)) * 100
other reticulum cell sarcoma thymic lymphoma
42.54144 29.28177 28.17680
Exercise 7: parsing out counts/frequencies by another variable
Above we used the tapply() and aggregate() codes to calculate means
by different groups or variables, what if we wanted to do the same for
our categorical variable “outcome”?
The code below creates a table of “outcome” by “trt”, this will allow
us to see if there seems to be certain cancer types more associated with
certain treatments
cancer_developed<-table(mouse$outcome,
mouse$trt)
cancer_developed
Control Germ-free
other 39 38
reticulum cell sarcoma 38 15
thymic lymphoma 22 29
What patterns do you notice from the table that gets outputted by the
code?
Answer:I noticed that for “other” and “thymic lymphoma” categories
there werea close number of mice in both outcome groups. There was a
major difference between the control and germ-free numbers with the
“reticulum cell sarcoma”. It seemed like the reticulum was more common
in the control group.
PLEASE CONVERT THIS TO AN HTML FILE AND UPLOAD IT TO CANVAS!
LS0tCnRpdGxlOiAiQklONTEwX0xhYjIiCnN1YnRpdGxlOiBTdW1tYXJ5IHN0YXRpc3RpY3MgYW5kIGJhc2ljIHZpc3VhbGl6YXRpb25zCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KCiMjIEludHJvZHVjdGlvbjoKSW4gdGhpcyBsYWIgd2Ugd2lsbCBsZWFybjoKCiogaG93IHRvIGNvbXB1dGUgYW5kIGludGVycHJldCBzdW1tYXJ5IHN0YXRpc3RpY3MKKiBob3cgdG8gY3JlYXRlIGJhc2ljIHZpc3VhbHMvZ3JhcGhzICAKCiMjIFBhcnQgMTogU3VtbWFyeSBzdGF0aXN0aWNzCgpFeGVyY2lzZSAxOiBMb2FkIHRoZSBtb3VzZS5jc3YgZmlsZSAoZm91bmQgb24gQ2FudmFzKSBpbiB0aGUgY29kZSBjaHVuayBiZWxvdywgY2FsbCB0aGUgZGF0YSBmcmFtZSAibW91c2UiOgoKYGBge3J9Cm1vdXNlIDwtIHJlYWQuY3N2KCd+L0Rlc2t0b3AvQklONTEwLWZpbGVzL21vdXNlLmNzdicpCmBgYApUaGUgbW91c2UgZGF0YXNldCBsb29rcyBhdCBob3cgaW5kaXZpZHVhbCBtaWNlIGRldmVsb3AgY2VydGFpbiB0eXBlcyBvZiBjYW5jZXIgYmFzZWQgb24gdHJlYXRtZW50cy4gVGhlIHByaW1hcnkgbnVtZXJpY2FsIHZhcmlhYmxlIGlzIGRheXMgdW50aWwgY2FuY2VyIGFwcGVhcnMuCgpPZnRlbiwgd2Ugd29yayB3aXRoIGRhdGEgd2hlcmUgd2UgZG9uJ3QgbmVjZXNzYXJpbHkga25vdyBlYWNoIGNvbHVtbi92YXJpYWJsZSBvciB0aGUgdHlwZXMgdGhleSBhcmUsIHdlIGNhbiB3cml0ZSBjb2RlIHRvIGhlbHAgcHJvdmlkZSBpbnNpZ2h0IGludG8gaG93IHRoZXNlIHNldHMgbG9vay4KYGBge3J9CnN0cihtb3VzZSkKYGBgCgpSIGFsc28gaGFzIG1hbnkgb3RoZXIgYnVpbHQgaW4gdG9vbHMgdG8gZXhwbG9yZSBkYXRhLCBoZXJlIGFyZSBzb21lIGV4YW1wbGVzOgoKU2l6ZToKZGltKCkgLSByZXR1cm5zIGEgdmVjdG9yIHdpdGggdGhlIG51bWJlciBvZiByb3dzIGluIHRoZSBmaXJzdCBlbGVtZW50LCBhbmQgdGhlIG51bWJlciBvZiBjb2x1bW5zIGFzIHRoZSBzZWNvbmQgZWxlbWVudCAodGhlIGRpbWVuc2lvbnMgb2YgdGhlIG9iamVjdCkKbnJvdygpIC0gcmV0dXJucyB0aGUgbnVtYmVyIG9mIHJvd3MKbmNvbCgpIC0gcmV0dXJucyB0aGUgbnVtYmVyIG9mIGNvbHVtbnMKCkNvbnRlbnQ6CmhlYWQoKSAtIHNob3dzIHRoZSBmaXJzdCA2IHJvd3MKdGFpbCgpIC0gc2hvd3MgdGhlIGxhc3QgNiByb3dzCgpOYW1lczoKbmFtZXMoKSAtIHJldHVybnMgdGhlIGNvbHVtbiBuYW1lcyAoc3lub255bSBvZiBjb2xuYW1lcygpIGZvciBkYXRhLmZyYW1lIG9iamVjdHMpCnJvd25hbWVzKCkgLSByZXR1cm5zIHRoZSByb3cgbmFtZXMKClN1bW1hcnk6CnN0cigpIC0gc3RydWN0dXJlIG9mIHRoZSBvYmplY3QgYW5kIGluZm9ybWF0aW9uIGFib3V0IHRoZSBjbGFzcywgbGVuZ3RoIGFuZCBjb250ZW50IG9mIGVhY2ggY29sdW1uCnN1bW1hcnkoKSAtIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgZWFjaCBjb2x1bW4KCiMjIEV4ZXJjaXNlIDE6IGZvciB0aGUgbW91c2UgZGF0YXNldCwgcGxlYXNlIHVzZSB0aGUgY29kZSBjaHVuayBiZWxvdyB0byB1c2UgY29kZSBhbmQgZGV0ZXJtaW5lIHRoZSBmb2xsb3dpbmc6CipIb3cgbWFueSByb3dzIGFyZSBpbiB0aGlzIGRhdGFzZXQ/CipIb3cgbWFueSBjb2x1bW5zIGFyZSBpbiB0aGlzIGRhdGFzZXQ/CipXaGF0IHR5cGUgb2YgdmFyaWFibGUgaXMgInRydCI/CipXaGF0IGlzIHRoZSBtZWFuIG9mIHRoZSAiZGF5cyIgY29sdW1uPwoKYGBge3J9Cm5yb3cobW91c2UpCm5jb2wobW91c2UpCnN0cihtb3VzZSR0cnQpCm1lYW4obW91c2UkZGF5cykKYGBgCgpCYXNpYyBidWlsdC1pbiBmdW5jdGlvbnMgaW4gUiBhbHNvIGFsbG93IGZvciBjYWxjdWxhdGluZyBzcGVjaWZpYyBzdW1tYXJ5IHN0YXRpc3RpY3M6Cm1lYW4oKSAtIGNhbGN1bGF0ZXMgdGhlIG1lYW4gb2YgYSBudW1lcmljYWwvaW50ZWdlciBjb2x1bW4KbWVkaWFuKCkgLSBjYWxjdWxhdGVzIHRoZSBtZWRpYW4gb2YgYSBudW1lcmljYWwvaW50ZWdlciBjb2x1bW4Kc2QoKSAtIGNhbGN1bGF0ZXMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBhIG51bWVyaWNhbC9pbnRlZ2VyIGNvbHVtbgoKCiMjIEV4ZXJjaXNlIDI6cGxlYXNlIHVzZSB0aGUgY29kZSBjaHVuayBiZWxvdyB0byB1c2UgY29kZSBhbmQgZGV0ZXJtaW5lIHRoZSBmb2xsb3dpbmc6CipXaGF0IGlzIHRoZSBtZWRpYW4gb2YgdGhlICJkYXlzIiBjb2x1bW4/CipXaGF0IGlzIHRoZSBzZCBvZiB0aGUgImRheXMiIGNvbHVtbj8KCmBgYHtyfQptZWRpYW4obW91c2UkZGF5cykKc2QobW91c2UkZGF5cykKCmBgYAoKV2hpbGUgY2FsY3VsYXRpbmcgdGhlIG1lYW4gb2YgYSBjb2x1bW4gaXMgdXNlZnVsLCB3ZSBvZnRlbiB3YW50IHRvIGRldGVybWluZSBob3cgc3VtbWFyeSBzdGF0aXN0aWNzIGRpZmZlciBhbW9uZyB2YXJpYWJsZXMgb3IgZ3JvdXBzLiBXZSBjYW4gY3JlYXRlIGNvZGUgdGhhdCBjYWxjdWxhdGVzIHRoZSBtZWFuIG9mIGEgbnVtZXJpY2FsIHZhcmlhYmxlIGJ5IHNwZWNpZmljIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyB1c2luZyB0aGUgdGFwcGx5KCkgY29kZToKCmBgYHtyfQp0YXBwbHkobW91c2UkZGF5cywgbW91c2Ukb3V0Y29tZSwgbWVhbikKYGBgCgojIyBRVUVTVElPTjogaG93IHdvdWxkIHlvdSBkZXNjcmliZSB3aGF0IHRoZSBjb2RlIGFib3ZlIGRvZXM/IEFuc3dlciBiZWxvdzoKIFRoZSBjb2RlIGFib3ZlIHNob3dzIHRoZSBtZWFucyBvZiBkYXlzIGZvciBlYWNoIG9mIHRoZSBvdXRjb21lcyAob3RoZXIsIHJldGljdWx1bSwgYW5kIHRoeW1pYy4pCgojIyBFeGVyY2lzZSAzOiB1c2luZyB0aGUgY29kZSBjaHVuayBiZWxvdywgdXNlIHRoZSB0YXBwbHkoKSBjb2RlIHRvIGNhbGN1bGF0ZSB0aGUgZm9sbG93aW5nOgoqV2hhdCBpcyB0aGUgbWVhbiBvZiB0aGUgImRheXMiIGNvbHVtbiBieSB0aGUgInRydCIgY29sdW1uPwoqV2hhdCBpcyB0aGUgc2Qgb2YgdGhlICJkYXlzIiBjb2x1bW4gYnkgdGhlICJ0cnQiIGNvbHVtbj8KCmBgYHtyfQp0YXBwbHkobW91c2UkZGF5cywgbW91c2UkdHJ0LCBtZWFuKQp0YXBwbHkobW91c2UkZGF5cywgbW91c2UkdHJ0LCBzZCkKYGBgCgpXZSBjYW4gdGFrZSB0YXBwbHkoKSBhIHN0ZXAgZnVydGhlciwgd2hhdCBpZiB3ZSB3YW50ZWQgdG8gYnJlYWsgdXAgc3VtbWFyeSBzdGF0aXN0aWNzIGJ5IG1vcmUgdGhhbiBvbmUgZ3JvdXA/PyBGb3IgdGhpcyB3ZSB3b3VsZCB1c2UgdGhlIGFnZ3JlZ2F0ZSgpIGNvZGU6CgpgYGB7cn0KYWdncmVnYXRlKG1vdXNlJGRheXMsIGJ5ID0gbGlzdChtb3VzZSRvdXRjb21lLCBtb3VzZSR0cnQpLCBtZWFuKSAKYGBgCk5PVEU6IHlvdSBjYW4gc3dhcCBpbiBvdGhlciBmdW5jdGlvbnMgaWYgbmVlZGVkCgojIyBRVUVTVElPTjogd2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHRoZSBvdXRwdXQgb2YgdGhlIGFnZ3JlZ2F0ZSBjb2RlPyBBbnN3ZXIgYmVsb3c6Ckkgbm90aWNlZCB0aGF0IHRoZSBvdXRwdXQgdGFibGUgaGFzIGJvdGggdGhlIG1lYW5zIGZvciBvdXRjb21lIGFuZCB0cnQgYmFzZWQgb24gZGF5cy4gCgojIyBFeGVyY2lzZSA0OiBjYW4geW91IHR1cm4gdGhlIGFnZ3JlZ2F0ZSBvdXRwdXQgaW50byBhIG5ldyBkYXRhZnJhbWUgd2l0aCBuZXcgY29sdW1uIG5hbWVzPyBISU5UOiBzdGVwIDEgd291bGQgYmUgZ2l2ZSBhIHZhcmlhYmxlIG5hbWUgdG8gdGhlIGFnZ3JlZ2F0ZSBjb2RlIChraW5kIG9mIGxpa2Ugd2UgZG8gZm9yIHRoZSByZWFkLnRhYmxlKCkgY29kZXMuLi4pCgpgYGB7cn0KbmV3bW91c2UgPC0gYWdncmVnYXRlKG1vdXNlJGRheXMsIGJ5ID0gbGlzdChtb3VzZSRvdXRjb21lLCBtb3VzZSR0cnQpLCBtZWFuKSAKYGBgCgpXaHkgZG8gd2Ugd2FudCB0byBkbyB0aGlzPyBXZSBvZnRlbiBuZWVkIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIHRvIGNyZWF0ZSBjZXJ0YWluIHR5cGVzIG9mIHBsb3RzLCBoYXZpbmcgdGhlc2Ugc3RvcmVkIGluIHRoZWlyIG93biBkYXRhZnJhbWUgbWFrZXMgdGhpcyBlYXN5IQoKCgoKIyMgUXVpY2sgdmlzdWFscwoKUiBjYW4gYWxzbyBxdWlja2x5IGdlbmVyYXRlIHZpc3VhbGl6YXRpb25zIHVzaW5nIGNvbW1hbmRzIGxpa2UgYGhpc3QoKWAsIGBib3hwbG90KClgLCBhbmQgYHBsb3QoKWAuICBXZSB3aWxsIGV4cGxvcmUgdGhlc2UsIGFzIHdlbGwgYXMgbW9yZSBzdGF0aXN0aWNhbCBzdW1tYXJpZXMsIG92ZXIgdGhlIG5leHQgdHdvIHdlZWtzLiBGb3Igbm93LCBsZXQncyB0cnkgdG8gZGV2ZWxvcCBhbiBpbnR1aXRpb24gdmlhIGV4YW1wbGVzCgojIyMjIEV4ZXJjaXNlIDQ6CipGb3IgZWFjaCBjb2RlIGNodW5rIGJlbG93LCBydW4gdGhlIGNvZGUgYW5kIGxvb2sgYXQgdGhlIG91dHB1dC4gVHJ5IHRvIGV4cGxhaW4gaG93IHRoZSBjb2RlIHdvcmtzIGluIHlvdXIgb3duIHdvcmRzLCBhcyB3ZWxsIGFzIHdoYXQgdGhlIGNvZGUgZ2VuZXJhdGVzLioKCmBgYHtyfQpoaXN0KG1vdXNlJGRheXMsY29sPSdyZWQnKQpgYGAKKioqKgojIyMjIEFuc3dlcjoKVGhpcyBjb2RlIGNyZWF0ZXMgYSBoaXN0b2dyYW0gYmFzZWQgb24gdGhlIG51bWJlciBvZiBtaWNlIHRoYXQgc3Vydml2ZWQgYSBjZXJ0YWluIG51bWJlciBvZiBkYXlzLiAKKioqKgoKYGBge3J9CmJveHBsb3QoZGF5c34gdHJ0LCBkYXRhID0gbW91c2UsIGNvbD0nYmx1ZScpCmBgYAoKYGBge3J9CmJveHBsb3QoZGF5c34gdHJ0LCBkYXRhID0gbW91c2UsIGNvbD1jKCdibHVlJywgImdyZWVuIikpCmBgYAoKKioqKgojIyMjIEFuc3dlcjoKVGhpcyBjb2RlIGNyZWF0ZXMgYSBib3hwbG90IGNvbXBhcmluZyB0aGUgbnVtYmVyIG9mIGRheXMgZm9yIGVhY2ggb2YgdGhlIHRyZWF0bWVudCB0eXBlczsgY29udHJvbCAoYmx1ZSksIGFuZCBHZXJtLWZyZWUgKGdyZWVuKS5UaGlzIGNhbiBzaG93IGlmIHRyZWF0bWVudHMgZWZmZWN0IGhvdyBsb25nIHRoZSBtaWNlIHN1cnZpdmVkLiAKKioqKgoKYGBge3J9CnBsb3QoZGF5cyB+IGlkLCBkYXRhID0gbW91c2UsIGNvbD0nYmxhY2snLAogICAgIG1haW49IkRheXMgYnkgSUQiKQpgYGAKCmBgYHtyfQpwbG90KGRheXMgfiBpZCwgZGF0YSA9IG1vdXNlLCBwY2ggPSA0LCBjb2w9J2JsYWNrJywKICAgICBtYWluPSJEYXlzIGJ5IElEIikKYGBgCgoKKioqKgojIyMjIEFuc3dlcjoKVGhlIGZpcnN0IGNvZGUgaXMgdXNlZCB0byBzaG93IGhvdyBsb25nIGVhY2ggbW91c2UgKGJ5IGlkKSBzdXJ2aXZlZC4gVGhlIHNlY29uZCBjb2RlIGp1c3QgY2hhbmdlcyB0aGUgY2lyY2xlcyBpbnRvIGFuIFguIAoqKioqCgojIyMjIEV4ZXJjaXNlIDU6IGNyZWF0ZSBhIGJveHBsb3QgZm9yICJkYXlzIiBieSAib3V0Y29tZSIsIHRoaXMgcGxvdCBzaG91bGQgaW5jbHVkZSB0aGUgZm9sbG93aW5nCip1bmlxdWUgY29sb3JzIGZvciBlYWNoIG91dGNvbWUKKmEgcGxvdCB0aXRsZQoKYGBge3J9CmJveHBsb3QoZGF5c35vdXRjb21lLAogICAgICAgIGRhdGE9IG1vdXNlLAogICAgICAgIGNvbD0gYygicGluayIsInR1cnF1b2lzZSIsICJza3libHVlIiksCiAgICAgICAgbWFpbj0gIk51bWJlciBvZiBEYXlzIGJ5IE91dGNvbWUiLAogICAgICAgIHhsYWI9Ik91dGNvbWUiLAogICAgICAgIHlsYWI9IkRheXMiKQpgYGAKCiMjIyMgRXhlcmNpc2UgNjogbG9va2luZyBhdCBzdW1tYXJpZXMgb2YgY2F0ZWdvcmljYWwgdmFyaWFibGVzCldlIHByZXZpb3VzbHkgbG9va2VkIGF0IHRoZSBtZWFuLCBtZWRpYW4sIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIG51bWVyaWNhbCAiZGF5cyIgdmFyaWFibGUsIGJ1dCBvdGhlciB2YXJpYWJsZXMgYXJlIHN0aWxsIG9mIGludGVyZXN0IHRvIHJlc2VhcmNoZXJzLCBzdWNoIGFzIGNhbmNlciB0eXBlIG9yICJvdXRjb21lIiwgd2UgY2FuJ3QgaG93ZXZlciwgY2FsY3VsYXRlIG1lYW5zIG9mIGNhdGVnb3JpZXMsIHNvIGluc3RlYWQgbGV0J3MgbG9vayBhdCBzb21lIG90aGVyIHN1bW1hcnkgaW5mb3JtYXRpb24gd2UgY2FuIG9idGFpbi4uLgoKVGhlIGNvZGUgY2h1bmsgYmVsb3cgc2hvd3MgaG93IHdlIGNhbiBleHRyYWN0IGEgdGFibGUgb2YgY291bnRzL2ZyZXF1ZW5jaWVzIGZvciBjYW5jZXIgb3V0Y29tZXM6CmBgYHtyfQp0YWJsZShtb3VzZSRvdXRjb21lKQpgYGAKCk9uZSBjb21tb24gcHJhY3RpY2UgaW4gYmlvbG9naWNhbCBzdGF0aXN0aWNzIGlzIHRvIHN0YW5kYXJkaXplIHZhbHVlcyAodXN1YWxseSBkb25lIGJ5IGNyZWF0aW5nIHBlcmNlbnRhZ2VzKSwgdGhpcyBhbGxvd3MgdXMgdG8gYmV0dGVyIG1ha2UgY29tcGFyaXNvbnMgYmV0d2VlbiBncm91cHMgb3IgZGF0YS4gSW4gb3JkZXIgZm9yIHVzIHRvIHRha2UgdGhlIGNvdW50cyB0aGF0IGFyZSBvdXRwdXQgaW4gdGhlIGNvZGUgYWJvdmUgYW5kIHR1cm4gdGhlbSBpbnRvIHBlcmNlbnRhZ2VzIG9yIHByb3BvcnRpb25zLCB3ZSBuZWVkIHRvIGRpdmlkZSBieSB0aGUgdG90YWwgbnVtYmVyIG9mIGNhc2VzLCBpbiB0aGlzIGNhc2UsIHRoYXQncyB0aGUgdG90YWwgbnVtYmVyIG9mIHJvd3MgaW4gdGhlIGRhdGFzZXQuCgpUaGUgY29kZSBiZWxvdyBkb2VzIHRoZSBmb2xsb3dpbmc6IGl0IGNyZWF0ZXMgYW5kIHN0b3JlcyBhIHZhcmlhYmxlIHRvIHJlcHJlc2VudCB0aGUgdG90YWwgbnVtYmVyIG9mIHJvd3MsIHRoZW4gaXQgZGl2aWRlcyBvdXIgdGFibGUgY291bnRzIGJ5IHRoYXQgdmFsdWUgLSB3aGF0IGdldHMgb3V0cHV0IGlzIHRoZSBwcm9wb3J0aW9uLgoKYGBge3J9Cm4gPC0gbGVuZ3RoKG1vdXNlJG91dGNvbWUpCnRhYmxlKG1vdXNlJG91dGNvbWUpL24KYGBgCgojIyMjIENIQUxMRU5HRTogY3JlYXRlIGEgY29kZSB0aGF0IGNhbGN1bGF0ZXMgdGhlIFBFUkNFTlQgb2YgZWFjaCBjYW5jZXIgdHlwZSAtIHVzZSB0aGUgY29kZSBjaHVuayBiZWxvdzoKCmBgYHtyfQpwcm9wLnRhYmxlKHRhYmxlKG1vdXNlJG91dGNvbWUpKSAqIDEwMApgYGAKCiMjIyMgRXhlcmNpc2UgNzogcGFyc2luZyBvdXQgY291bnRzL2ZyZXF1ZW5jaWVzIGJ5IGFub3RoZXIgdmFyaWFibGUKQWJvdmUgd2UgdXNlZCB0aGUgdGFwcGx5KCkgYW5kIGFnZ3JlZ2F0ZSgpIGNvZGVzIHRvIGNhbGN1bGF0ZSBtZWFucyBieSBkaWZmZXJlbnQgZ3JvdXBzIG9yIHZhcmlhYmxlcywgd2hhdCBpZiB3ZSB3YW50ZWQgdG8gZG8gdGhlIHNhbWUgZm9yIG91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZSAib3V0Y29tZSI/CgpUaGUgY29kZSBiZWxvdyBjcmVhdGVzIGEgdGFibGUgb2YgIm91dGNvbWUiIGJ5ICJ0cnQiLCB0aGlzIHdpbGwgYWxsb3cgdXMgdG8gc2VlIGlmIHRoZXJlIHNlZW1zIHRvIGJlIGNlcnRhaW4gY2FuY2VyIHR5cGVzIG1vcmUgYXNzb2NpYXRlZCB3aXRoIGNlcnRhaW4gdHJlYXRtZW50cwoKYGBge3J9CmNhbmNlcl9kZXZlbG9wZWQ8LXRhYmxlKG1vdXNlJG91dGNvbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vdXNlJHRydCkKY2FuY2VyX2RldmVsb3BlZApgYGAKCldoYXQgcGF0dGVybnMgZG8geW91IG5vdGljZSBmcm9tIHRoZSB0YWJsZSB0aGF0IGdldHMgb3V0cHV0dGVkIGJ5IHRoZSBjb2RlPwoKKioqKgojIyMjIEFuc3dlcjpJIG5vdGljZWQgdGhhdCBmb3IgIm90aGVyIiBhbmQgInRoeW1pYyBseW1waG9tYSIgY2F0ZWdvcmllcyB0aGVyZSB3ZXJlYSBjbG9zZSBudW1iZXIgb2YgbWljZSBpbiBib3RoIG91dGNvbWUgZ3JvdXBzLiBUaGVyZSB3YXMgYSBtYWpvciBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGNvbnRyb2wgYW5kIGdlcm0tZnJlZSBudW1iZXJzIHdpdGggdGhlICJyZXRpY3VsdW0gY2VsbCBzYXJjb21hIi4gSXQgc2VlbWVkIGxpa2UgdGhlIHJldGljdWx1bSB3YXMgbW9yZSBjb21tb24gaW4gdGhlIGNvbnRyb2wgZ3JvdXAuIAoKCioqKioKCgpQTEVBU0UgQ09OVkVSVCBUSElTIFRPIEFOIEhUTUwgRklMRSBBTkQgVVBMT0FEIElUIFRPIENBTlZBUyEKCg==