# Import metadata
metadata <-read.csv("~/Documents/gbru_fy18_rice_methane/march2020/metadata_biomassCH4_noRIL9.csv", header=TRUE)

Explore uni-variate distributions of data

library(tidyverse)
metadata %>%
  keep(is.numeric) %>% 
  gather() %>% 
  ggplot(aes(value)) +
    facet_wrap(~ key, scales = "free") +
    geom_histogram(bins=12)

Genotype vs Sum Methane

d <- ggplot(metadata, aes(genotype, sum_ch4))
d + geom_point(aes(color=dev))

Total methane is highly consistent across treatment time point for each genotype.

Genotype vs Daily Methane

d <- ggplot(metadata, aes(genotype, daily_ch4))
d + geom_point(aes(color=dev))

D2 is the high methane producing time-point

Total methane and root biomass

d <- ggplot(metadata[metadata$dev=="D3",], aes(sum_ch4, root_biomass_2017))
d + geom_point(aes(colour = factor(genotype)))

Total methane and shoot biomass

d <- ggplot(metadata[metadata$dev=="D3",], aes((sum_ch4), log10(shoot_root_ratio2017)))
d + geom_point(aes(colour = factor(genotype)))

Load taxonomic count data

# Import OTU counts
otudata<-read.table("~/Documents/gbru_fy18_rice_methane/march2020/otu_table.tsv", header=TRUE)
# Move feature ID to rownames
row.names(otudata)<-otudata$feature.id
otudata<-otudata[,-1]
# Sort columns by name
otudata<- otudata[, order(names(otudata))]
# load Taxonomy annotation 
taxa <- read.table("~/Documents/gbru_fy18_rice_methane/march2020/observation_meta_data.tsv", sep="\t", header=TRUE, quote = "")

Define function to filter taxa with low abundance and many zeros


#Define the geometric mean for all values greater than 0
geomean <- function(x) { exp(mean(log(x[x>0]))) }

# Create a function to filter rows by the proportion of nonzero samples and the geometric mean of the nonzero samples
prefilter <- function(x, zcutoff, mcutoff){
    nzvect <- apply(x, 1, function(y){
      ((sum(y>0)/length(y))> zcutoff) & (geomean(y)> mcutoff)
      })
    lowcounts <- t(as.data.frame(apply(x[!nzvect,],2,sum)))
    rownames(lowcounts)<-c("lowconts")
    df1 <-rbind(lowcounts, x[nzvect,])
    return(df1)
}

Group by Family and Genus

Initial tests of un-grouped and unfiltered data returned no significant taxa. Independent filtering by depth is something which has been done in DESeq2 and EdgeR and is considered a valid preselection technique.

#Filter data to specific taxonomic levels
cdata <-cbind(taxa,otudata)
library(dplyr)
library(tidyr)

fd_long<- gather(cdata, sample, count, colnames(cdata)[10:105], factor_key=TRUE)

#group by family
fd_fam_tally <- fd_long[,c(7,10,11)] %>% group_by(taxonomy_5, sample) %>%  summarise(n = sum(count))
fd_fam_wide <- pivot_wider(fd_fam_tally, names_from= sample, values_from=n)
df_fam_wide<- as.data.frame(fd_fam_wide)
rownames(df_fam_wide)<- df_fam_wide[,1]
df_fam_wide<- df_fam_wide[,-1]
otutaxa_fam<-prefilter(df_fam_wide, 0.5, 100)

#group by genus
fd_genus_tally <- fd_long[,c(8,10,11)] %>% group_by(taxonomy_6, sample) %>%  summarise(n = sum(count))
fd_genus_wide <- fd_genus_tally %>% pivot_wider(names_from= sample, values_from=n)
df_genus_wide<- as.data.frame(fd_genus_wide)
rownames(df_genus_wide)<- df_genus_wide[,1]
df_genus_wide<- df_genus_wide[,-1]
otutaxa_genus<-prefilter(df_genus_wide, 0.5, 100)

ALDEx2 statistical analysis for compositional count data at the family level

library("ALDEx2")

# Construct covariates matrix
covariates1 <- data.frame(genotype=metadata$genotype, sumch4=log10(metadata$sum_ch4), dev=metadata$dev)
# Process 

#select D3 developmental stage 
d3cov<-  covariates1[covariates1$dev=="D3",]
d3cov<-d3cov[1:30,]
d3rows <- as.numeric(rownames(d3cov))
d3otus <- otutaxa_fam[,d3rows]

# create model matrix for log10 of total methane
mm1 <- model.matrix(~ sumch4, d3cov)

