1 Introduction

This dataset contains multiple experiments.

2 Annotations

pa14_gff <- load_gff_annotations("reference/paeruginosa_pa14.gff", id_col="gene_id")
## Trying attempt: rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo = TRUE)
## Had a successful gff import with rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo = TRUE)
## Returning a df with 16 columns and 11946 rows.
rownames(pa14_gff) <- pa14_gff[["gene_id"]]
## The Alias column has PA14_00010

pa14_microbes <- as.data.frame(load_microbesonline_annotations("PA14"))
## Found 1 entry.
## Pseudomonas aeruginosa UCBPP-PA14Proteobacteria2006-11-22yes105972208963
## The species being downloaded is: Pseudomonas aeruginosa UCBPP-PA14
## Downloading: http://www.microbesonline.org/cgi-bin/genomeInfo.cgi?tId=208963;export=tab
## The sysName column has PA14_0010

pa14_annot <- merge(pa14_gff, pa14_microbes, by.x="Alias", by.y="sysName")
rownames(pa14_annot) <- pa14_annot[["gene_id"]]

pa14_go <- load_microbesonline_go(species="PA14")
## Found 1 entry.
## Pseudomonas aeruginosa UCBPP-PA14Proteobacteria2006-11-22yes105972208963
## The species being downloaded is: Pseudomonas aeruginosa UCBPP-PA14 and is being downloaded as 208963.tab.

3 Make the expressionset

Given the above annotations, now lets pull in the counts.

I am switching to the sheet all_samples_modified_gcd.xlsx for the moment because I added a space in the strain name for the gcd sampl

pa14_expt <- create_expt("sample_sheets/all_samples_modified_gcd.xlsx",
                         gene_info=pa14_annot, file_column="hisatcounttable")
## Reading the sample metadata.
## Did not find the condition column in the sample sheet.
## Filling it in as undefined.
## Did not find the batch column in the sample sheet.
## Filling it in as undefined.
## The sample definitions comprises: 105 rows(samples) and 31 columns(metadata fields).
## Matched 5972 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 5979 rows and 105 columns.

4 Quick global look at the data

While we are at it, lets drop the two sad samples.

pa14_libsize <- plot_libsize(pa14_expt)
pa14_libsize$plot

pa14_nonzero <- plot_nonzero(pa14_expt)
pa14_nonzero$plot
## Warning: ggrepel: 100 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

pa14_expt <- subset_expt(pa14_expt, nonzero=5500)
## The samples (and read coverage) removed when filtering 5500 non-zero genes are:
##  SM040  SM048 
##  43984 316632
## subset_expt(): There were 105, now there are 103 samples.

5 View all samples briefly

sk_norm <- normalize_expt(sk_expt, transform="log2", convert="cpm", norm="quant", filter=TRUE)
## Error in normalize_expt(sk_expt, transform = "log2", convert = "cpm", : object 'sk_expt' not found
plot_pca(sk_norm)$plot
## Error in plot_pca(sk_norm): object 'sk_norm' not found

6 Alginate!

initials_factor <- gsub(x=rownames(pData(pa14_expt)), pattern="^(..).*$", replacement="\\1")
pData(pa14_expt)[["initials"]] <- as.factor(initials_factor)
sk_expt <- subset_expt(pa14_expt, subset="initials=='SK'")
## subset_expt(): There were 103, now there are 45 samples.
alginate_expt <- subset_expt(sk_expt, subset="media!='LB'") %>%
  set_expt_batches(fact="bioreplicate") %>%
  set_expt_conditions(fact="media")
## subset_expt(): There were 45, now there are 36 samples.
rph_expt <- subset_expt(sk_expt, subset="media=='LB'") %>%
  set_expt_batches(fact="bioreplicate") %>%
  set_expt_conditions(fact="strains") %>%
  sanitize_expt_metadata()
## subset_expt(): There were 45, now there are 9 samples.

7 The alginate data

There are two media, an inducer, and multiple methods of reducing expression…

