1 Introduction

I downloaded the zip file from macrogen and processed the samples before receiving the sample sheet from Maria Adelaida and made a skeleton sheet with the samplenames as I created them. Upon receiving the sample sheet, I merged the skeleton with the actual sheet and continued.

2 Annotation

hs_annot <- sm(load_biomart_annotations(year = "2020"))
hs_annot <- hs_annot[["annotation"]]
hs_annot[["transcript"]] <- paste0(rownames(hs_annot), ".", hs_annot[["version"]])
rownames(hs_annot) <- make.names(hs_annot[["ensembl_gene_id"]], unique = TRUE)
tx_gene_map <- hs_annot[, c("transcript", "ensembl_gene_id")]

summary(hs_annot)
##  ensembl_transcript_id ensembl_gene_id       version     transcript_version
##  Length:227921         Length:227921      Min.   : 1.0   Min.   : 1.00     
##  Class :character      Class :character   1st Qu.: 6.0   1st Qu.: 1.00     
##  Mode  :character      Mode  :character   Median :12.0   Median : 1.00     
##                                           Mean   :10.7   Mean   : 3.08     
##                                           3rd Qu.:16.0   3rd Qu.: 5.00     
##                                           Max.   :29.0   Max.   :17.00     
##                                                                            
##  hgnc_symbol        description        gene_biotype         cds_length    
##  Length:227921      Length:227921      Length:227921      Min.   :     3  
##  Class :character   Class :character   Class :character   1st Qu.:   357  
##  Mode  :character   Mode  :character   Mode  :character   Median :   694  
##                                                           Mean   :  1139  
##                                                           3rd Qu.:  1446  
##                                                           Max.   :107976  
##                                                           NA's   :127343  
##  chromosome_name       strand          start_position      end_position     
##  Length:227921      Length:227921      Min.   :5.77e+02   Min.   :6.47e+02  
##  Class :character   Class :character   1st Qu.:3.11e+07   1st Qu.:3.12e+07  
##  Mode  :character   Mode  :character   Median :6.04e+07   Median :6.06e+07  
##                                        Mean   :7.41e+07   Mean   :7.42e+07  
##                                        3rd Qu.:1.09e+08   3rd Qu.:1.09e+08  
##                                        Max.   :2.49e+08   Max.   :2.49e+08  
##                                                                             
##   transcript       
##  Length:227921     
##  Class :character  
##  Mode  :character  
##                    
##                    
##                    
## 
hs_go <- sm(load_biomart_go()[["go"]])
hs_length <- hs_annot[, c("ensembl_gene_id", "cds_length")]
colnames(hs_length) <- c("ID", "length")

3 Sample Estimation

3.1 Generate expressionsets

The sample sheet is copied from our shared online sheet and updated with each release of sequencing data.

samplesheet <- "sample_sheets/macrogen_samples.xlsx"

3.1.1 Hisat2 expressionsets

## Create the expressionset and immediately pass it to a filter
## removing the non protein coding genes.
hs_expt <- create_expt(samplesheet,
                       file_column = "file",
                       gene_info = hs_annot) %>%
  exclude_genes_expt(column = "gene_biotype", method = "keep", pattern = "protein_coding")
## Reading the sample metadata.
## The sample definitions comprises: 27 rows(samples) and 18 columns(metadata fields).
## Reading count tables.
## Reading count files with read.table().
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt2008_b1/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt2008_b2/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt2008_b3/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt1029_b1/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt1029_b2/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt1029_b3/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt1031_b1/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt1031_b2/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt1031_b3/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt2010_b1/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt2010_b2/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/wt2010_b3/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/sfb/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/m1/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/m2/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/su1158/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/a_20179/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/c_10036/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/a_20187/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/c_10046/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/a_20132/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/c_10063/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/a_20133/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/c_10093/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/su1160/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/a_20134/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## /fs01/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/preprocessing/c_10073/outputs/hisat2_hg38_100/r1.count_hg38_100_sno_gene_gene_id.count.xz contains 21486 rows and merges to 21486 rows.
## Finished reading count data.
## Matched 21452 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## Saving the expressionset to 'expt.rda'.
## The final expressionset has 21481 rows and 27 columns.
## Before removal, there were 21481 genes, now there are 19941.
## There are 5 samples which kept less than 90 percent counts.
## wt2008_b2 wt1029_b2 wt1029_b3 wt1031_b2 wt2010_b3 
##     86.08     83.67     88.98     89.81     86.82

3.1.1.1 Initial metrics