Run Centered log ratio transformations and Dirichlet sampling

# run CLR transformations and sampling
d3ch4fam.clr<-  aldex.clr(otutaxa_fam[,d3rows], mm1, mc.samples = 128, denom="all", verbose=TRUE, useMC=TRUE)
multicore environment is is OK -- using the BiocParallel package
removed rows with sums equal to zero
computing center with all features
data format is OK
'package:stats' may not be available when loading'package:stats' may not be available when loadingdirichlet samples complete
'package:stats' may not be available when loading'package:stats' may not be available when loadingtransformation complete

Fit a GLM on total methane

# run CLR transformations and sampling
d3ch4fam.clr.glm<- aldex.glm(d3ch4fam.clr, verbose=TRUE)
running tests for each MC instance:
|------------(25%)----------(50%)----------(75%)----------|
d3ch4fam.clr.glm[d3ch4fam.clr.glm$`model.sumch4 Pr(>|t|).BH`<0.5,]

Results

Because there are no significant taxa after BH correction. The challenge of regressing this data is that each sample does not have its own menthane measurment whic reduces the degrees of freedom

Do a correlation test

corr.test.fam <- aldex.corr(d3ch4fam.clr, d3cov$sumch4)

Results

Eight families have a signifigant statistical association with methane in the correlation test

corr.test.fam[corr.test.fam$BH<0.05,]
hist(corr.test.fam$BH)

ALDEx22 statistical analysis for compositional count data at the Genus Level

Run Centered log ratio transformations and Dirichlet sampling

# run CLR transformations and sampling
d3ch4genus.clr<-  aldex.clr(otutaxa_genus[,d3rows], mm1, mc.samples = 128, denom="all", verbose=TRUE, useMC=TRUE)
multicore environment is is OK -- using the BiocParallel package
removed rows with sums equal to zero
computing center with all features
data format is OK
'package:stats' may not be available when loading'package:stats' may not be available when loadingdirichlet samples complete
'package:stats' may not be available when loading'package:stats' may not be available when loadingtransformation complete

Fit a GLM on total methane

# run CLR transformations and sampling
d3ch4genus.clr.glm<- aldex.glm(d3ch4genus.clr, verbose=TRUE)
running tests for each MC instance:
|------------(25%)----------(50%)----------(75%)----------|

Results

Because there are no significant taxa after BH correction. The challenge of regressing this data is that each sample does not have its own menthane measurment whic reduces the degrees of freedom

d3ch4genus.clr.glm[d3ch4genus.clr.glm$`model.sumch4 Pr(>|t|).BH`<0.5,]

Do a correlation test

corr.test.fam <- aldex.corr(d3ch4genus.clr, d3cov$sumch4)

Results

Eight families have a signifigant statistical association with methane in the correlation test

corr.test.fam[corr.test.fam$BH<0.10,]

# New apprach: Split methane into a categoical variable and do a Welche’s test on high vs low methane

# Construct covariates matrix
covariates2 <- data.frame(genotype=metadata$genotype, sumch4=log10(metadata$sum_ch4), dev=metadata$dev)
# Process 

#select D3 developmental stage 
d3cov<-  covariates2[covariates2$dev=="D3",]
d3cov<-d3cov[1:30,]
d3cov$methfactor<-cut(d3cov$sumch4,breaks=2)
d3rows <- as.numeric(rownames(d3cov))
d3otus <- otutaxa_fam[,d3rows]

# create model matrix for log10 of total methane
mm1 <- model.matrix(~ methfactor, d3cov)

hlmeth.clr <- aldex.clr(d3otus, as.character(d3cov$methfactor), mc.samples=128, denom="iqlr")
operating in serial mode
computing iqlr centering
hlmeth.test <- aldex.ttest(hlmeth.clr, hist.plot=TRUE )

hlmeth.test[hlmeth.test$we.eBH<0.1,]

## Results Spliting into high and low methane at D2 did not highlihght new groups.

# Run the methane GLM anaysis for timepoint D2

## Construct new covariates matrix

covariates1 <- data.frame(genotype=metadata$genotype, sumch4=log10(metadata$sum_ch4), dev=metadata$dev)
# Process 

#select D3 developmental stage 
d2cov<-  covariates1[covariates1$dev=="D2",]
d2cov<-d2cov[1:30,] # Remove soil samples
d2rows <- as.numeric(rownames(d2cov))
d2otus <- otutaxa_fam[,d2rows]

# create model matrix for log10 of total methane
mm2 <- model.matrix(~ sumch4, d2cov)

