Load data from counting scripts
library(compositions)
# read library totals
tot<- read.csv("~/Documents/collaboratorProjects/chip_hunter_maize_TIR/data/totals.txt", sep ="\t", header=F)
Option 1: Close the composition using the total reads
These steps perform the closure operation telling it the total number of reads, then cast the data as a count composition dataframe that sums to 1. Finally we calculate a centered log ratio transformation on the data.
compclosed <- clo(X=a2t,total=tot[,1], detectionlimit= 1)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
# create a ccount composition dataset
a2c<-ccomp(compclosed, total=1)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
#calulate a centered log ratio transform
a2d <- clr(a2c)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
Heatmap
A heat map of all data shows some general trends (forward and reverse probes tend to group together)
# plot a heat map of the results
library(gplots)
Attaching package: ‘gplots’
The following object is masked from ‘package:stats’:
lowess
library(viridis)
Loading required package: viridisLite
heatmap.2(a2d, col=viridis, scale="none",trace="none")

Analysis of known homozygotes and heterozygotes
Next we attempt to plot the forward and reverse data for two probes where we know Homozygous samples are in 1-15 and heterozygous are in 18-30. This data is the clr values for the dataset closed on all reads.
plot(a2d[,85])

plot(a2d[,86])

fr = a2d[,85] + a2d[,86]
plot(fr)# Plot mean and SD of Homo

mean(fr[1:15])
[1] 0.7546468
msd(fr[1:15])
[1] 1.601614
#Plot mean and SD of Hetero
mean(fr[18:30])
[1] 0.401688
msd(fr[18:30])
[1] 1.581361
The data is not very distinguishable. Other normalization approaches are needed.
Option 2: Close the composition using the total mapped reads
compclosed2 <- clo(X=a2t, detectionlimit= 1)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
# create a ccount composition dataset
a2c2<-ccomp(compclosed2, total=1)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
#calulate a centered log ratio transform
a2d2 <- clr(a2c2)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
Analysis of known homozygotes and heterozygotes
Next we attempt to plot the forward and reverse data for two probes where we know Homozygous samples are in 1-15 and heterozygous are in 18-30.
This data is the count composition value for each probe
plot(a2c2[,85])

plot(a2c2[,86])

fr = a2c2[,85] + a2c2[,86]
plot(fr)

# Plot mean and SD of Homo
mean(fr[1:15])
[1] 0.03628429
msd(fr[1:15])
[1] 0.02337816
#Plot mean and SD of Hetero
mean(fr[18:30])
[1] 0.03999595
msd(fr[18:30])
[1] 0.02945496
This data is the clr transformation of the count composition value for each probe
# plot the clr data for probes "Probe087-mu1017716-F", "Probe088-mu1017716-R" where we know half are heterozygous and half are homozugous
plot(a2d2[,85])

plot(a2d2[,86])

fr = a2d2[,85] + a2d2[,86]
plot(fr)

# Plot mean and SD of Homo
mean(fr[1:15])
[1] 0.7546468
msd(fr[1:15])
[1] 1.601614
#Plot mean and SD of Hetero
mean(fr[18:30])
[1] 0.401688
msd(fr[18:30])
[1] 1.581361
Neither approach is easily separable.
Option 3: treat the unmapped reads as a component of the composition
cs <-colSums(a2)
nonmapped <- tot$reads-cs
a3 <- rbind(a2,nonmapped)
rownames(a3)[145]<-"nonmapped"
a3t=t(a3)
a3c<-ccomp(a3t, total=1)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
a3d <- clr(a3c)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
Heatmap
A heat map of all data shows some general trends (forward and reverse probes tend to group together)
# plot a heat map of the results
library(gplots)
library(viridis)
heatmap.2(a3d, col=viridis, scale="none",trace="none")

Analysis of known homozygotes and heterozygotes
plot(a3c[,85])

plot(a3c[,86])

fr = a3c[,85] + a3c[,86]
plot(fr)

# Plot mean and SD of Homo
mean(fr[1:15])
[1] 4.432075e-05
msd(fr[1:15])
[1] 7.462433e-05
#Plot mean and SD of Hetero
mean(fr[18:30])
[1] 3.889691e-05
msd(fr[18:30])
[1] 4.013475e-05
These results are closer being seperable
plot the clr of the compositional data for probes “Probe087-mu1017716-F”, “Probe088-mu1017716-R” where we know half are heterozygous and half are homozugous
plot(a3d[,85])