alg_norm <- normalize_expt(alginate_expt, transform="log2",
                           convert="cpm", norm="quant", filter=TRUE)
## Removing 18 low-count genes (5961 remaining).
## transform_counts: Found 7 values equal to 0, adding 1 to the matrix.
plot_pca(alg_norm)$plot
## Warning: ggrepel: 1 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

conditions <- pData(alginate_expt)[["condition"]]
induce_bool <- grepl(pattern="IPTG", x=conditions)
induce_factor <- rep("not_induced", length(induce_bool))
induce_factor[induce_bool] <- "IPTG"

reduce_bool <- grepl(pattern="Eb", x=conditions)
reduce_factor <- rep("not_reduced", length(reduce_bool))
eb_samples <-  grepl(pattern="Eb", x=conditions)
reduce_factor[eb_samples] <- "Eb"
ebo_samples <- grepl(pattern="EbO", x=conditions)
reduce_factor[ebo_samples] <- "EbO"
ebs_samples <- grepl(pattern="EbS", x=conditions)
reduce_factor[ebs_samples] <- "EbS"

media_factor <- conditions
lb_bool <- grepl(pattern="LB", x=conditions)
media_factor[lb_bool] <- "LB"
media_factor[!lb_bool] <- "SCFM"

pData(alginate_expt)[["media_add"]] <- pData(alginate_expt)[["media"]]
pData(alginate_expt)[["media"]] <- media_factor
pData(alginate_expt)[["induced"]] <- as.factor(induce_factor)
pData(alginate_expt)[["reduced"]] <- as.factor(reduce_factor)

7.1 Compare media

alginate_media <- set_expt_conditions(alginate_expt, fact="media") %>%
  set_expt_batches(fact="bioreplicate")

alginate_media_norm <- normalize_expt(alginate_media, transform="log2",
                                      convert="cpm", norm="quant", filter=TRUE)
## Removing 18 low-count genes (5961 remaining).
## transform_counts: Found 7 values equal to 0, adding 1 to the matrix.
plot_pca(alginate_media_norm)$plot
## Warning: ggrepel: 6 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

7.2 Compare induce

alginate_induce <- set_expt_conditions(alginate_expt, fact="induced") %>%
  set_expt_batches(fact="bioreplicate")
alginate_induce_norm <- normalize_expt(alginate_induce, transform="log2",
                                       convert="cpm", norm="quant", filter=TRUE)
## Removing 18 low-count genes (5961 remaining).
## transform_counts: Found 7 values equal to 0, adding 1 to the matrix.
plot_pca(alginate_induce_norm)$plot
## Warning: ggrepel: 4 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

alginate_reduce <- set_expt_conditions(alginate_expt, fact="reduced") %>%
  set_expt_batches(fact="bioreplicate")
alginate_reduce_norm <- normalize_expt(alginate_reduce, transform="log2",
                                       convert="cpm", norm="quant", filter=TRUE)
## Removing 18 low-count genes (5961 remaining).
## transform_counts: Found 7 values equal to 0, adding 1 to the matrix.
plot_pca(alginate_reduce_norm)$plot
## Warning: ggrepel: 11 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

both_fact <- paste0(pData(alginate_expt)[["induced"]], "_",
                    pData(alginate_expt)[["reduced"]])
pData(alginate_expt)[["induce_reduce"]] <- both_fact

alginate_both <- set_expt_conditions(alginate_expt, fact="induce_reduce") %>%
  set_expt_batches(fact="bioreplicate")
alginate_both_norm <- normalize_expt(alginate_both, transform="log2", batch="svaseq",
                                     convert="cpm", norm="quant", filter=TRUE)
## Warning in normalize_expt(alginate_both, transform = "log2", batch = "svaseq", :
## Quantile normalization and sva do not always play well together.
## Removing 18 low-count genes (5961 remaining).
## batch_counts: Before batch/surrogate estimation, 7 entries are x==0: 0%.
## batch_counts: Before batch/surrogate estimation, 2144 entries are 0<x<1: 1%.
## Setting 60 low elements to zero.
## transform_counts: Found 60 values equal to 0, adding 1 to the matrix.
plot_pca(alginate_both_norm)$plot