Run Centered log ratio transformations and Dirichlet sampling


## Run Centered log ratio transformations and Dirichlet sampling

d2ch4fam.clr<-  aldex.clr(otutaxa_fam[,d2rows], mm2, mc.samples = 128, denom="all", verbose=TRUE, useMC=TRUE)
multicore environment is is OK -- using the BiocParallel package
removed rows with sums equal to zero
computing center with all features
data format is OK
'package:stats' may not be available when loading'package:stats' may not be available when loadingdirichlet samples complete
'package:stats' may not be available when loading'package:stats' may not be available when loadingtransformation complete

Fit a GLM on total methane

# run CLR transformations and sampling
d2ch4fam.clr.glm<- aldex.glm(d2ch4fam.clr, verbose=TRUE)
running tests for each MC instance:
|------------(25%)----------(50%)----------(75%)----------|
d2ch4fam.clr.glm[d2ch4fam.clr.glm$`model.sumch4 Pr(>|t|).BH`<0.5,]

Results

There were no signifigant effects at stage D2

#Test RIL6 (lowest emitter) and RIL1 (highest emmitter) at D3


c16<-covariates1[covariates1$genotype %in% c("RIL1", "RIL6") & covariates1$dev=="D3",]
c16rows <- as.numeric(rownames(c16))
c16otus <- otutaxa_fam[,c16rows]

hlgeno.clr <- aldex.clr(c16otus, c16$genotype, mc.samples=128, denom="iqlr")
operating in serial mode
computing iqlr centering
hlgeno.test <- aldex.ttest(hlmeth.clr, hist.plot=TRUE )