plot(a3d[,86])

fr = a3d[,85] + a3d[,86]
plot(fr)

# Plot mean and SD of Homo
mean(fr[1:15])
[1] 1.473779
msd(fr[1:15])
[1] 2.061553
#Plot mean and SD of Hetero
mean(fr[18:30])
[1] 1.415554
msd(fr[18:30])
[1] 2.028346
the trend is less clear
Option 4: Additive log ratio
Use the additive log ratio with non-mapped reads as the common denominator
a3a <- alr(a3c,ivar=145)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
plot the compositional data for probes “Probe087-mu1017716-F”, “Probe088-mu1017716-R” where we know half are heterozygous and half are homozugous
plot(a3a[,85])

plot(a3a[,86])

fr = a3a[,85] + a3a[,86]
plot(fr)

# Plot mean and SD of Homo
mean(fr[1:15])
[1] -Inf
msd(fr[1:15])
[1] NaN
#Plot mean and SD of Hetero
mean(fr[18:30])
[1] -Inf
msd(fr[18:30])
[1] NaN
Again the means appear to be different but there is not a clear separation
Option 5: Balances
Balances are the geometric means of log ratios between sub-components of the data. We take the dataset where untapped is a component and we compare the log ratios of the forward probe to un-mapped. Again the data is not separable
a3acomp <- acomp(a3t)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
bal85 <- balance(X=acomp(a3t),expr= ~ (Probe087-mu1017716-F) / nonmapped)
Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
Consider 'structure(list(), *)' instead.
plot(bal85[,1])

Option 6: simple normalization
For comparison here is simple normalization
simplenorm <- sweep(a2c, 2, tot[,1], "/")
STATS does not recycle exactly across MARGIN
plot(simplenorm[,85])

plot(simplenorm[,86])

Results
The best approach seems to be creating a compositional count dataset with the non mapped reads as a component. However, the difference is not enough to reliably classify the data.
Option 8: normalize by tircounts
For comparison here is simple normalization
tirnorm <- sweep(a2c, 2, tirlong, "/")
STATS does not recycle exactly across MARGIN
plot(tirnorm[,85])

plot(tirnorm[,86])

Enrichment efficiency
plot(log(rowSums(a2t)/tot[,1]))

table(a2t[,30] < 5)
FALSE TRUE
24 6
Enrichment efficiency using tircounts as the numerator
plot((tirlong/tot[,1]))