8 rph data

rph_norm <- normalize_expt(rph_expt, transform="log2",
                           convert="cpm", norm="quant", filter=TRUE)
## Removing 71 low-count genes (5908 remaining).
## transform_counts: Found 4 values equal to 0, adding 1 to the matrix.
plot_pca(rph_norm)$plot

rph_de <- all_pairwise(rph_expt, model_batch=TRUE, filter=TRUE)
## Plotting a PCA before surrogate/batch inclusion.
## Using limma's removeBatchEffect to visualize with(out) batch inclusion.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

rph_tables <- combine_de_tables(
    rph_de,
    excel=glue::glue("excel/rph_tables-v{ver}.xlsx"))
## Deleting the file excel/rph_tables-v20220131.xlsx before writing the tables.
rph_sig <- extract_significant_genes(
    rph_tables,
    excel=glue::glue("excel/rph_sig-v{ver}.xlsx"))
## Deleting the file excel/rph_sig-v20220131.xlsx before writing the tables.
pander::pander(sessionInfo())
message(paste0("This is hpgltools commit: ", get_git_commit()))
this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
message(paste0("Saving to ", this_save))
tmp <- sm(saveme(filename=this_save))
LS0tCnRpdGxlOiAiU29tZSBQc2V1ZG9tb25hcyBSTkFzZXEgZGF0YTogU0suIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogZmFsc2UKICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UKICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB3aWR0aDogMzAwCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCiAgQmlvY1N0eWxlOjpodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSwgdGQgewogIGZvbnQtc2l6ZTogMTZweDsKfQpjb2RlLnJ7CiAgZm9udC1zaXplOiAxNnB4Owp9CnByZSB7CiBmb250LXNpemU6IDE2cHgKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSgiaHBnbHRvb2xzIikKdHQgPC0gZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHdpZHRoPTEyMCwKICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cz00LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsPSJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQ9IiVZJW0lZCIpCnByZXZpb3VzX2ZpbGUgPC0gIiIKdmVyIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCAiJVklbSVkIikKCiMjdG1wIDwtIHNtKGxvYWRtZShmaWxlbmFtZT1wYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXByZXZpb3VzX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikpKQpybWRfZmlsZSA8LSAiaW5kZXhfc2suUm1kIgpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGlzIGRhdGFzZXQgY29udGFpbnMgbXVsdGlwbGUgZXhwZXJpbWVudHMuCgojIEFubm90YXRpb25zCgpgYGB7ciBhbm5vdGF0aW9ufQpwYTE0X2dmZiA8LSBsb2FkX2dmZl9hbm5vdGF0aW9ucygicmVmZXJlbmNlL3BhZXJ1Z2lub3NhX3BhMTQuZ2ZmIiwgaWRfY29sPSJnZW5lX2lkIikKcm93bmFtZXMocGExNF9nZmYpIDwtIHBhMTRfZ2ZmW1siZ2VuZV9pZCJdXQojIyBUaGUgQWxpYXMgY29sdW1uIGhhcyBQQTE0XzAwMDEwCgpwYTE0X21pY3JvYmVzIDwtIGFzLmRhdGEuZnJhbWUobG9hZF9taWNyb2Jlc29ubGluZV9hbm5vdGF0aW9ucygiUEExNCIpKQojIyBUaGUgc3lzTmFtZSBjb2x1bW4gaGFzIFBBMTRfMDAxMAoKcGExNF9hbm5vdCA8LSBtZXJnZShwYTE0X2dmZiwgcGExNF9taWNyb2JlcywgYnkueD0iQWxpYXMiLCBieS55PSJzeXNOYW1lIikKcm93bmFtZXMocGExNF9hbm5vdCkgPC0gcGExNF9hbm5vdFtbImdlbmVfaWQiXV0KCnBhMTRfZ28gPC0gbG9hZF9taWNyb2Jlc29ubGluZV9nbyhzcGVjaWVzPSJQQTE0IikKYGBgCgojIE1ha2UgdGhlIGV4cHJlc3Npb25zZXQKCkdpdmVuIHRoZSBhYm92ZSBhbm5vdGF0aW9ucywgbm93IGxldHMgcHVsbCBpbiB0aGUgY291bnRzLgoKSSBhbSBzd2l0Y2hpbmcgdG8gdGhlIHNoZWV0IGFsbF9zYW1wbGVzX21vZGlmaWVkX2djZC54bHN4IGZvciB0aGUKbW9tZW50IGJlY2F1c2UgSSBhZGRlZCBhIHNwYWNlIGluIHRoZSBzdHJhaW4gbmFtZSBmb3IgdGhlIGdjZCBzYW1wbAoKYGBge3IgZXhwcmVzc2lvbnNldH0KcGExNF9leHB0IDwtIGNyZWF0ZV9leHB0KCJzYW1wbGVfc2hlZXRzL2FsbF9zYW1wbGVzX21vZGlmaWVkX2djZC54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbz1wYTE0X2Fubm90LCBmaWxlX2NvbHVtbj0iaGlzYXRjb3VudHRhYmxlIikKYGBgCgojIFF1aWNrIGdsb2JhbCBsb29rIGF0IHRoZSBkYXRhCgpXaGlsZSB3ZSBhcmUgYXQgaXQsIGxldHMgZHJvcCB0aGUgdHdvIHNhZCBzYW1wbGVzLgoKYGBge3IgbWV0cmljc30KcGExNF9saWJzaXplIDwtIHBsb3RfbGlic2l6ZShwYTE0X2V4cHQpCnBhMTRfbGlic2l6ZSRwbG90CgpwYTE0X25vbnplcm8gPC0gcGxvdF9ub256ZXJvKHBhMTRfZXhwdCkKcGExNF9ub256ZXJvJHBsb3QKCnBhMTRfZXhwdCA8LSBzdWJzZXRfZXhwdChwYTE0X2V4cHQsIG5vbnplcm89NTUwMCkKYGBgCgojIFZpZXcgYWxsIHNhbXBsZXMgYnJpZWZseQoKYGBge3IgZ2xvYmFsX3ZpZXdfc2t9CnNrX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoc2tfZXhwdCwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwgbm9ybT0icXVhbnQiLCBmaWx0ZXI9VFJVRSkKcGxvdF9wY2Eoc2tfbm9ybSkkcGxvdApgYGAKCiMgQWxnaW5hdGUhCgpgYGB7ciBhbGdpbmF0ZX0KaW5pdGlhbHNfZmFjdG9yIDwtIGdzdWIoeD1yb3duYW1lcyhwRGF0YShwYTE0X2V4cHQpKSwgcGF0dGVybj0iXiguLikuKiQiLCByZXBsYWNlbWVudD0iXFwxIikKcERhdGEocGExNF9leHB0KVtbImluaXRpYWxzIl1dIDwtIGFzLmZhY3Rvcihpbml0aWFsc19mYWN0b3IpCnNrX2V4cHQgPC0gc3Vic2V0X2V4cHQocGExNF9leHB0LCBzdWJzZXQ9ImluaXRpYWxzPT0nU0snIikKCmFsZ2luYXRlX2V4cHQgPC0gc3Vic2V0X2V4cHQoc2tfZXhwdCwgc3Vic2V0PSJtZWRpYSE9J0xCJyIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0iYmlvcmVwbGljYXRlIikgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0PSJtZWRpYSIpCgpycGhfZXhwdCA8LSBzdWJzZXRfZXhwdChza19leHB0LCBzdWJzZXQ9Im1lZGlhPT0nTEInIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJiaW9yZXBsaWNhdGUiKSAlPiUKICBzZXRfZXhwdF9jb25kaXRpb25zKGZhY3Q9InN0cmFpbnMiKSAlPiUKICBzYW5pdGl6ZV9leHB0X21ldGFkYXRhKCkKYGBgCgojIFRoZSBhbGdpbmF0ZSBkYXRhCgpUaGVyZSBhcmUgdHdvIG1lZGlhLCBhbiBpbmR1Y2VyLCBhbmQgbXVsdGlwbGUgbWV0aG9kcyBvZiByZWR1Y2luZyBleHByZXNzaW9uLi4uCgpgYGB7ciBhbGdpbmF0ZTAyfQphbGdfbm9ybSA8LSBub3JtYWxpemVfZXhwdChhbGdpbmF0ZV9leHB0LCB0cmFuc2Zvcm09ImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb252ZXJ0PSJjcG0iLCBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQpwbG90X3BjYShhbGdfbm9ybSkkcGxvdAoKY29uZGl0aW9ucyA8LSBwRGF0YShhbGdpbmF0ZV9leHB0KVtbImNvbmRpdGlvbiJdXQppbmR1Y2VfYm9vbCA8LSBncmVwbChwYXR0ZXJuPSJJUFRHIiwgeD1jb25kaXRpb25zKQppbmR1Y2VfZmFjdG9yIDwtIHJlcCgibm90X2luZHVjZWQiLCBsZW5ndGgoaW5kdWNlX2Jvb2wpKQppbmR1Y2VfZmFjdG9yW2luZHVjZV9ib29sXSA8LSAiSVBURyIKCnJlZHVjZV9ib29sIDwtIGdyZXBsKHBhdHRlcm49IkViIiwgeD1jb25kaXRpb25zKQpyZWR1Y2VfZmFjdG9yIDwtIHJlcCgibm90X3JlZHVjZWQiLCBsZW5ndGgocmVkdWNlX2Jvb2wpKQplYl9zYW1wbGVzIDwtICBncmVwbChwYXR0ZXJuPSJFYiIsIHg9Y29uZGl0aW9ucykKcmVkdWNlX2ZhY3RvcltlYl9zYW1wbGVzXSA8LSAiRWIiCmVib19zYW1wbGVzIDwtIGdyZXBsKHBhdHRlcm49IkViTyIsIHg9Y29uZGl0aW9ucykKcmVkdWNlX2ZhY3RvcltlYm9fc2FtcGxlc10gPC0gIkViTyIKZWJzX3NhbXBsZXMgPC0gZ3JlcGwocGF0dGVybj0iRWJTIiwgeD1jb25kaXRpb25zKQpyZWR1Y2VfZmFjdG9yW2Vic19zYW1wbGVzXSA8LSAiRWJTIgoKbWVkaWFfZmFjdG9yIDwtIGNvbmRpdGlvbnMKbGJfYm9vbCA8LSBncmVwbChwYXR0ZXJuPSJMQiIsIHg9Y29uZGl0aW9ucykKbWVkaWFfZmFjdG9yW2xiX2Jvb2xdIDwtICJMQiIKbWVkaWFfZmFjdG9yWyFsYl9ib29sXSA8LSAiU0NGTSIKCnBEYXRhKGFsZ2luYXRlX2V4cHQpW1sibWVkaWFfYWRkIl1dIDwtIHBEYXRhKGFsZ2luYXRlX2V4cHQpW1sibWVkaWEiXV0KcERhdGEoYWxnaW5hdGVfZXhwdClbWyJtZWRpYSJdXSA8LSBtZWRpYV9mYWN0b3IKcERhdGEoYWxnaW5hdGVfZXhwdClbWyJpbmR1Y2VkIl1dIDwtIGFzLmZhY3RvcihpbmR1Y2VfZmFjdG9yKQpwRGF0YShhbGdpbmF0ZV9leHB0KVtbInJlZHVjZWQiXV0gPC0gYXMuZmFjdG9yKHJlZHVjZV9mYWN0b3IpCmBgYAoKIyMgQ29tcGFyZSBtZWRpYQoKYGBge3IgYWxnaW5hdGVfbWVkaWF9CmFsZ2luYXRlX21lZGlhIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoYWxnaW5hdGVfZXhwdCwgZmFjdD0ibWVkaWEiKSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3Q9ImJpb3JlcGxpY2F0ZSIpCgphbGdpbmF0ZV9tZWRpYV9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KGFsZ2luYXRlX21lZGlhLCB0cmFuc2Zvcm09ImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpCnBsb3RfcGNhKGFsZ2luYXRlX21lZGlhX25vcm0pJHBsb3QKYGBgCgojIyBDb21wYXJlIGluZHVjZQoKYGBge3IgaW5kdWNlfQphbGdpbmF0ZV9pbmR1Y2UgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhhbGdpbmF0ZV9leHB0LCBmYWN0PSJpbmR1Y2VkIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJiaW9yZXBsaWNhdGUiKQphbGdpbmF0ZV9pbmR1Y2Vfbm9ybSA8LSBub3JtYWxpemVfZXhwdChhbGdpbmF0ZV9pbmR1Y2UsIHRyYW5zZm9ybT0ibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpCnBsb3RfcGNhKGFsZ2luYXRlX2luZHVjZV9ub3JtKSRwbG90CmBgYAoKYGBge3IgcmVkdWNlfQphbGdpbmF0ZV9yZWR1Y2UgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhhbGdpbmF0ZV9leHB0LCBmYWN0PSJyZWR1Y2VkIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJiaW9yZXBsaWNhdGUiKQphbGdpbmF0ZV9yZWR1Y2Vfbm9ybSA8LSBub3JtYWxpemVfZXhwdChhbGdpbmF0ZV9yZWR1Y2UsIHRyYW5zZm9ybT0ibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpCnBsb3RfcGNhKGFsZ2luYXRlX3JlZHVjZV9ub3JtKSRwbG90CmBgYAoKYGBge3IgaW5kdWNlX3JlZHVjZX0KYm90aF9mYWN0IDwtIHBhc3RlMChwRGF0YShhbGdpbmF0ZV9leHB0KVtbImluZHVjZWQiXV0sICJfIiwKICAgICAgICAgICAgICAgICAgICBwRGF0YShhbGdpbmF0ZV9leHB0KVtbInJlZHVjZWQiXV0pCnBEYXRhKGFsZ2luYXRlX2V4cHQpW1siaW5kdWNlX3JlZHVjZSJdXSA8LSBib3RoX2ZhY3QKCmFsZ2luYXRlX2JvdGggPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhhbGdpbmF0ZV9leHB0LCBmYWN0PSJpbmR1Y2VfcmVkdWNlIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJiaW9yZXBsaWNhdGUiKQphbGdpbmF0ZV9ib3RoX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoYWxnaW5hdGVfYm90aCwgdHJhbnNmb3JtPSJsb2cyIiwgYmF0Y2g9InN2YXNlcSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb252ZXJ0PSJjcG0iLCBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQpwbG90X3BjYShhbGdpbmF0ZV9ib3RoX25vcm0pJHBsb3QKYGBgCgojIHJwaCBkYXRhCgpgYGB7ciBycGh9CnJwaF9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KHJwaF9leHB0LCB0cmFuc2Zvcm09ImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb252ZXJ0PSJjcG0iLCBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQpwbG90X3BjYShycGhfbm9ybSkkcGxvdApgYGAKCmBgYHtyIHJwaF9kZX0KcnBoX2RlIDwtIGFsbF9wYWlyd2lzZShycGhfZXhwdCwgbW9kZWxfYmF0Y2g9VFJVRSwgZmlsdGVyPVRSVUUpCnJwaF90YWJsZXMgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBycGhfZGUsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9ycGhfdGFibGVzLXZ7dmVyfS54bHN4IikpCnJwaF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIHJwaF90YWJsZXMsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9ycGhfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKCmBgYHtyIHNhdmVtZSwgZXZhbD1GQUxTRX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCnRoaXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXJtZF9maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgdGhpc19zYXZlKSkKdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQpgYGAK