After fertilization but prior to the onset of zygotic transcription, the C. elegans zygote cleaves asymmetrically to create the anterior AB and posterior P1 blastomeres, each of which goes on to generate distinct cell lineages. To understand how patterns of RNA inheritance and abundance arise after this first asymmetric cell division, we pooled hand-dissected AB and P1 blastomeres and performed RNA-seq. http://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE59943

The reads have been aligned to the genome and summarized to gene level in the Rsubread tutorial.

library(tidyverse)
library(edgeR)
## Loading required package: limma
## 
## Attaching package: 'limma'
## The following object is masked from 'package:BiocGenerics':
## 
##     plotMA

#Read featurecounts object

We import the featurecounts object that we have stored.

fc <- readRDS("fcElegans.rds")
names(fc)
## [1] "counts"     "annotation" "targets"    "stat"
counts_featurecounts <- fc$counts
head(counts_featurecounts)
##                SRR1532959.bam SRR1532960.bam SRR1532961.bam SRR1532962.bam
## WBGene00197333              0              0              0              0
## WBGene00198386              0              0              0              0
## WBGene00015153              0              0              0              0
## WBGene00002061            152            253            157             95
## WBGene00255704              0              0              0              0
## WBGene00235314              0              0              0              0
##                SRR1532963.bam SRR1532964.bam
## WBGene00197333              0              0
## WBGene00198386              0              0
## WBGene00015153              1              2
## WBGene00002061            144            152
## WBGene00255704              0              0
## WBGene00235314              0              0
dim(counts_featurecounts)
## [1] 46904     6
fc$stat
##                           Status SRR1532959.bam SRR1532960.bam SRR1532961.bam
## 1                       Assigned        1657500        1323934        2013110
## 2            Unassigned_Unmapped          98398         257946          67401
## 3           Unassigned_Read_Type              0              0              0
## 4           Unassigned_Singleton              0              0              0
## 5      Unassigned_MappingQuality              0              0              0
## 6             Unassigned_Chimera              0              0              0
## 7      Unassigned_FragmentLength              0              0              0
## 8           Unassigned_Duplicate              0              0              0
## 9        Unassigned_MultiMapping              0              0              0
## 10          Unassigned_Secondary              0              0              0
## 11           Unassigned_NonSplit              0              0              0
## 12         Unassigned_NoFeatures           9430          11104          10279
## 13 Unassigned_Overlapping_Length              0              0              0
## 14          Unassigned_Ambiguity          18542          17985          26523
##    SRR1532962.bam SRR1532963.bam SRR1532964.bam
## 1         1304759        2568046        2208253
## 2           82920         108861          92578
## 3               0              0              0
## 4               0              0              0
## 5               0              0              0
## 6               0              0              0
## 7               0              0              0
## 8               0              0              0
## 9               0              0              0
## 10              0              0              0
## 11              0              0              0
## 12           5867          11931           9791
## 13              0              0              0
## 14          16467          47238          27401

0.1 Read Meta Data

target <- readRDS("elegansMetaData.rds")

1 Data Analysis

1.1 Setup count object edgeR

dge <- DGEList(fc$counts)
substr(colnames(dge),1,10)==target$Run
## [1] TRUE TRUE TRUE TRUE TRUE TRUE

Order of information in target file and count table is the same

colnames(dge) <- paste0(target$`cell type:ch1`,target$`replicate:ch1`)
cellType <- as.factor(target$`cell type:ch1`)

1.2 Normalisation

dge <- calcNormFactors(dge)

1.3 Data exploration

One way to reduce dimensionality is the use of multidimensional scaling (MDS). For MDS, we first have to calculate all pairwise distances between our objects (samples in this case), and then create a (typically) two-dimensional representation where these pre-calculated distances are represented as accurately as possible. This means that depending on how the pairwise sample distances are defined, the two-dimensional plot can be very different, and it is important to choose a distance that is suitable for the type of data at hand.

edgeR contains a function plotMDS, which operates on a DGEList object and generates a two-dimensional MDS representation of the samples. The default distance between two samples can be interpreted as the “typical” log fold change between the two samples, for the genes that are most different between them (by default, the top 500 genes, but this can be modified). We generate an MDS plot from the DGEList object dge, coloring by the treatment and using different plot symbols for different cell lines.