mean(log(tirlong/tot[,1]))
[1] -3.258941
sd(log(tirlong/tot[,1]))
[1] 0.7283162
LS0tCnRpdGxlOiAiI0FuYWx5emluZyBjb21wb3NpdGlvbmFsIGNvdW50IGRhdGEgZnJvbSBNYWl6ZSBUSVIgZXhwZXJpbWVudCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgTG9hZCBkYXRhIGZyb20gY291bnRpbmcgc2NyaXB0cwoKYGBge3J9CmxpYnJhcnkoY29tcG9zaXRpb25zKQojIHJlYWQgbGlicmFyeSB0b3RhbHMKdG90PC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL2NvbGxhYm9yYXRvclByb2plY3RzL2NoaXBfaHVudGVyX21haXplX1RJUi9kYXRhL3RvdGFscy50eHQiLCBzZXAgPSJcdCIsIGhlYWRlcj1GKQpuYW1lcyh0b3QpPC1jKCJyZWFkcyIsImxpYnJhcnkiKQojIGxvYWQgaW4gY291bnRzCmEyIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9jb2xsYWJvcmF0b3JQcm9qZWN0cy9jaGlwX2h1bnRlcl9tYWl6ZV9USVIvZGF0YS9maW5hbGNvdW50czMuY3N2IikKIyBjcmVhdGUgYSBkYXRhZnJhbWUgZm9yIHVzZSBpbiB0aGUgY29tcG9zaXRpb25zIHBhY2thZ2UKYTIgPC1hMlssLTFdCnJvd25hbWVzKGEyKTwtYTJbLDFdCmEyPC1hMlssLTFdCmEyW2lzLm5hKGEyKV0gPC0gMAphMnQ8LXQoYTIpCiMgUmFtb3ZlIHRpcmxvbmcgdmFsdWVzCnRpcmxvbmcgPC0gYTJ0WywxNDVdCmEydCA8LSBhMnRbLDE6MTQ0XQpgYGAKCgoKIyBPcHRpb24gMTogQ2xvc2UgdGhlIGNvbXBvc2l0aW9uIHVzaW5nIHRoZSB0b3RhbCByZWFkcwoKVGhlc2Ugc3RlcHMgcGVyZm9ybSB0aGUgY2xvc3VyZSBvcGVyYXRpb24gdGVsbGluZyBpdCB0aGUgdG90YWwgbnVtYmVyIG9mIHJlYWRzLCB0aGVuIGNhc3QgdGhlIGRhdGEgYXMgYSBjb3VudCBjb21wb3NpdGlvbiBkYXRhZnJhbWUgdGhhdCBzdW1zIHRvIDEuIEZpbmFsbHkgd2UgY2FsY3VsYXRlIGEgY2VudGVyZWQgbG9nIHJhdGlvIHRyYW5zZm9ybWF0aW9uIG9uIHRoZSBkYXRhLgpgYGB7cn0KY29tcGNsb3NlZCA8LSBjbG8oWD1hMnQsdG90YWw9dG90WywxXSwgZGV0ZWN0aW9ubGltaXQ9IDEpCiMgY3JlYXRlIGEgY2NvdW50IGNvbXBvc2l0aW9uIGRhdGFzZXQKYTJjPC1jY29tcChjb21wY2xvc2VkLCB0b3RhbD0xKQojY2FsdWxhdGUgYSBjZW50ZXJlZCBsb2cgcmF0aW8gdHJhbnNmb3JtIAphMmQgPC0gY2xyKGEyYykKYGBgCgojIyBIZWF0bWFwCkEgaGVhdCBtYXAgb2YgYWxsIGRhdGEgc2hvd3Mgc29tZSBnZW5lcmFsIHRyZW5kcyAoZm9yd2FyZCBhbmQgcmV2ZXJzZSBwcm9iZXMgdGVuZCB0byBncm91cCB0b2dldGhlcikKYGBge3J9CiMgcGxvdCBhIGhlYXQgbWFwIG9mIHRoZSByZXN1bHRzCmxpYnJhcnkoZ3Bsb3RzKQpsaWJyYXJ5KHZpcmlkaXMpCmhlYXRtYXAuMihhMmQsIGNvbD12aXJpZGlzLCBzY2FsZT0ibm9uZSIsdHJhY2U9Im5vbmUiKQpgYGAKCiMjIEFuYWx5c2lzIG9mIGtub3duIGhvbW96eWdvdGVzIGFuZCBoZXRlcm96eWdvdGVzCgpOZXh0IHdlIGF0dGVtcHQgdG8gcGxvdCB0aGUgZm9yd2FyZCBhbmQgcmV2ZXJzZSBkYXRhIGZvciB0d28gcHJvYmVzIHdoZXJlIHdlIGtub3cgSG9tb3p5Z291cyBzYW1wbGVzIGFyZSBpbiAxLTE1IGFuZCBoZXRlcm96eWdvdXMgYXJlIGluIDE4LTMwLiBUaGlzIGRhdGEgaXMgdGhlIGNsciB2YWx1ZXMgZm9yIHRoZSBkYXRhc2V0IGNsb3NlZCBvbiBhbGwgcmVhZHMuCmBgYHtyfQpwbG90KGEyZFssODVdKQpwbG90KGEyZFssODZdKQpmciA9IGEyZFssODVdICsgYTJkWyw4Nl0KcGxvdChmcikjIFBsb3QgbWVhbiBhbmQgU0Qgb2YgSG9tbwptZWFuKGZyWzE6MTVdKQptc2QoZnJbMToxNV0pCiNQbG90IG1lYW4gYW5kIFNEIG9mIEhldGVybwptZWFuKGZyWzE4OjMwXSkKbXNkKGZyWzE4OjMwXSkKYGBgCgpUaGUgZGF0YSBpcyBub3QgdmVyeSBkaXN0aW5ndWlzaGFibGUuIE90aGVyIG5vcm1hbGl6YXRpb24gYXBwcm9hY2hlcyBhcmUgbmVlZGVkLgoKCiMgT3B0aW9uIDI6IENsb3NlIHRoZSBjb21wb3NpdGlvbiB1c2luZyB0aGUgdG90YWwgbWFwcGVkIHJlYWRzCgpgYGB7cn0KY29tcGNsb3NlZDIgPC0gY2xvKFg9YTJ0LCBkZXRlY3Rpb25saW1pdD0gMSkKIyBjcmVhdGUgYSBjY291bnQgY29tcG9zaXRpb24gZGF0YXNldAphMmMyPC1jY29tcChjb21wY2xvc2VkMiwgdG90YWw9MSkKI2NhbHVsYXRlIGEgY2VudGVyZWQgbG9nIHJhdGlvIHRyYW5zZm9ybSAKYTJkMiA8LSBjbHIoYTJjMikKYGBgCgojIyBBbmFseXNpcyBvZiBrbm93biBob21venlnb3RlcyBhbmQgaGV0ZXJvenlnb3RlcwoKTmV4dCB3ZSBhdHRlbXB0IHRvIHBsb3QgdGhlIGZvcndhcmQgYW5kIHJldmVyc2UgZGF0YSBmb3IgdHdvIHByb2JlcyB3aGVyZSB3ZSBrbm93IEhvbW96eWdvdXMgc2FtcGxlcyBhcmUgaW4gMS0xNSBhbmQgaGV0ZXJvenlnb3VzIGFyZSBpbiAxOC0zMC4gCgpUaGlzIGRhdGEgaXMgdGhlIGNvdW50IGNvbXBvc2l0aW9uIHZhbHVlIGZvciBlYWNoIHByb2JlCmBgYHtyfQoKcGxvdChhMmMyWyw4NV0pCnBsb3QoYTJjMlssODZdKQpmciA9IGEyYzJbLDg1XSArIGEyYzJbLDg2XQpwbG90KGZyKQoKIyBQbG90IG1lYW4gYW5kIFNEIG9mIEhvbW8KbWVhbihmclsxOjE1XSkKbXNkKGZyWzE6MTVdKQojUGxvdCBtZWFuIGFuZCBTRCBvZiBIZXRlcm8KbWVhbihmclsxODozMF0pCm1zZChmclsxODozMF0pCmBgYAogCgpUaGlzIGRhdGEgaXMgdGhlIGNsciB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgY291bnQgY29tcG9zaXRpb24gdmFsdWUgZm9yIGVhY2ggcHJvYmUKYGBge3J9CiMgcGxvdCB0aGUgY2xyIGRhdGEgZm9yIHByb2JlcyAiUHJvYmUwODctbXUxMDE3NzE2LUYiLCAiUHJvYmUwODgtbXUxMDE3NzE2LVIiIHdoZXJlIHdlIGtub3cgaGFsZiBhcmUgaGV0ZXJvenlnb3VzIGFuZCBoYWxmIGFyZSBob21venVnb3VzCnBsb3QoYTJkMlssODVdKQpwbG90KGEyZDJbLDg2XSkKZnIgPSBhMmQyWyw4NV0gKyBhMmQyWyw4Nl0KcGxvdChmcikKIyBQbG90IG1lYW4gYW5kIFNEIG9mIEhvbW8KbWVhbihmclsxOjE1XSkKbXNkKGZyWzE6MTVdKQojUGxvdCBtZWFuIGFuZCBTRCBvZiBIZXRlcm8KbWVhbihmclsxODozMF0pCm1zZChmclsxODozMF0pCmBgYApOZWl0aGVyIGFwcHJvYWNoIGlzIGVhc2lseSBzZXBhcmFibGUuCgojIE9wdGlvbiAzOiB0cmVhdCB0aGUgdW5tYXBwZWQgcmVhZHMgYXMgYSBjb21wb25lbnQgb2YgdGhlIGNvbXBvc2l0aW9uICAKCmBgYHtyfQpjcyA8LWNvbFN1bXMoYTIpCm5vbm1hcHBlZCA8LSB0b3QkcmVhZHMtY3MKYTMgPC0gcmJpbmQoYTIsbm9ubWFwcGVkKQpyb3duYW1lcyhhMylbMTQ1XTwtIm5vbm1hcHBlZCIKYTN0PXQoYTMpCmEzYzwtY2NvbXAoYTN0LCB0b3RhbD0xKQphM2QgPC0gY2xyKGEzYykKYGBgCgojIyBIZWF0bWFwCgpBIGhlYXQgbWFwIG9mIGFsbCBkYXRhIHNob3dzIHNvbWUgZ2VuZXJhbCB0cmVuZHMgKGZvcndhcmQgYW5kIHJldmVyc2UgcHJvYmVzIHRlbmQgdG8gZ3JvdXAgdG9nZXRoZXIpCmBgYHtyfQojIHBsb3QgYSBoZWF0IG1hcCBvZiB0aGUgcmVzdWx0cwpsaWJyYXJ5KGdwbG90cykKbGlicmFyeSh2aXJpZGlzKQpoZWF0bWFwLjIoYTNkLCBjb2w9dmlyaWRpcywgc2NhbGU9Im5vbmUiLHRyYWNlPSJub25lIikKYGBgCiMjIEFuYWx5c2lzIG9mIGtub3duIGhvbW96eWdvdGVzIGFuZCBoZXRlcm96eWdvdGVzCmBgYHtyfQoKcGxvdChhM2NbLDg1XSkKcGxvdChhM2NbLDg2XSkKZnIgPSBhM2NbLDg1XSArIGEzY1ssODZdCnBsb3QoZnIpCiMgUGxvdCBtZWFuIGFuZCBTRCBvZiBIb21vCm1lYW4oZnJbMToxNV0pCm1zZChmclsxOjE1XSkKI1Bsb3QgbWVhbiBhbmQgU0Qgb2YgSGV0ZXJvCm1lYW4oZnJbMTg6MzBdKQptc2QoZnJbMTg6MzBdKQpgYGAKClRoZXNlIHJlc3VsdHMgYXJlIGNsb3NlciBiZWluZyBzZXBlcmFibGUKCiMjIyBwbG90IHRoZSBjbHIgb2YgdGhlICBjb21wb3NpdGlvbmFsIGRhdGEgZm9yIHByb2JlcyAiUHJvYmUwODctbXUxMDE3NzE2LUYiLCAiUHJvYmUwODgtbXUxMDE3NzE2LVIiIHdoZXJlIHdlIGtub3cgaGFsZiBhcmUgaGV0ZXJvenlnb3VzIGFuZCBoYWxmIGFyZSBob21venVnb3VzCmBgYHtyfQoKcGxvdChhM2RbLDg1XSkKcGxvdChhM2RbLDg2XSkKZnIgPSBhM2RbLDg1XSArIGEzZFssODZdCnBsb3QoZnIpCiMgUGxvdCBtZWFuIGFuZCBTRCBvZiBIb21vCm1lYW4oZnJbMToxNV0pCm1zZChmclsxOjE1XSkKI1Bsb3QgbWVhbiBhbmQgU0Qgb2YgSGV0ZXJvCm1lYW4oZnJbMTg6MzBdKQptc2QoZnJbMTg6MzBdKQoKYGBgCnRoZSB0cmVuZCBpcyBsZXNzIGNsZWFyCgojIE9wdGlvbiA0OiBBZGRpdGl2ZSBsb2cgcmF0aW8KVXNlIHRoZSBhZGRpdGl2ZSBsb2cgcmF0aW8gd2l0aCAgbm9uLW1hcHBlZCByZWFkcyBhcyB0aGUgY29tbW9uIGRlbm9taW5hdG9yCmBgYHtyfQphM2EgPC0gYWxyKGEzYyxpdmFyPTE0NSkKYGBgCgojIyMgcGxvdCB0aGUgY29tcG9zaXRpb25hbCBkYXRhIGZvciBwcm9iZXMgIlByb2JlMDg3LW11MTAxNzcxNi1GIiwgIlByb2JlMDg4LW11MTAxNzcxNi1SIiB3aGVyZSB3ZSBrbm93IGhhbGYgYXJlIGhldGVyb3p5Z291cyBhbmQgaGFsZiBhcmUgaG9tb3p1Z291cwpgYGB7cn0KCnBsb3QoYTNhWyw4NV0pCnBsb3QoYTNhWyw4Nl0pCmZyID0gYTNhWyw4NV0gKyBhM2FbLDg2XQpwbG90KGZyKQojIFBsb3QgbWVhbiBhbmQgU0Qgb2YgSG9tbwptZWFuKGZyWzE6MTVdKQptc2QoZnJbMToxNV0pCiNQbG90IG1lYW4gYW5kIFNEIG9mIEhldGVybwptZWFuKGZyWzE4OjMwXSkKbXNkKGZyWzE4OjMwXSkKYGBgCkFnYWluIHRoZSBtZWFucyBhcHBlYXIgdG8gYmUgZGlmZmVyZW50IGJ1dCB0aGVyZSBpcyBub3QgYSBjbGVhciBzZXBhcmF0aW9uCgojIE9wdGlvbiA1OiBCYWxhbmNlcwpCYWxhbmNlcyBhcmUgdGhlIGdlb21ldHJpYyBtZWFucyBvZiBsb2cgcmF0aW9zIGJldHdlZW4gc3ViLWNvbXBvbmVudHMgb2YgdGhlIGRhdGEuIFdlIHRha2UgdGhlIGRhdGFzZXQgd2hlcmUgdW50YXBwZWQgaXMgYSBjb21wb25lbnQgYW5kIHdlIGNvbXBhcmUgdGhlIGxvZyByYXRpb3Mgb2YgdGhlIGZvcndhcmQgcHJvYmUgdG8gdW4tbWFwcGVkLiBBZ2FpbiB0aGUgZGF0YSBpcyBub3Qgc2VwYXJhYmxlCmBgYHtyfQphM2Fjb21wIDwtIGFjb21wKGEzdCkKYmFsODUgPC0gYmFsYW5jZShYPWFjb21wKGEzdCksZXhwcj0gfiAoUHJvYmUwODctbXUxMDE3NzE2LUYpIC8gbm9ubWFwcGVkKQpwbG90KGJhbDg1WywxXSkKYGBgCgojIE9wdGlvbiA2OiBzaW1wbGUgbm9ybWFsaXphdGlvbgoKRm9yIGNvbXBhcmlzb24gaGVyZSBpcyBzaW1wbGUgbm9ybWFsaXphdGlvbgpgYGB7cn0Kc2ltcGxlbm9ybSA8LSBzd2VlcChhMmMsIDIsIHRvdFssMV0sICIvIikKcGxvdChzaW1wbGVub3JtWyw4NV0pCnBsb3Qoc2ltcGxlbm9ybVssODZdKQpgYGAKCiMgUmVzdWx0cwoKVGhlIGJlc3QgYXBwcm9hY2ggc2VlbXMgdG8gYmUgY3JlYXRpbmcgYSBjb21wb3NpdGlvbmFsIGNvdW50IGRhdGFzZXQgd2l0aCB0aGUgbm9uIG1hcHBlZCByZWFkcyBhcyBhIGNvbXBvbmVudC4gSG93ZXZlciwgdGhlIGRpZmZlcmVuY2UgaXMgbm90IGVub3VnaCB0byByZWxpYWJseSBjbGFzc2lmeSB0aGUgZGF0YS4KCiMgT3B0aW9uIDg6IG5vcm1hbGl6ZSBieSB0aXJjb3VudHMKCkZvciBjb21wYXJpc29uIGhlcmUgaXMgc2ltcGxlIG5vcm1hbGl6YXRpb24KYGBge3J9CnRpcm5vcm0gPC0gc3dlZXAoYTJjLCAyLCB0aXJsb25nLCAiLyIpCnBsb3QodGlybm9ybVssODVdKQpwbG90KHRpcm5vcm1bLDg2XSkKYGBgCiMgRW5yaWNobWVudCBlZmZpY2llbmN5CgpgYGB7cn0KcGxvdChsb2cocm93U3VtcyhhMnQpL3RvdFssMV0pKQoKdGFibGUoYTJ0WywzMF0gPCA1KQoKYGBgCiNFbnJpY2htZW50IGVmZmljaWVuY3kgdXNpbmcgdGlyY291bnRzIGFzIHRoZSBudW1lcmF0b3IKYGBge3J9CnBsb3QoKHRpcmxvbmcvdG90WywxXSkpCm1lYW4obG9nKHRpcmxvbmcvdG90WywxXSkpCnNkKGxvZyh0aXJsb25nL3RvdFssMV0pKQpgYGAK