# run CLR transformations and sampling
hlgeno.test[hlgeno.test$we.eBH<0.1,]
LS0tCnRpdGxlOiAiRXhwbG9yYXRvcnkgYW5hbHlzaXMgb2YgcmljZSBtZXRoYW5lIGRhdGEgc2V0IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgoKYGBge3J9CiMgSW1wb3J0IG1ldGFkYXRhCm1ldGFkYXRhIDwtcmVhZC5jc3YoIn4vRG9jdW1lbnRzL2dicnVfZnkxOF9yaWNlX21ldGhhbmUvbWFyY2gyMDIwL21ldGFkYXRhX2Jpb21hc3NDSDRfbm9SSUw5LmNzdiIsIGhlYWRlcj1UUlVFKQpgYGAKCiMgRXhwbG9yZSB1bmktdmFyaWF0ZSBkaXN0cmlidXRpb25zIG9mIGRhdGEKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQptZXRhZGF0YSAlPiUKICBrZWVwKGlzLm51bWVyaWMpICU+JSAKICBnYXRoZXIoKSAlPiUgCiAgZ2dwbG90KGFlcyh2YWx1ZSkpICsKICAgIGZhY2V0X3dyYXAofiBrZXksIHNjYWxlcyA9ICJmcmVlIikgKwogICAgZ2VvbV9oaXN0b2dyYW0oYmlucz0xMikKYGBgCgojIEdlbm90eXBlIHZzIFN1bSBNZXRoYW5lCmBgYHtyfQpkIDwtIGdncGxvdChtZXRhZGF0YSwgYWVzKGdlbm90eXBlLCBzdW1fY2g0KSkKZCArIGdlb21fcG9pbnQoYWVzKGNvbG9yPWRldikpCgpgYGAKVG90YWwgbWV0aGFuZSBpcyBoaWdobHkgY29uc2lzdGVudCBhY3Jvc3MgdHJlYXRtZW50IHRpbWUgcG9pbnQgZm9yIGVhY2ggZ2Vub3R5cGUuCgojIEdlbm90eXBlIHZzIERhaWx5IE1ldGhhbmUKYGBge3J9CmQgPC0gZ2dwbG90KG1ldGFkYXRhLCBhZXMoZ2Vub3R5cGUsIGRhaWx5X2NoNCkpCmQgKyBnZW9tX3BvaW50KGFlcyhjb2xvcj1kZXYpKQoKYGBgCkQyIGlzIHRoZSBoaWdoIG1ldGhhbmUgcHJvZHVjaW5nIHRpbWUtcG9pbnQgCgojIFRvdGFsIG1ldGhhbmUgYW5kIHJvb3QgYmlvbWFzcwpgYGB7cn0KZCA8LSBnZ3Bsb3QobWV0YWRhdGFbbWV0YWRhdGEkZGV2PT0iRDMiLF0sIGFlcyhzdW1fY2g0LCByb290X2Jpb21hc3NfMjAxNykpCmQgKyBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBmYWN0b3IoZ2Vub3R5cGUpKSkKYGBgCgojIFRvdGFsIG1ldGhhbmUgYW5kIHNob290IGJpb21hc3MKYGBge3J9CmQgPC0gZ2dwbG90KG1ldGFkYXRhW21ldGFkYXRhJGRldj09IkQzIixdLCBhZXMoKHN1bV9jaDQpLCBsb2cxMChzaG9vdF9yb290X3JhdGlvMjAxNykpKQpkICsgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gZmFjdG9yKGdlbm90eXBlKSkpCmBgYAoKIyBMb2FkIHRheG9ub21pYyBjb3VudCBkYXRhCmBgYHtyfQojIEltcG9ydCBPVFUgY291bnRzCm90dWRhdGE8LXJlYWQudGFibGUoIn4vRG9jdW1lbnRzL2dicnVfZnkxOF9yaWNlX21ldGhhbmUvbWFyY2gyMDIwL290dV90YWJsZS50c3YiLCBoZWFkZXI9VFJVRSkKIyBNb3ZlIGZlYXR1cmUgSUQgdG8gcm93bmFtZXMKcm93Lm5hbWVzKG90dWRhdGEpPC1vdHVkYXRhJGZlYXR1cmUuaWQKb3R1ZGF0YTwtb3R1ZGF0YVssLTFdCiMgU29ydCBjb2x1bW5zIGJ5IG5hbWUKb3R1ZGF0YTwtIG90dWRhdGFbLCBvcmRlcihuYW1lcyhvdHVkYXRhKSldCiMgbG9hZCBUYXhvbm9teSBhbm5vdGF0aW9uIAp0YXhhIDwtIHJlYWQudGFibGUoIn4vRG9jdW1lbnRzL2dicnVfZnkxOF9yaWNlX21ldGhhbmUvbWFyY2gyMDIwL29ic2VydmF0aW9uX21ldGFfZGF0YS50c3YiLCBzZXA9Ilx0IiwgaGVhZGVyPVRSVUUsIHF1b3RlID0gIiIpCgpgYGAKCiMgRGVmaW5lIGZ1bmN0aW9uIHRvIGZpbHRlciB0YXhhIHdpdGggbG93IGFidW5kYW5jZSBhbmQgbWFueSB6ZXJvcyAKCmBgYHtyfQoKI0RlZmluZSB0aGUgZ2VvbWV0cmljIG1lYW4gZm9yIGFsbCB2YWx1ZXMgZ3JlYXRlciB0aGFuIDAKZ2VvbWVhbiA8LSBmdW5jdGlvbih4KSB7IGV4cChtZWFuKGxvZyh4W3g+MF0pKSkgfQoKIyBDcmVhdGUgYSBmdW5jdGlvbiB0byBmaWx0ZXIgcm93cyBieSB0aGUgcHJvcG9ydGlvbiBvZiBub256ZXJvIHNhbXBsZXMgYW5kIHRoZSBnZW9tZXRyaWMgbWVhbiBvZiB0aGUgbm9uemVybyBzYW1wbGVzCnByZWZpbHRlciA8LSBmdW5jdGlvbih4LCB6Y3V0b2ZmLCBtY3V0b2ZmKXsKICAgIG56dmVjdCA8LSBhcHBseSh4LCAxLCBmdW5jdGlvbih5KXsKICAgICAgKChzdW0oeT4wKS9sZW5ndGgoeSkpPiB6Y3V0b2ZmKSAmIChnZW9tZWFuKHkpPiBtY3V0b2ZmKQogICAgICB9KQogICAgbG93Y291bnRzIDwtIHQoYXMuZGF0YS5mcmFtZShhcHBseSh4WyFuenZlY3QsXSwyLHN1bSkpKQogICAgcm93bmFtZXMobG93Y291bnRzKTwtYygibG93Y29udHMiKQogICAgZGYxIDwtcmJpbmQobG93Y291bnRzLCB4W256dmVjdCxdKQogICAgcmV0dXJuKGRmMSkKfQpgYGAKCgojIEdyb3VwIGJ5IEZhbWlseSBhbmQgR2VudXMKSW5pdGlhbCB0ZXN0cyBvZiB1bi1ncm91cGVkIGFuZCB1bmZpbHRlcmVkIGRhdGEgcmV0dXJuZWQgbm8gc2lnbmlmaWNhbnQgdGF4YS4gSW5kZXBlbmRlbnQgZmlsdGVyaW5nIGJ5IGRlcHRoIGlzIHNvbWV0aGluZyB3aGljaCBoYXMgYmVlbiBkb25lIGluIERFU2VxMiBhbmQgRWRnZVIgYW5kIGlzIGNvbnNpZGVyZWQgYSB2YWxpZCBwcmVzZWxlY3Rpb24gdGVjaG5pcXVlLiAgCmBgYHtyfQojRmlsdGVyIGRhdGEgdG8gc3BlY2lmaWMgdGF4b25vbWljIGxldmVscwpjZGF0YSA8LWNiaW5kKHRheGEsb3R1ZGF0YSkKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKCmZkX2xvbmc8LSBnYXRoZXIoY2RhdGEsIHNhbXBsZSwgY291bnQsIGNvbG5hbWVzKGNkYXRhKVsxMDoxMDVdLCBmYWN0b3Jfa2V5PVRSVUUpCgojZ3JvdXAgYnkgZmFtaWx5CmZkX2ZhbV90YWxseSA8LSBmZF9sb25nWyxjKDcsMTAsMTEpXSAlPiUgZ3JvdXBfYnkodGF4b25vbXlfNSwgc2FtcGxlKSAlPiUgIHN1bW1hcmlzZShuID0gc3VtKGNvdW50KSkKZmRfZmFtX3dpZGUgPC0gcGl2b3Rfd2lkZXIoZmRfZmFtX3RhbGx5LCBuYW1lc19mcm9tPSBzYW1wbGUsIHZhbHVlc19mcm9tPW4pCmRmX2ZhbV93aWRlPC0gYXMuZGF0YS5mcmFtZShmZF9mYW1fd2lkZSkKcm93bmFtZXMoZGZfZmFtX3dpZGUpPC0gZGZfZmFtX3dpZGVbLDFdCmRmX2ZhbV93aWRlPC0gZGZfZmFtX3dpZGVbLC0xXQpvdHV0YXhhX2ZhbTwtcHJlZmlsdGVyKGRmX2ZhbV93aWRlLCAwLjUsIDEwMCkKCiNncm91cCBieSBnZW51cwpmZF9nZW51c190YWxseSA8LSBmZF9sb25nWyxjKDgsMTAsMTEpXSAlPiUgZ3JvdXBfYnkodGF4b25vbXlfNiwgc2FtcGxlKSAlPiUgIHN1bW1hcmlzZShuID0gc3VtKGNvdW50KSkKZmRfZ2VudXNfd2lkZSA8LSBmZF9nZW51c190YWxseSAlPiUgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbT0gc2FtcGxlLCB2YWx1ZXNfZnJvbT1uKQpkZl9nZW51c193aWRlPC0gYXMuZGF0YS5mcmFtZShmZF9nZW51c193aWRlKQpyb3duYW1lcyhkZl9nZW51c193aWRlKTwtIGRmX2dlbnVzX3dpZGVbLDFdCmRmX2dlbnVzX3dpZGU8LSBkZl9nZW51c193aWRlWywtMV0Kb3R1dGF4YV9nZW51czwtcHJlZmlsdGVyKGRmX2dlbnVzX3dpZGUsIDAuNSwgMTAwKQpgYGAKCgojIEFMREV4MiBzdGF0aXN0aWNhbCBhbmFseXNpcyBmb3IgY29tcG9zaXRpb25hbCBjb3VudCBkYXRhIGF0IHRoZSBmYW1pbHkgbGV2ZWwKYGBge3J9CmxpYnJhcnkoIkFMREV4MiIpCgojIENvbnN0cnVjdCBjb3ZhcmlhdGVzIG1hdHJpeApjb3ZhcmlhdGVzMSA8LSBkYXRhLmZyYW1lKGdlbm90eXBlPW1ldGFkYXRhJGdlbm90eXBlLCBzdW1jaDQ9bG9nMTAobWV0YWRhdGEkc3VtX2NoNCksIGRldj1tZXRhZGF0YSRkZXYpCiMgUHJvY2VzcyAKCiNzZWxlY3QgRDMgZGV2ZWxvcG1lbnRhbCBzdGFnZSAKZDNjb3Y8LSAgY292YXJpYXRlczFbY292YXJpYXRlczEkZGV2PT0iRDMiLF0KZDNjb3Y8LWQzY292WzE6MzAsXQpkM3Jvd3MgPC0gYXMubnVtZXJpYyhyb3duYW1lcyhkM2NvdikpCmQzb3R1cyA8LSBvdHV0YXhhX2ZhbVssZDNyb3dzXQoKIyBjcmVhdGUgbW9kZWwgbWF0cml4IGZvciBsb2cxMCBvZiB0b3RhbCBtZXRoYW5lCm1tMSA8LSBtb2RlbC5tYXRyaXgofiBzdW1jaDQsIGQzY292KQoKCmBgYAoKIyMgUnVuIENlbnRlcmVkIGxvZyByYXRpbyB0cmFuc2Zvcm1hdGlvbnMgYW5kIERpcmljaGxldCBzYW1wbGluZwpgYGB7cn0KIyBydW4gQ0xSIHRyYW5zZm9ybWF0aW9ucyBhbmQgc2FtcGxpbmcKZDNjaDRmYW0uY2xyPC0gIGFsZGV4LmNscihvdHV0YXhhX2ZhbVssZDNyb3dzXSwgbW0xLCBtYy5zYW1wbGVzID0gMTI4LCBkZW5vbT0iYWxsIiwgdmVyYm9zZT1UUlVFLCB1c2VNQz1UUlVFKQpgYGAKCiMjIEZpdCBhIEdMTSBvbiB0b3RhbCBtZXRoYW5lCmBgYHtyfQojIHJ1biBDTFIgdHJhbnNmb3JtYXRpb25zIGFuZCBzYW1wbGluZwpkM2NoNGZhbS5jbHIuZ2xtPC0gYWxkZXguZ2xtKGQzY2g0ZmFtLmNsciwgdmVyYm9zZT1UUlVFKQpgYGAKYGBge3J9CmQzY2g0ZmFtLmNsci5nbG1bZDNjaDRmYW0uY2xyLmdsbSRgbW9kZWwuc3VtY2g0IFByKD58dHwpLkJIYDwwLjUsXQpgYGAKCiMjIyBSZXN1bHRzCkJlY2F1c2UgdGhlcmUgYXJlIG5vIHNpZ25pZmljYW50IHRheGEgYWZ0ZXIgQkggY29ycmVjdGlvbi4gVGhlIGNoYWxsZW5nZSBvZiByZWdyZXNzaW5nIHRoaXMgZGF0YSBpcyB0aGF0IGVhY2ggc2FtcGxlIGRvZXMgbm90IGhhdmUgaXRzIG93biBtZW50aGFuZSBtZWFzdXJtZW50IHdoaWMgcmVkdWNlcyB0aGUgZGVncmVlcyBvZiBmcmVlZG9tCgojIyBEbyBhIGNvcnJlbGF0aW9uIHRlc3QKYGBge3J9CmNvcnIudGVzdC5mYW0gPC0gYWxkZXguY29ycihkM2NoNGZhbS5jbHIsIGQzY292JHN1bWNoNCkKYGBgCgoKIyMjIFJlc3VsdHMKRWlnaHQgZmFtaWxpZXMgaGF2ZSBhIHNpZ25pZmlnYW50IHN0YXRpc3RpY2FsIGFzc29jaWF0aW9uIHdpdGggbWV0aGFuZSBpbiB0aGUgY29ycmVsYXRpb24gdGVzdApgYGB7cn0KY29yci50ZXN0LmZhbVtjb3JyLnRlc3QuZmFtJEJIPDAuMDUsXQpgYGAKCmBgYHtyfQpoaXN0KGNvcnIudGVzdC5mYW0kQkgpCmBgYAoKIyBBTERFeDIyIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGZvciBjb21wb3NpdGlvbmFsIGNvdW50IGRhdGEgYXQgdGhlIEdlbnVzIExldmVsCgojIyBSdW4gQ2VudGVyZWQgbG9nIHJhdGlvIHRyYW5zZm9ybWF0aW9ucyBhbmQgRGlyaWNobGV0IHNhbXBsaW5nCmBgYHtyfQojIHJ1biBDTFIgdHJhbnNmb3JtYXRpb25zIGFuZCBzYW1wbGluZwpkM2NoNGdlbnVzLmNscjwtICBhbGRleC5jbHIob3R1dGF4YV9nZW51c1ssZDNyb3dzXSwgbW0xLCBtYy5zYW1wbGVzID0gMTI4LCBkZW5vbT0iYWxsIiwgdmVyYm9zZT1UUlVFLCB1c2VNQz1UUlVFKQpgYGAKCiMjIEZpdCBhIEdMTSBvbiB0b3RhbCBtZXRoYW5lCmBgYHtyfQojIHJ1biBDTFIgdHJhbnNmb3JtYXRpb25zIGFuZCBzYW1wbGluZwpkM2NoNGdlbnVzLmNsci5nbG08LSBhbGRleC5nbG0oZDNjaDRnZW51cy5jbHIsIHZlcmJvc2U9VFJVRSkKYGBgCgojIyMgUmVzdWx0cwpCZWNhdXNlIHRoZXJlIGFyZSBubyBzaWduaWZpY2FudCB0YXhhIGFmdGVyIEJIIGNvcnJlY3Rpb24uIFRoZSBjaGFsbGVuZ2Ugb2YgcmVncmVzc2luZyB0aGlzIGRhdGEgaXMgdGhhdCBlYWNoIHNhbXBsZSBkb2VzIG5vdCBoYXZlIGl0cyBvd24gbWVudGhhbmUgbWVhc3VybWVudCB3aGljIHJlZHVjZXMgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbQpgYGB7cn0KZDNjaDRnZW51cy5jbHIuZ2xtW2QzY2g0Z2VudXMuY2xyLmdsbSRgbW9kZWwuc3VtY2g0IFByKD58dHwpLkJIYDwwLjUsXQpgYGAKCiMjIERvIGEgY29ycmVsYXRpb24gdGVzdApgYGB7cn0KY29yci50ZXN0LmZhbSA8LSBhbGRleC5jb3JyKGQzY2g0Z2VudXMuY2xyLCBkM2NvdiRzdW1jaDQpCmBgYAoKCiMjIyBSZXN1bHRzCkVpZ2h0IGZhbWlsaWVzIGhhdmUgYSBzaWduaWZpZ2FudCBzdGF0aXN0aWNhbCBhc3NvY2lhdGlvbiB3aXRoIG1ldGhhbmUgaW4gdGhlIGNvcnJlbGF0aW9uIHRlc3QKYGBge3J9CmNvcnIudGVzdC5mYW1bY29yci50ZXN0LmZhbSRCSDwwLjEwLF0KYGBgCgoKIAogIyBOZXcgYXBwcmFjaDogU3BsaXQgbWV0aGFuZSBpbnRvIGEgY2F0ZWdvaWNhbCB2YXJpYWJsZSBhbmQgZG8gYSBXZWxjaGUncyB0ZXN0IG9uIGhpZ2ggdnMgbG93IG1ldGhhbmUKICAKYGBge3J9CiMgQ29uc3RydWN0IGNvdmFyaWF0ZXMgbWF0cml4CmNvdmFyaWF0ZXMyIDwtIGRhdGEuZnJhbWUoZ2Vub3R5cGU9bWV0YWRhdGEkZ2Vub3R5cGUsIHN1bWNoND1sb2cxMChtZXRhZGF0YSRzdW1fY2g0KSwgZGV2PW1ldGFkYXRhJGRldikKIyBQcm9jZXNzIAoKI3NlbGVjdCBEMyBkZXZlbG9wbWVudGFsIHN0YWdlIApkM2NvdjwtICBjb3ZhcmlhdGVzMltjb3ZhcmlhdGVzMiRkZXY9PSJEMyIsXQpkM2NvdjwtZDNjb3ZbMTozMCxdCmQzY292JG1ldGhmYWN0b3I8LWN1dChkM2NvdiRzdW1jaDQsYnJlYWtzPTIpCmQzcm93cyA8LSBhcy5udW1lcmljKHJvd25hbWVzKGQzY292KSkKZDNvdHVzIDwtIG90dXRheGFfZmFtWyxkM3Jvd3NdCgojIGNyZWF0ZSBtb2RlbCBtYXRyaXggZm9yIGxvZzEwIG9mIHRvdGFsIG1ldGhhbmUKbW0xIDwtIG1vZGVsLm1hdHJpeCh+IG1ldGhmYWN0b3IsIGQzY292KQoKaGxtZXRoLmNsciA8LSBhbGRleC5jbHIoZDNvdHVzLCBhcy5jaGFyYWN0ZXIoZDNjb3YkbWV0aGZhY3RvciksIG1jLnNhbXBsZXM9MTI4LCBkZW5vbT0iaXFsciIpCmhsbWV0aC50ZXN0IDwtIGFsZGV4LnR0ZXN0KGhsbWV0aC5jbHIsIGhpc3QucGxvdD1UUlVFICkKCmBgYAogCmBgYHtyfQpobG1ldGgudGVzdFtobG1ldGgudGVzdCR3ZS5lQkg8MC4xLF0KYGBgCiAjIyBSZXN1bHRzCiBTcGxpdGluZyBpbnRvIGhpZ2ggYW5kIGxvdyBtZXRoYW5lIGF0IEQyIGRpZCBub3QgaGlnaGxpaGdodCBuZXcgZ3JvdXBzLgogCiAjIFJ1biB0aGUgbWV0aGFuZSBHTE0gYW5heXNpcyBmb3IgdGltZXBvaW50IEQyCiAKIAogIyMgQ29uc3RydWN0IG5ldyBjb3ZhcmlhdGVzIG1hdHJpeAogCmBgYHtyfQpjb3ZhcmlhdGVzMSA8LSBkYXRhLmZyYW1lKGdlbm90eXBlPW1ldGFkYXRhJGdlbm90eXBlLCBzdW1jaDQ9bG9nMTAobWV0YWRhdGEkc3VtX2NoNCksIGRldj1tZXRhZGF0YSRkZXYpCiMgUHJvY2VzcyAKCiNzZWxlY3QgRDMgZGV2ZWxvcG1lbnRhbCBzdGFnZSAKZDJjb3Y8LSAgY292YXJpYXRlczFbY292YXJpYXRlczEkZGV2PT0iRDIiLF0KZDJjb3Y8LWQyY292WzE6MzAsXSAjIFJlbW92ZSBzb2lsIHNhbXBsZXMKZDJyb3dzIDwtIGFzLm51bWVyaWMocm93bmFtZXMoZDJjb3YpKQpkMm90dXMgPC0gb3R1dGF4YV9mYW1bLGQycm93c10KCiMgY3JlYXRlIG1vZGVsIG1hdHJpeCBmb3IgbG9nMTAgb2YgdG90YWwgbWV0aGFuZQptbTIgPC0gbW9kZWwubWF0cml4KH4gc3VtY2g0LCBkMmNvdikKYGBgCiAKIyMgUnVuIENlbnRlcmVkIGxvZyByYXRpbyB0cmFuc2Zvcm1hdGlvbnMgYW5kIERpcmljaGxldCBzYW1wbGluZwpgYGB7cn0KZDJjaDRmYW0uY2xyPC0gIGFsZGV4LmNscihvdHV0YXhhX2ZhbVssZDJyb3dzXSwgbW0yLCBtYy5zYW1wbGVzID0gMTI4LCBkZW5vbT0iYWxsIiwgdmVyYm9zZT1UUlVFLCB1c2VNQz1UUlVFKQpgYGAKCiMjIEZpdCBhIEdMTSBvbiB0b3RhbCBtZXRoYW5lCmBgYHtyfQojIHJ1biBDTFIgdHJhbnNmb3JtYXRpb25zIGFuZCBzYW1wbGluZwpkMmNoNGZhbS5jbHIuZ2xtPC0gYWxkZXguZ2xtKGQyY2g0ZmFtLmNsciwgdmVyYm9zZT1UUlVFKQpgYGAKCmBgYHtyfQpkMmNoNGZhbS5jbHIuZ2xtW2QyY2g0ZmFtLmNsci5nbG0kYG1vZGVsLnN1bWNoNCBQcig+fHR8KS5CSGA8MC41LF0KYGBgCgojIyBSZXN1bHRzClRoZXJlIHdlcmUgbm8gc2lnbmlmaWdhbnQgZWZmZWN0cyBhdCBzdGFnZSBEMgoKCiNUZXN0IFJJTDYgKGxvd2VzdCBlbWl0dGVyKSBhbmQgUklMMSAoaGlnaGVzdCBlbW1pdHRlcikgYXQgRDMKYGBge3J9CgpjMTY8LWNvdmFyaWF0ZXMxW2NvdmFyaWF0ZXMxJGdlbm90eXBlICVpbiUgYygiUklMMSIsICJSSUw2IikgJiBjb3ZhcmlhdGVzMSRkZXY9PSJEMyIsXQpjMTZyb3dzIDwtIGFzLm51bWVyaWMocm93bmFtZXMoYzE2KSkKYzE2b3R1cyA8LSBvdHV0YXhhX2ZhbVssYzE2cm93c10KCmhsZ2Vuby5jbHIgPC0gYWxkZXguY2xyKGMxNm90dXMsIGMxNiRnZW5vdHlwZSwgbWMuc2FtcGxlcz0xMjgsIGRlbm9tPSJpcWxyIikKaGxnZW5vLnRlc3QgPC0gYWxkZXgudHRlc3QoaGxtZXRoLmNsciwgaGlzdC5wbG90PVRSVUUgKQpgYGAKCmBgYHtyfQojIHJ1biBDTFIgdHJhbnNmb3JtYXRpb25zIGFuZCBzYW1wbGluZwpobGdlbm8udGVzdFtobGdlbm8udGVzdCR3ZS5lQkg8MC4xLF0KYGBg