libsize <- plot_libsize(hs_expt)
libsize$plot

nonzero <- plot_nonzero(hs_expt)
nonzero$plot
## Warning: ggrepel: 2 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

4 Questions from Maria Adelaida

Could you please help us with a couple of requests?

  1. PCA only of WT samples
  2. PCA only of the non-WT samples
  3. DE list of “c” vs. “a” samples (n=5/group)
  4. count table for WT samples

In order to make these queries more legible, I am changing the sample sheet slightly so that the WT (not wild type!) samples have the donor set to condition and the visit number set to batch for the trust samples. For the others I set condition to ‘a’ or ‘c’ and batch to just ‘undefined’. Finally, I made a column ‘experiment’ containing either ‘trust’, ‘stimulation’, or ‘clinical’ for what I think are the three experiments performed.

4.1 Trust samples

Start with #1 and #4 above, e.g. query the trust samples.

wt_expt <- subset_expt(hs_expt, subset = "experiment=='trust'")
## There were 27, now there are 12 samples.
wt_norm <- normalize_expt(wt_expt, transform = "log2", convert = "cpm",
                          norm = "quant", filter = TRUE)
## Removing 6279 low-count genes (13662 remaining).
## transform_counts: Found 3 values equal to 0, adding 1 to the matrix.
wt_pca <- plot_pca(wt_norm)
wt_pca$plot

From this initial PCA plot, it seems pretty clear that visit number is a strong factor (visit 1 on the left, visit 2 in the middle, visit 3 on the right).

Now let us write out the data, with some plots.

wt_written <- write_expt(wt_expt,
                         excel = glue::glue("excel/trust_samples-v{ver}.xlsx"))
## Deleting the file excel/trust_samples-v202105.xlsx before writing the tables.
## Writing the first sheet, containing a legend and some summary data.
## Writing the raw reads.
## Graphing the raw reads.
## `geom_smooth()` using formula 'y ~ x'
## `geom_smooth()` using formula 'y ~ x'
## Warning in doTryCatch(return(expr), name, parentenv, handler): display list
## redraw incomplete

## Warning in doTryCatch(return(expr), name, parentenv, handler): display list
## redraw incomplete
## Loading required package: Matrix
## 
## Attaching package: 'Matrix'
## The following object is masked from 'package:S4Vectors':
## 
##     expand
## 
## Total:113 s
## Writing the normalized reads.
## Graphing the normalized reads.
## `geom_smooth()` using formula 'y ~ x'
## `geom_smooth()` using formula 'y ~ x'
## Warning in doTryCatch(return(expr), name, parentenv, handler): display list
## redraw incomplete

## Warning in doTryCatch(return(expr), name, parentenv, handler): display list
## redraw incomplete
## 
## Total:90 s
## Writing the median reads by factor.

4.2 Clinical samples

Now let us look at the clinical samples, for which Maria Adelaida would like a look at the asymptomatic vs. the chronic.

clinical_expt <- subset_expt(hs_expt, subset = "experiment=='clinical'") %>%
  set_expt_conditions(fact = "clinicalpresentation")
## There were 27, now there are 12 samples.
clinical_norm <- normalize_expt(clinical_expt, transform = "log2", convert = "cpm",
                                norm = "quant", filter = TRUE)
## Removing 8474 low-count genes (11467 remaining).
## transform_counts: Found 8 values equal to 0, adding 1 to the matrix.
clinical_pca <- plot_pca(clinical_norm)
clinical_pca$plot

clinical_nb  <- normalize_expt(clinical_expt, transform = "log2", convert = "cpm",
                               filter = TRUE, batch = "svaseq")
## Removing 8474 low-count genes (11467 remaining).
## batch_counts: Before batch/surrogate estimation, 901 entries are x==0: 1%.
## batch_counts: Before batch/surrogate estimation, 4233 entries are 0<x<1: 3%.
## Setting 116 low elements to zero.
## transform_counts: Found 116 values equal to 0, adding 1 to the matrix.
clinical_nbpca <- plot_pca(clinical_nb)
clinical_nbpca$plot

clinical_de <- all_pairwise(clinical_expt, model_batch = "svaseq", filter = TRUE)
## batch_counts: Before batch/surrogate estimation, 901 entries are x==0: 1%.
## Plotting a PCA before surrogate/batch inclusion.
## Using svaseq to visualize before/after batch inclusion.
## Performing a test normalization with: raw
## Removing 0 low-count genes (11467 remaining).
## batch_counts: Before batch/surrogate estimation, 901 entries are x==0: 1%.
## batch_counts: Before batch/surrogate estimation, 4233 entries are 0<x<1: 3%.
## Setting 116 low elements to zero.
## transform_counts: Found 116 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