plotMDS(dge, top = 500, col = as.double(cellType))

1.4 Differential analysis

1.4.1 Filtering

design <- model.matrix(~cellType)
keep <- filterByExpr(dge, design)
dge <- dge[keep, ,keep.lib.sizes = FALSE]

The option keep.lib.sizes=FALSE causes the library sizes to be recomputed after the filtering. This is generally recommended, although the effect on the downstream analysis is usually small.

The normalisation factors have to be recalculated upon filtering.

dge <- calcNormFactors(dge)

1.4.2 Fit Model

We first estimate the overdispersion.

dge <- estimateDisp(dge, design)
plotBCV(dge)

Finally, we fit the generalized linear model and perform the test. In the glmLRT function, we indicate which coefficient (which column in the design matrix) that we would like to test for. It is possible to test more general contrasts as well, and the user guide contains many examples on how to do this. The topTags function extracts the top-ranked genes. You can indicate the adjusted p-value cutoff, and/or the number of genes to keep.

fit <- glmFit(dge, design)
lrt <- glmLRT(fit, coef = ncol(design))
ttAll <-topTags(lrt, n = nrow(dge)) # all genes

Note, that the workflow with glmFit and glmLRT is no longer the default workflow of edgeR. We will discuss this when we focus on the technical aspects of differential analysis of RNASeq data.

1.4.2.1 Evaluate distribution of p-values

hist(ttAll$table$PValue)

1.4.2.2 DE genes?

tt <- topTags(lrt, n = nrow(dge), p.value = 0.05) # genes with adj.p<0.05
knitr::kable(tt)
logFC logCPM LR PValue FDR
WBGene00011409 2.3051280 7.119802 73.05792 0.0000000 0.0000000
WBGene00017985 -1.7957089 7.372791 62.01882 0.0000000 0.0000000
WBGene00016824 -1.8923338 6.753206 60.58811 0.0000000 0.0000000
WBGene00019811 1.8317181 6.588456 48.07969 0.0000000 0.0000000
WBGene00000388 -1.5819410 7.523366 45.20634 0.0000000 0.0000000
WBGene00020948 -1.4293678 9.866419 44.42801 0.0000000 0.0000000
WBGene00000496 2.5765059 6.137689 44.36365 0.0000000 0.0000000
WBGene00021200 2.8405675 5.752301 43.29921 0.0000000 0.0000000
WBGene00017397 1.8053895 4.954892 39.44648 0.0000000 0.0000002
WBGene00010354 3.5189772 3.594563 36.90842 0.0000000 0.0000008
WBGene00021009 -2.5009414 5.901792 35.03340 0.0000000 0.0000018
WBGene00008823 -1.4590401 6.893432 33.67495 0.0000000 0.0000033
WBGene00009035 2.4812880 3.637571 33.33107 0.0000000 0.0000037
WBGene00008080 -1.5849757 6.273693 31.88531 0.0000000 0.0000072
WBGene00000863 -1.3206086 6.869690 31.18917 0.0000000 0.0000096
WBGene00009264 1.3101438 7.737531 29.98508 0.0000000 0.0000168
WBGene00019001 1.5310735 5.796877 29.80333 0.0000000 0.0000173
WBGene00009793 -1.5448441 6.443390 28.72037 0.0000001 0.0000286
WBGene00016823 -1.6283682 6.822229 28.52248 0.0000001 0.0000300
WBGene00009606 -1.6836921 7.018377 27.59933 0.0000001 0.0000422
WBGene00006562 1.2334479 8.237130 27.59138 0.0000001 0.0000422
WBGene00004374 1.3126857 8.205130 27.57883 0.0000002 0.0000422
WBGene00018009 -1.1679161 7.288469 27.24427 0.0000002 0.0000480
WBGene00009921 -1.4520825 7.509272 27.08123 0.0000002 0.0000501
WBGene00005022 3.0989396 3.072409 26.65312 0.0000002 0.0000600
WBGene00012031 1.6710488 5.983430 26.46157 0.0000003 0.0000637
WBGene00007145 1.3911358 5.955030 26.23073 0.0000003 0.0000691
WBGene00000550 1.8567741 6.986777 25.65848 0.0000004 0.0000869
WBGene00008464 -1.3691265 6.098891 25.59697 0.0000004 0.0000869
WBGene00002276 -1.7151651 7.783958 25.58421 0.0000004 0.0000869
WBGene00020721 1.1766318 6.785538 25.31562 0.0000005 0.0000967
WBGene00001333 -2.1906933 6.816367 25.20089 0.0000005 0.0000994
WBGene00015463 1.1298098 7.473493 23.97879 0.0000010 0.0001818
WBGene00004258 1.1255996 7.206061 23.83100 0.0000011 0.0001905
WBGene00015515 1.4428044 4.813602 23.46583 0.0000013 0.0002237
WBGene00020375 -1.1448080 9.964018 23.25288 0.0000014 0.0002430
WBGene00001402 1.3805811 5.396251 22.72596 0.0000019 0.0003106
WBGene00003994 1.1635326 7.673470 22.67691 0.0000019 0.0003106
WBGene00019792 -1.2852712 6.342227 22.31845 0.0000023 0.0003647
WBGene00010678 1.4904174 7.068914 22.21037 0.0000024 0.0003762
WBGene00008825 -1.0459065 9.314393 21.83429 0.0000030 0.0004464
WBGene00010048 1.2281757 6.560963 21.60210 0.0000034 0.0004919
WBGene00013765 1.8422391 5.233003 21.42048 0.0000037 0.0005282
WBGene00008789 -1.1018128 8.449436 20.27976 0.0000067 0.0009364
WBGene00011543 1.3377977 6.012064 20.19114 0.0000070 0.0009590
WBGene00018349 2.2981756 2.694337 19.98302 0.0000078 0.0010460
WBGene00000146 -1.0998566 9.314730 19.47284 0.0000102 0.0013369
WBGene00016029 2.3799083 2.545932 18.96458 0.0000133 0.0017084
WBGene00016955 -1.2883337 7.532638 18.90645 0.0000137 0.0017253
WBGene00017037 -1.2944945 5.432695 18.55934 0.0000165 0.0020284
WBGene00019890 1.0627183 6.801901 18.49984 0.0000170 0.0020517
WBGene00019892 1.2158317 5.784601 18.34878 0.0000184 0.0021782
WBGene00003229 -0.9372311 10.526524 18.21850 0.0000197 0.0022884
WBGene00000090 -1.3084139 7.318347 18.10653 0.0000209 0.0023820
WBGene00020269 -0.9985510 7.976130 17.82257 0.0000242 0.0027150
WBGene00011350 2.0098571 4.328635 17.34870 0.0000311 0.0034211
WBGene00001979 -0.8765155 8.474812 17.17564 0.0000341 0.0036816
WBGene00005019 1.0245921 7.112465 17.07943 0.0000358 0.0038061
WBGene00019710 1.4716330 4.586270 16.96655 0.0000380 0.0039708
WBGene00004855 -1.1541964 6.333543 16.42440 0.0000506 0.0051459
WBGene00017263 -0.9855036 8.581250 16.41151 0.0000510 0.0051459
WBGene00012716 1.0387739 7.859506 16.19168 0.0000572 0.0056320
WBGene00021440 0.8953822 6.731520 16.15533 0.0000584 0.0056320
WBGene00021467 -0.9242074 7.905627 16.14953 0.0000585 0.0056320
WBGene00011775 1.1204249 7.361743 15.96554 0.0000645 0.0061112
WBGene00005026 1.4272652 5.311851 15.79960 0.0000704 0.0065702
WBGene00008775 -1.1781239 7.984440 15.69945 0.0000742 0.0068239
WBGene00000585 1.0513345 6.756986 15.66281 0.0000757 0.0068551
WBGene00011153 -1.4629380 6.169867 15.49869 0.0000826 0.0073684
WBGene00001949 -1.0142771 6.977753 15.43446 0.0000854 0.0075142
WBGene00001492 -1.2619828 4.913039 14.75912 0.0001222 0.0105948
WBGene00012934 1.8036181 3.441028 14.66929 0.0001281 0.0109576
WBGene00010036 1.4099247 5.412889 14.60783 0.0001324 0.0111657
WBGene00000872 -0.9535369 6.287211 14.55322 0.0001363 0.0112802
WBGene00004076 1.4108462 4.517042 14.53766 0.0001374 0.0112802
WBGene00013381 1.5419159 3.944388 14.51101 0.0001393 0.0112904
WBGene00020771 -1.2922388 4.633363 14.33126 0.0001533 0.0122598
WBGene00020447 1.0656443 5.986732 14.24530 0.0001605 0.0126682
WBGene00004268 1.2772874 6.431653 13.99685 0.0001831 0.0140699
WBGene00015217 -1.9734551 3.064682 13.99320 0.0001835 0.0140699
WBGene00000537 0.9602926 6.110812 13.97690 0.0001851 0.0140699
WBGene00001566 1.4373083 5.172078 13.87318 0.0001956 0.0146868
WBGene00004094 1.6105546 3.673329 13.74675 0.0002092 0.0155199
WBGene00006934 1.0510840 5.928105 13.25434 0.0002719 0.0198006
WBGene00004373 1.3076155 6.353003 13.24497 0.0002733 0.0198006
WBGene00016486 -1.0003894 5.894267 13.13510 0.0002898 0.0207521
WBGene00003898 0.8692242 6.677060 13.01894 0.0003084 0.0218259
WBGene00020498 1.0154543 7.016678 12.65675 0.0003742 0.0261864
WBGene00009065 -1.2121033 6.659070 12.51676 0.0004033 0.0275513
WBGene00021051 1.3519472 4.947833 12.50484 0.0004059 0.0275513
WBGene00021352 -0.7553539 7.201147 12.47903 0.0004115 0.0275513
WBGene00010846 1.2226988 4.625478 12.47872 0.0004116 0.0275513
WBGene00008410 0.7656502 7.069255 12.41191 0.0004266 0.0282476
WBGene00008118 1.0221416 5.062304 12.38480 0.0004328 0.0283558
WBGene00016501 -0.7720642 9.024532 12.32469 0.0004470 0.0289754
WBGene00009559 0.7864199 7.725558 12.13651 0.0004944 0.0317165
WBGene00011225 1.8970620 3.966269 12.11100 0.0005013 0.0318218
WBGene00003026 1.4137142 4.879505 12.05388 0.0005168 0.0322426
WBGene00013529 -0.8337794 6.423924 12.04846 0.0005184 0.0322426
WBGene00011272 -0.9044026 6.470998 11.95771 0.0005442 0.0335128
WBGene00017951 -0.8492104 8.086303 11.84378 0.0005785 0.0352740
WBGene00013339 0.8364854 6.384117 11.80672 0.0005902 0.0356302
WBGene00020549 0.8701194 7.354495 11.65816 0.0006392 0.0382163
WBGene00002804 1.0513295 5.504499 11.59312 0.0006620 0.0391958
WBGene00004272 0.8604911 7.606023 11.57305 0.0006691 0.0392439
WBGene00011986 1.1433862 6.271676 11.48880 0.0007002 0.0406052
WBGene00018226 1.3684392 3.741883 11.47458 0.0007055 0.0406052
WBGene00019341 -0.7131633 6.992116 11.31288 0.0007697 0.0438879
WBGene00016632 -0.7425463 6.955333 11.22841 0.0008055 0.0455096
WBGene00015102 1.1349527 10.206572 11.12247 0.0008529 0.0477459
WBGene00004445 1.0439088 6.327324 11.05683 0.0008836 0.0490205
x
BH
x
cellTypeP1
x
glm

There are 111 genes differentially expressed.

1.4.3 Plots

We first make a volcanoplot and an MA plot.

library(ggplot2)
volcano<- ggplot(ttAll$table,aes(x=logFC,y=-log10(PValue),color=FDR<0.05)) + geom_point() + scale_color_manual(values=c("black","red"))
volcano

plotSmear(lrt, de.tags = row.names(tt$table))

Another way of representing the results of a differential expression analysis is to construct a heatmap of the top differentially expressed genes. Here, we would expect the contrasted sample groups to cluster separately. A heatmap is a “color coded expression matrix”, where the rows and columns are clustered using hierarchical clustering. Typically, it should not be applied to counts, but works better with transformed values. Here we show how it can be applied to the variance-stabilized values generated above. We choose the top 30 differentially expressed genes. There are many functions in R that can generate heatmaps, here we show the one from the pheatmap package.

library(pheatmap)
pheatmap(cpm(dge, log = TRUE)[rownames(tt$table)[1:30],])

LS0tCnRpdGxlOiAiRWxlZ2FuczogREUgYW5hbHlzaXMiCmF1dGhvcjogIkxpZXZlbiBDbGVtZW50IgpkYXRlOiAic3RhdE9taWNzLCBHaGVudCBVbml2ZXJzaXR5IChodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8pIgpvdXRwdXQ6CiAgICBodG1sX2RvY3VtZW50OgogICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgIHRoZW1lOiBjb3NtbwogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKQWZ0ZXIgZmVydGlsaXphdGlvbiBidXQgcHJpb3IgdG8gdGhlIG9uc2V0IG9mIHp5Z290aWMgdHJhbnNjcmlwdGlvbiwgdGhlIEMuIGVsZWdhbnMgenlnb3RlIGNsZWF2ZXMgYXN5bW1ldHJpY2FsbHkgdG8gY3JlYXRlIHRoZSBhbnRlcmlvciBBQiBhbmQgcG9zdGVyaW9yIFAxIGJsYXN0b21lcmVzLCBlYWNoIG9mIHdoaWNoIGdvZXMgb24gdG8gZ2VuZXJhdGUgZGlzdGluY3QgY2VsbCBsaW5lYWdlcy4gVG8gdW5kZXJzdGFuZCBob3cgcGF0dGVybnMgb2YgUk5BIGluaGVyaXRhbmNlIGFuZCBhYnVuZGFuY2UgYXJpc2UgYWZ0ZXIgdGhpcyBmaXJzdCBhc3ltbWV0cmljIGNlbGwgZGl2aXNpb24sIHdlIHBvb2xlZCBoYW5kLWRpc3NlY3RlZCBBQiBhbmQgUDEgYmxhc3RvbWVyZXMgYW5kIHBlcmZvcm1lZCBSTkEtc2VxLgpodHRwOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvZ2VvL3F1ZXJ5L2FjYy5jZ2k/YWNjPUdTRTU5OTQzCgpUaGUgcmVhZHMgaGF2ZSBiZWVuIGFsaWduZWQgdG8gdGhlIGdlbm9tZSBhbmQgc3VtbWFyaXplZCB0byBnZW5lIGxldmVsIGluIHRoZSBSc3VicmVhZCB0dXRvcmlhbC4KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShlZGdlUikKYGBgCgojUmVhZCBmZWF0dXJlY291bnRzIG9iamVjdAoKV2UgaW1wb3J0IHRoZSBmZWF0dXJlY291bnRzIG9iamVjdCB0aGF0IHdlIGhhdmUgc3RvcmVkLgoKYGBge3J9CmZjIDwtIHJlYWRSRFMoImZjRWxlZ2Fucy5yZHMiKQpuYW1lcyhmYykKY291bnRzX2ZlYXR1cmVjb3VudHMgPC0gZmMkY291bnRzCmhlYWQoY291bnRzX2ZlYXR1cmVjb3VudHMpCmRpbShjb3VudHNfZmVhdHVyZWNvdW50cykKZmMkc3RhdApgYGAKCiMjIFJlYWQgTWV0YSBEYXRhCgpgYGB7cn0KdGFyZ2V0IDwtIHJlYWRSRFMoImVsZWdhbnNNZXRhRGF0YS5yZHMiKQpgYGAKCiMgRGF0YSBBbmFseXNpcwojIyBTZXR1cCBjb3VudCBvYmplY3QgZWRnZVIKCmBgYHtyfQpkZ2UgPC0gREdFTGlzdChmYyRjb3VudHMpCnN1YnN0cihjb2xuYW1lcyhkZ2UpLDEsMTApPT10YXJnZXQkUnVuCmBgYAoKT3JkZXIgb2YgaW5mb3JtYXRpb24gaW4gdGFyZ2V0IGZpbGUgYW5kIGNvdW50IHRhYmxlIGlzIHRoZSBzYW1lCgpgYGB7cn0KY29sbmFtZXMoZGdlKSA8LSBwYXN0ZTAodGFyZ2V0JGBjZWxsIHR5cGU6Y2gxYCx0YXJnZXQkYHJlcGxpY2F0ZTpjaDFgKQpjZWxsVHlwZSA8LSBhcy5mYWN0b3IodGFyZ2V0JGBjZWxsIHR5cGU6Y2gxYCkKYGBgCgojIyBOb3JtYWxpc2F0aW9uCmBgYHtyfQpkZ2UgPC0gY2FsY05vcm1GYWN0b3JzKGRnZSkKYGBgCgojIyBEYXRhIGV4cGxvcmF0aW9uCgpPbmUgd2F5IHRvIHJlZHVjZSBkaW1lbnNpb25hbGl0eSBpcyB0aGUgdXNlIG9mIG11bHRpZGltZW5zaW9uYWwgc2NhbGluZyAoTURTKS4gRm9yIE1EUywgd2UgZmlyc3QgaGF2ZSB0byBjYWxjdWxhdGUgYWxsIHBhaXJ3aXNlIGRpc3RhbmNlcyBiZXR3ZWVuIG91ciBvYmplY3RzIChzYW1wbGVzIGluIHRoaXMgY2FzZSksIGFuZCB0aGVuIGNyZWF0ZSBhICh0eXBpY2FsbHkpIHR3by1kaW1lbnNpb25hbCByZXByZXNlbnRhdGlvbiB3aGVyZSB0aGVzZSBwcmUtY2FsY3VsYXRlZCBkaXN0YW5jZXMgYXJlIHJlcHJlc2VudGVkIGFzIGFjY3VyYXRlbHkgYXMgcG9zc2libGUuIFRoaXMgbWVhbnMgdGhhdCBkZXBlbmRpbmcgb24gaG93IHRoZSBwYWlyd2lzZSBzYW1wbGUgZGlzdGFuY2VzIGFyZSBkZWZpbmVkLCB0aGUgdHdvLWRpbWVuc2lvbmFsIHBsb3QgY2FuIGJlIHZlcnkgZGlmZmVyZW50LCBhbmQgaXQgaXMgaW1wb3J0YW50IHRvIGNob29zZSBhIGRpc3RhbmNlIHRoYXQgaXMgc3VpdGFibGUgZm9yIHRoZSB0eXBlIG9mIGRhdGEgYXQgaGFuZC4KCmVkZ2VSIGNvbnRhaW5zIGEgZnVuY3Rpb24gcGxvdE1EUywgd2hpY2ggb3BlcmF0ZXMgb24gYSBER0VMaXN0IG9iamVjdCBhbmQgZ2VuZXJhdGVzIGEgdHdvLWRpbWVuc2lvbmFsIE1EUyByZXByZXNlbnRhdGlvbiBvZiB0aGUgc2FtcGxlcy4gVGhlIGRlZmF1bHQgZGlzdGFuY2UgYmV0d2VlbiB0d28gc2FtcGxlcyBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgdGhlICJ0eXBpY2FsIiBsb2cgZm9sZCBjaGFuZ2UgYmV0d2VlbiB0aGUgdHdvIHNhbXBsZXMsIGZvciB0aGUgZ2VuZXMgdGhhdCBhcmUgbW9zdCBkaWZmZXJlbnQgYmV0d2VlbiB0aGVtIChieSBkZWZhdWx0LCB0aGUgdG9wIDUwMCBnZW5lcywgYnV0IHRoaXMgY2FuIGJlIG1vZGlmaWVkKS4gV2UgZ2VuZXJhdGUgYW4gTURTIHBsb3QgZnJvbSB0aGUgREdFTGlzdCBvYmplY3QgZGdlLCBjb2xvcmluZyBieSB0aGUgdHJlYXRtZW50IGFuZCB1c2luZyBkaWZmZXJlbnQgcGxvdCBzeW1ib2xzIGZvciBkaWZmZXJlbnQgY2VsbCBsaW5lcy4KCmBgYHtyfQpwbG90TURTKGRnZSwgdG9wID0gNTAwLCBjb2wgPSBhcy5kb3VibGUoY2VsbFR5cGUpKQpgYGAKCgoKCiMjIERpZmZlcmVudGlhbCBhbmFseXNpcwoKIyMjIEZpbHRlcmluZwpgYGB7cn0KZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+Y2VsbFR5cGUpCmtlZXAgPC0gZmlsdGVyQnlFeHByKGRnZSwgZGVzaWduKQpkZ2UgPC0gZGdlW2tlZXAsICxrZWVwLmxpYi5zaXplcyA9IEZBTFNFXQpgYGAKClRoZSBvcHRpb24ga2VlcC5saWIuc2l6ZXM9RkFMU0UgY2F1c2VzIHRoZSBsaWJyYXJ5IHNpemVzIHRvIGJlIHJlY29tcHV0ZWQgYWZ0ZXIgdGhlIGZpbHRlcmluZy4gVGhpcyBpcyBnZW5lcmFsbHkgcmVjb21tZW5kZWQsIGFsdGhvdWdoIHRoZSBlZmZlY3Qgb24gdGhlIGRvd25zdHJlYW0gYW5hbHlzaXMgaXMgdXN1YWxseSBzbWFsbC4KClRoZSBub3JtYWxpc2F0aW9uIGZhY3RvcnMgaGF2ZSB0byBiZSByZWNhbGN1bGF0ZWQgdXBvbiBmaWx0ZXJpbmcuCgpgYGB7cn0KZGdlIDwtIGNhbGNOb3JtRmFjdG9ycyhkZ2UpCmBgYAoKIyMjIEZpdCBNb2RlbAoKV2UgZmlyc3QgZXN0aW1hdGUgdGhlIG92ZXJkaXNwZXJzaW9uLgoKYGBge3J9CmRnZSA8LSBlc3RpbWF0ZURpc3AoZGdlLCBkZXNpZ24pCnBsb3RCQ1YoZGdlKQpgYGAKCgpGaW5hbGx5LCB3ZSBmaXQgdGhlIGdlbmVyYWxpemVkIGxpbmVhciBtb2RlbCBhbmQgcGVyZm9ybSB0aGUgdGVzdC4gSW4gdGhlIGdsbUxSVCBmdW5jdGlvbiwgd2UgaW5kaWNhdGUgd2hpY2ggY29lZmZpY2llbnQgKHdoaWNoIGNvbHVtbiBpbiB0aGUgZGVzaWduIG1hdHJpeCkgdGhhdCB3ZSB3b3VsZCBsaWtlIHRvIHRlc3QgZm9yLiBJdCBpcyBwb3NzaWJsZSB0byB0ZXN0IG1vcmUgZ2VuZXJhbCBjb250cmFzdHMgYXMgd2VsbCwgYW5kIHRoZSB1c2VyIGd1aWRlIGNvbnRhaW5zIG1hbnkgZXhhbXBsZXMgb24gaG93IHRvIGRvIHRoaXMuIFRoZSB0b3BUYWdzIGZ1bmN0aW9uIGV4dHJhY3RzIHRoZSB0b3AtcmFua2VkIGdlbmVzLiBZb3UgY2FuIGluZGljYXRlIHRoZSBhZGp1c3RlZCBwLXZhbHVlIGN1dG9mZiwgYW5kL29yIHRoZSBudW1iZXIgb2YgZ2VuZXMgdG8ga2VlcC4KCmBgYHtyfQpmaXQgPC0gZ2xtRml0KGRnZSwgZGVzaWduKQpscnQgPC0gZ2xtTFJUKGZpdCwgY29lZiA9IG5jb2woZGVzaWduKSkKdHRBbGwgPC10b3BUYWdzKGxydCwgbiA9IG5yb3coZGdlKSkgIyBhbGwgZ2VuZXMKYGBgCgpOb3RlLCB0aGF0IHRoZSB3b3JrZmxvdyB3aXRoIGdsbUZpdCBhbmQgZ2xtTFJUIGlzIG5vIGxvbmdlciB0aGUgZGVmYXVsdCB3b3JrZmxvdyBvZiBlZGdlUi4KV2Ugd2lsbCBkaXNjdXNzIHRoaXMgd2hlbiB3ZSBmb2N1cyBvbiB0aGUgdGVjaG5pY2FsIGFzcGVjdHMgb2YgZGlmZmVyZW50aWFsIGFuYWx5c2lzIG9mIFJOQVNlcSBkYXRhLiAKCiMjIyMgRXZhbHVhdGUgZGlzdHJpYnV0aW9uIG9mIHAtdmFsdWVzCgpgYGB7cn0KaGlzdCh0dEFsbCR0YWJsZSRQVmFsdWUpCmBgYAoKIyMjIyBERSBnZW5lcz8KCmBgYHtyfQp0dCA8LSB0b3BUYWdzKGxydCwgbiA9IG5yb3coZGdlKSwgcC52YWx1ZSA9IDAuMDUpICMgZ2VuZXMgd2l0aCBhZGoucDwwLjA1CmtuaXRyOjprYWJsZSh0dCkKYGBgCgpUaGVyZSBhcmUgYHIgbnJvdyh0dClgIGdlbmVzIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZC4KCiMjIyBQbG90cwoKV2UgZmlyc3QgbWFrZSBhIHZvbGNhbm9wbG90IGFuZCBhbiBNQSBwbG90LgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKdm9sY2FubzwtIGdncGxvdCh0dEFsbCR0YWJsZSxhZXMoeD1sb2dGQyx5PS1sb2cxMChQVmFsdWUpLGNvbG9yPUZEUjwwLjA1KSkgKyBnZW9tX3BvaW50KCkgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImJsYWNrIiwicmVkIikpCnZvbGNhbm8KcGxvdFNtZWFyKGxydCwgZGUudGFncyA9IHJvdy5uYW1lcyh0dCR0YWJsZSkpCmBgYAoKQW5vdGhlciB3YXkgb2YgcmVwcmVzZW50aW5nIHRoZSByZXN1bHRzIG9mIGEgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMgaXMgdG8gY29uc3RydWN0IGEgaGVhdG1hcCBvZiB0aGUgdG9wIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcy4gSGVyZSwgd2Ugd291bGQgZXhwZWN0IHRoZSBjb250cmFzdGVkIHNhbXBsZSBncm91cHMgdG8gY2x1c3RlciBzZXBhcmF0ZWx5LiBBIGhlYXRtYXAgaXMgYSAiY29sb3IgY29kZWQgZXhwcmVzc2lvbiBtYXRyaXgiLCB3aGVyZSB0aGUgcm93cyBhbmQgY29sdW1ucyBhcmUgY2x1c3RlcmVkIHVzaW5nIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nLiBUeXBpY2FsbHksIGl0IHNob3VsZCBub3QgYmUgYXBwbGllZCB0byBjb3VudHMsIGJ1dCB3b3JrcyBiZXR0ZXIgd2l0aCB0cmFuc2Zvcm1lZCB2YWx1ZXMuIEhlcmUgd2Ugc2hvdyBob3cgaXQgY2FuIGJlIGFwcGxpZWQgdG8gdGhlIHZhcmlhbmNlLXN0YWJpbGl6ZWQgdmFsdWVzIGdlbmVyYXRlZCBhYm92ZS4gV2UgY2hvb3NlIHRoZSB0b3AgMzAgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzLiBUaGVyZSBhcmUgbWFueSBmdW5jdGlvbnMgaW4gUiB0aGF0IGNhbiBnZW5lcmF0ZSBoZWF0bWFwcywgaGVyZSB3ZSBzaG93IHRoZSBvbmUgZnJvbSB0aGUgcGhlYXRtYXAgcGFja2FnZS4KCmBgYHtyfQpsaWJyYXJ5KHBoZWF0bWFwKQpwaGVhdG1hcChjcG0oZGdlLCBsb2cgPSBUUlVFKVtyb3duYW1lcyh0dCR0YWJsZSlbMTozMF0sXSkKYGBgCg==