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
## 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
Data Analysis
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`)
Normalisation
dge <- calcNormFactors(dge)
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))
Differential analysis
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)
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.
Evaluate distribution of p-values
DE genes?
tt <- topTags(lrt, n = nrow(dge), p.value = 0.05) # genes with adj.p<0.05
knitr::kable(tt)
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 |
|
|
|
|
There are 111 genes differentially expressed.
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==