clinical_tables <- combine_de_tables(clinical_de,
                                     excel = glue::glue("excel/clinical_tables-v{ver}.xlsx"))
## Deleting the file excel/clinical_tables-v202105.xlsx before writing the tables.

tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiU29tZSBtYWNyb2dlbiBzYW1wbGVzIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiBodG1sX2RvY3VtZW50OgogIGNvZGVfZG93bmxvYWQ6IHRydWUKICBjb2RlX2ZvbGRpbmc6IHNob3cKICBmaWdfY2FwdGlvbjogdHJ1ZQogIGZpZ19oZWlnaHQ6IDcKICBmaWdfd2lkdGg6IDcKICBoaWdobGlnaHQ6IGRlZmF1bHQKICBrZWVwX21kOiBmYWxzZQogIG1vZGU6IHNlbGZjb250YWluZWQKICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogIHRoZW1lOiByZWFkYWJsZQogIHRvYzogdHJ1ZQogIHRvY19mbG9hdDoKICAgY29sbGFwc2VkOiBmYWxzZQogICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQotLS0KCjxzdHlsZT4KICBib2R5IC5tYWluLWNvbnRhaW5lciB7CiAgICBtYXgtd2lkdGg6IDE2MDBweDsKICB9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoaHBnbHRvb2xzKQp0dCA8LSBzbShkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMTIwLAogICAgICAgICAgICAgICAgICAgICBlY2hvID0gVFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDEyLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodCA9IDEyLAogICAgICAgICAgICAgICAgICAgICAgZHBpID0gOTYpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzID0gNCwKICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsID0gImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEyKSkKdmVyIDwtICIyMDIxMDUiCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdCA9ICIlWSVtJWQiKQoKcm1kX2ZpbGUgPC0gZ2x1ZTo6Z2x1ZSgibWFjcm9nZW5fc2FtcGxlcy5SbWQiKQpzYXZlZmlsZSA8LSBnc3ViKHBhdHRlcm4gPSAiXFwuUm1kIiwgcmVwbGFjZSA9ICJcXC5yZGFcXC54eiIsIHggPSBybWRfZmlsZSkKYGBgCgojIEludHJvZHVjdGlvbgoKSSBkb3dubG9hZGVkIHRoZSB6aXAgZmlsZSBmcm9tIG1hY3JvZ2VuIGFuZCBwcm9jZXNzZWQgdGhlIHNhbXBsZXMKYmVmb3JlIHJlY2VpdmluZyB0aGUgc2FtcGxlIHNoZWV0IGZyb20gTWFyaWEgQWRlbGFpZGEgYW5kIG1hZGUgYQpza2VsZXRvbiBzaGVldCB3aXRoIHRoZSBzYW1wbGVuYW1lcyBhcyBJIGNyZWF0ZWQgdGhlbS4gIFVwb24gcmVjZWl2aW5nCnRoZSBzYW1wbGUgc2hlZXQsIEkgbWVyZ2VkIHRoZSBza2VsZXRvbiB3aXRoIHRoZSBhY3R1YWwgc2hlZXQgYW5kCmNvbnRpbnVlZC4KCgojIEFubm90YXRpb24KCmBgYHtyIGhzX2Fubm90fQpoc19hbm5vdCA8LSBzbShsb2FkX2Jpb21hcnRfYW5ub3RhdGlvbnMoeWVhciA9ICIyMDIwIikpCmhzX2Fubm90IDwtIGhzX2Fubm90W1siYW5ub3RhdGlvbiJdXQpoc19hbm5vdFtbInRyYW5zY3JpcHQiXV0gPC0gcGFzdGUwKHJvd25hbWVzKGhzX2Fubm90KSwgIi4iLCBoc19hbm5vdFtbInZlcnNpb24iXV0pCnJvd25hbWVzKGhzX2Fubm90KSA8LSBtYWtlLm5hbWVzKGhzX2Fubm90W1siZW5zZW1ibF9nZW5lX2lkIl1dLCB1bmlxdWUgPSBUUlVFKQp0eF9nZW5lX21hcCA8LSBoc19hbm5vdFssIGMoInRyYW5zY3JpcHQiLCAiZW5zZW1ibF9nZW5lX2lkIildCgpzdW1tYXJ5KGhzX2Fubm90KQpgYGAKCmBgYHtyIGhzX2dvfQpoc19nbyA8LSBzbShsb2FkX2Jpb21hcnRfZ28oKVtbImdvIl1dKQpoc19sZW5ndGggPC0gaHNfYW5ub3RbLCBjKCJlbnNlbWJsX2dlbmVfaWQiLCAiY2RzX2xlbmd0aCIpXQpjb2xuYW1lcyhoc19sZW5ndGgpIDwtIGMoIklEIiwgImxlbmd0aCIpCmBgYAoKIyBTYW1wbGUgRXN0aW1hdGlvbgoKIyMgR2VuZXJhdGUgZXhwcmVzc2lvbnNldHMKClRoZSBzYW1wbGUgc2hlZXQgaXMgY29waWVkIGZyb20gb3VyIHNoYXJlZCBvbmxpbmUgc2hlZXQgYW5kIHVwZGF0ZWQgd2l0aCBlYWNoIHJlbGVhc2UKb2Ygc2VxdWVuY2luZyBkYXRhLgoKYGBge3Igc2FtcGxlc2hlZXR9CnNhbXBsZXNoZWV0IDwtICJzYW1wbGVfc2hlZXRzL21hY3JvZ2VuX3NhbXBsZXMueGxzeCIKYGBgCgojIyMgSGlzYXQyIGV4cHJlc3Npb25zZXRzCgpgYGB7ciBhbGxfbmV3X2hpc2F0Mn0KIyMgQ3JlYXRlIHRoZSBleHByZXNzaW9uc2V0IGFuZCBpbW1lZGlhdGVseSBwYXNzIGl0IHRvIGEgZmlsdGVyCiMjIHJlbW92aW5nIHRoZSBub24gcHJvdGVpbiBjb2RpbmcgZ2VuZXMuCmhzX2V4cHQgPC0gY3JlYXRlX2V4cHQoc2FtcGxlc2hlZXQsCiAgICAgICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW4gPSAiZmlsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgZ2VuZV9pbmZvID0gaHNfYW5ub3QpICU+JQogIGV4Y2x1ZGVfZ2VuZXNfZXhwdChjb2x1bW4gPSAiZ2VuZV9iaW90eXBlIiwgbWV0aG9kID0gImtlZXAiLCBwYXR0ZXJuID0gInByb3RlaW5fY29kaW5nIikKYGBgCgojIyMjIEluaXRpYWwgbWV0cmljcwoKYGBge3IgaW5pdGlhbF9tZXRyaWNzfQpsaWJzaXplIDwtIHBsb3RfbGlic2l6ZShoc19leHB0KQpsaWJzaXplJHBsb3QKCm5vbnplcm8gPC0gcGxvdF9ub256ZXJvKGhzX2V4cHQpCm5vbnplcm8kcGxvdApgYGAKCiMgUXVlc3Rpb25zIGZyb20gTWFyaWEgQWRlbGFpZGEKCgpDb3VsZCB5b3UgcGxlYXNlIGhlbHAgdXMgd2l0aCBhIGNvdXBsZSBvZiByZXF1ZXN0cz8KCjEpIFBDQSBvbmx5IG9mIFdUIHNhbXBsZXMKMikgUENBIG9ubHkgb2YgdGhlIG5vbi1XVCBzYW1wbGVzCjMpIERFIGxpc3Qgb2YgImMiIHZzLiAiYSIgc2FtcGxlcyAobj01L2dyb3VwKQo0KSBjb3VudCB0YWJsZSBmb3IgV1Qgc2FtcGxlcwoKSW4gb3JkZXIgdG8gbWFrZSB0aGVzZSBxdWVyaWVzIG1vcmUgbGVnaWJsZSwgSSBhbSBjaGFuZ2luZyB0aGUgc2FtcGxlCnNoZWV0IHNsaWdodGx5IHNvIHRoYXQgdGhlIFdUIChub3Qgd2lsZCB0eXBlISkgc2FtcGxlcyBoYXZlIHRoZSBkb25vcgpzZXQgdG8gY29uZGl0aW9uIGFuZCB0aGUgdmlzaXQgbnVtYmVyIHNldCB0byBiYXRjaCBmb3IgdGhlIHRydXN0CnNhbXBsZXMuICBGb3IgdGhlIG90aGVycyBJIHNldCBjb25kaXRpb24gdG8gJ2EnIG9yICdjJyBhbmQgYmF0Y2ggdG8KanVzdCAndW5kZWZpbmVkJy4gIEZpbmFsbHksIEkgbWFkZSBhIGNvbHVtbiAnZXhwZXJpbWVudCcgY29udGFpbmluZwplaXRoZXIgJ3RydXN0JywgJ3N0aW11bGF0aW9uJywgb3IgJ2NsaW5pY2FsJyBmb3Igd2hhdCBJIHRoaW5rIGFyZSB0aGUKdGhyZWUgZXhwZXJpbWVudHMgcGVyZm9ybWVkLgoKIyMgVHJ1c3Qgc2FtcGxlcwoKU3RhcnQgd2l0aCAjMSBhbmQgIzQgYWJvdmUsIGUuZy4gcXVlcnkgdGhlIHRydXN0IHNhbXBsZXMuCgpgYGB7ciB0cnVzdF9zYW1wbGVzfQp3dF9leHB0IDwtIHN1YnNldF9leHB0KGhzX2V4cHQsIHN1YnNldCA9ICJleHBlcmltZW50PT0ndHJ1c3QnIikKd3Rfbm9ybSA8LSBub3JtYWxpemVfZXhwdCh3dF9leHB0LCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gInF1YW50IiwgZmlsdGVyID0gVFJVRSkKd3RfcGNhIDwtIHBsb3RfcGNhKHd0X25vcm0pCnd0X3BjYSRwbG90CmBgYAoKRnJvbSB0aGlzIGluaXRpYWwgUENBIHBsb3QsIGl0IHNlZW1zIHByZXR0eSBjbGVhciB0aGF0IHZpc2l0IG51bWJlciBpcwphIHN0cm9uZyBmYWN0b3IgKHZpc2l0IDEgb24gdGhlIGxlZnQsIHZpc2l0IDIgaW4gdGhlIG1pZGRsZSwgdmlzaXQgMwpvbiB0aGUgcmlnaHQpLgoKTm93IGxldCB1cyB3cml0ZSBvdXQgdGhlIGRhdGEsIHdpdGggc29tZSBwbG90cy4KCmBgYHtyIHd0X3dyaXRlLCBmaWcuc2hvdyA9ICJoaWRlIn0Kd3Rfd3JpdHRlbiA8LSB3cml0ZV9leHB0KHd0X2V4cHQsCiAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3RydXN0X3NhbXBsZXMtdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyBDbGluaWNhbCBzYW1wbGVzCgpOb3cgbGV0IHVzIGxvb2sgYXQgdGhlIGNsaW5pY2FsIHNhbXBsZXMsIGZvciB3aGljaCBNYXJpYSBBZGVsYWlkYQp3b3VsZCBsaWtlIGEgbG9vayBhdCB0aGUgYXN5bXB0b21hdGljIHZzLiB0aGUgY2hyb25pYy4KCmBgYHtyIG90aGVyc30KY2xpbmljYWxfZXhwdCA8LSBzdWJzZXRfZXhwdChoc19leHB0LCBzdWJzZXQgPSAiZXhwZXJpbWVudD09J2NsaW5pY2FsJyIpICU+JQogIHNldF9leHB0X2NvbmRpdGlvbnMoZmFjdCA9ICJjbGluaWNhbHByZXNlbnRhdGlvbiIpCgpjbGluaWNhbF9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KGNsaW5pY2FsX2V4cHQsIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSAicXVhbnQiLCBmaWx0ZXIgPSBUUlVFKQpjbGluaWNhbF9wY2EgPC0gcGxvdF9wY2EoY2xpbmljYWxfbm9ybSkKY2xpbmljYWxfcGNhJHBsb3QKCmNsaW5pY2FsX25iICA8LSBub3JtYWxpemVfZXhwdChjbGluaWNhbF9leHB0LCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpCmNsaW5pY2FsX25icGNhIDwtIHBsb3RfcGNhKGNsaW5pY2FsX25iKQpjbGluaWNhbF9uYnBjYSRwbG90CgpjbGluaWNhbF9kZSA8LSBhbGxfcGFpcndpc2UoY2xpbmljYWxfZXhwdCwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwgZmlsdGVyID0gVFJVRSkKY2xpbmljYWxfdGFibGVzIDwtIGNvbWJpbmVfZGVfdGFibGVzKGNsaW5pY2FsX2RlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9jbGluaWNhbF90YWJsZXMtdnt2ZXJ9Lnhsc3giKSkKYGBgCgoKCmBgYHtyIGxvYWRtZV9hZnRlciwgZXZhbCA9IEZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYAo=