1 Introduction

export HS_TYPE=gene
export HS_TAG=ID

1.1 Testing directory

I think for speed sake, I will run these through salmon.

I have been making some changes to my pipeline recently; so I will put 100k reads into a test directory.

cd preprocessing
mkdir test
cd test
less ../SRR/*R1* | head -n 400000 > r1.fastq
less ../SRR/*R2* | head -n 400000 > r2.fastq
gzip *.fastq
inputs=$(/bin/ls outputs/12fastp/*-fastp.fastq.xz | tr '\n' ':')
cyoa --method salmon --species hg38_111 --input $inputs --libtype CDS --jprefix 20

1.2 Trimming via fastp

I am going to use that tree to run everything first, notably I want my tools to collect more thorough statistics on runtime etc to improve my nascent heuristics to choose memory/time on the cluster.

start=$(pwd)
for i in $(/bin/ls -d SR*); do
    cd ${start}/${i}
    mkdir unprocessed
    mv *.fastq.gz unprocessed/
    cyoa --method fastp --input $(/bin/ls -d unprocessed/*.fastq.gz | tr '\n' ':')
done
cd $start

1.3 Salmon quantification

start=$(pwd)
for i in $(/bin/ls -d SR*); do
    cd ${start}/${i}
    inputs=$(/bin/ls outputs/12fastp/*-fastp.fastq.xz | tr '\n' ':')
    cyoa --method salmon --species hg38_111 --input $inputs --libtype CDS --jprefix 20
done
cd $start

2 Load annotations

hs_annot <- load_biomart_annotations(year = 2021, month = 02)
## The biomart annotations file already exists, loading from it.
annot <- hs_annot[["gene_annotations"]]

3 Collect preprocessing information

meta <- gather_preprocessing_metadata("sample_sheets/PRJNA675090.xlsx")
## 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.
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## Writing new metadata to: sample_sheets/PRJNA675090_modified.xlsx
## Deleting the file sample_sheets/PRJNA675090_modified.xlsx before writing the tables.

4 Create SE

tx_gene_map <- hs_annot[["gene_tx_map"]]
tx_gene_map[["transcript"]] <- gsub(x = tx_gene_map[["transcript"]], pattern = "\\.\\d+$", replacement = "")
rownames(tx_gene_map) <- make.names(gsub(x = rownames(tx_gene_map), pattern = "\\.\\d+$", replacement = ""), unique = TRUE)
## Error in `rownames<-`(`*tmp*`, value = character(0)): attempt to set 'rownames' on an object with no dimensions
hs_se_tx <- create_se(meta[["new_meta"]], gene_info = annot, file_column = "salmon_count_table")
## Reading the sample metadata.
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## The sample definitions comprises: 41 rows(samples) and 22 columns(metadata fields).
## Warning in create_se(meta[["new_meta"]], gene_info = annot, file_column = "salmon_count_table"): Some
## samples were removed when cross referencing the samples against the count data.
## Warning in create_se(meta[["new_meta"]], gene_info = annot, file_column = "salmon_count_table"): Even
## after changing the rownames in gene info, they do not match the count table.
## Even after changing the rownames in gene info, they do not match the count table.
## Here are the first few rownames from the count tables:
## ENST00000000233.10, ENST00000000412.8, ENST00000000442.11, ENST00000001008.6, ENST00000001146.7, ENST00000002125.9
## Here are the first few rownames from the gene information table:
## ENSG00000000003, ENSG00000000005, ENSG00000000419, ENSG00000000457, ENSG00000000460, ENSG00000000938
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## Saving the summarized experiment to 'se.rda'.
## The final summarized experiment has 97117 rows and 22 columns.
hs_se_gene <- create_se(meta[["new_meta"]], gene_info = annot, file_column = "salmon_count_table",
                        tx_gene_map = tx_gene_map)
## Reading the sample metadata.
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## The sample definitions comprises: 41 rows(samples) and 22 columns(metadata fields).
## In some cases, (notably salmon) the format of the IDs used by this can be tricky.
## It is likely to require the transcript ID followed by a '.' and the ensembl column:
## 'transcript_version', which is explicitly different than the gene version column.
## If this is not correctly performed, very few genes will be observed
## reading in files with read_tsv
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
## Error in `colnames<-`(`*tmp*`, value = c("tx", "gene")): attempt to set 'colnames' on an object with less than two dimensions

5 Set condition/batch

I have extracted two potentially interesting columns from the metadata, after that I will need to read more carefully in the paper to try to get a sense of what is what…

hs_se <- set_se_conditions(hs_se_gene, fact = "controlp") %>%
  set_se_batches(fact = "type")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'colData': error in evaluating the argument 'x' in selecting a method for function 'colData': object 'hs_se_gene' not found

6 A couple plots

plot_legend(hs_se)
## Error: object 'hs_se' not found
plot_libsize(hs_se)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_libsize': object 'hs_se' not found
plot_nonzero(hs_se)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_nonzero': object 'hs_se' not found

Presumably we will need to separate the exome and rnaseq data; but for the moment I will leave them together to see what I can see.

hs_norm <- normalize(hs_se, transform = "log2", convert = "cpm", filter = TRUE, norm = "quant")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'normalize': object 'hs_se' not found
plot_pca(hs_norm)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_pca': object 'hs_norm' not found
hs_nb <- normalize(hs_se,  transform = "log2", convert = "cpm", filter = TRUE, batch = "combat")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'normalize': object 'hs_se' not found
plot_pca(hs_nb)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_pca': object 'hs_nb' not found

Ok, nevermind, the exome data is too different.

hs_rna <- subset_se(hs_se, subset = "batch=='rnaseq'")
## Error: object 'hs_se' not found
hs_rna_norm <- normalize(hs_rna, transform = "log2", convert = "cpm", filter = TRUE, norm = "quant")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'normalize': object 'hs_rna' not found
norm_pca <- plot_pca(hs_rna_norm)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_pca': object 'hs_rna_norm' not found
pp(file = "images/norm_pca.pdf")
norm_pca
## Error: object 'norm_pca' not found
dev.off()
## png 
##   2
##hs_rna_nb <- normalize(hs_rna, transform = "log2", convert = "cpm", filter = TRUE, batch = "svaseq")
##plot_pca(hs_rna_nb)

7 Exclude odd sample

In our initial PCA plot, SRR12999746 looks particularly strange.

hs_idx <- colnames(hs_rna) != "SRR12999746"
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'colnames': object 'hs_rna' not found
kept_ids <- colnames(hs_rna)[hs_idx]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'colnames': object 'hs_rna' not found
hs_excluded <- subset_se(hs_rna, ids = kept_ids)
## Error: object 'hs_rna' not found
excluded_norm <- normalize(hs_excluded, filter = TRUE, convert = "cpm", transform = "log2")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'input' in selecting a method for function 'normalize': object 'hs_excluded' not found
plot_pca(excluded_norm)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_pca': object 'excluded_norm' not found

8 First try DE

hs_de <- all_pairwise(hs_excluded, filter = TRUE, model_svs = "svaseq",
                      model_fstring = "~ 0 + condition", force = TRUE)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'hs_excluded' not found
hs_table <- combine_de_tables(hs_de, excel = "excel/control_vs_hcm.xlsx")
## Deleting the file excel/control_vs_hcm.xlsx before writing the tables.
## Error in h(simpleError(msg, call)): error in evaluating the argument 'expt' in selecting a method for function 'colors': object 'hs_de' not found
hs_sig <- extract_significant_genes(hs_table, excel = "excel/control_vs_hcm-sig.xlsx")
## Deleting the file excel/control_vs_hcm-sig.xlsx before writing the tables.
## Error: object 'hs_table' not found

9 Ontology shenanigans

hs_gp <- all_cprofiler(hs_sig, hs_table)
## Error: object 'hs_sig' not found

A few specific mSigDB categories: C8, C7, C5, C3, C2

This is actually C2 because I need to download a new copy of msigdb in the new format.

9.1 New copy of msigdb

I downloaded a fresh copy of the human mSigDB because my copy was in the old format and that no longer parses well.

9.1.1 Load msigdb

up_cp_c8 <- simple_clusterprofiler(input_up, de_table = table,
                                   msig_db = "reference/msigdb_v2024.1.Hs.db",
                                   do_msigdb = TRUE, msigdb_category = "C8",
                                   do_mesh = TRUE, do_dose = TRUE, orgdb_from = "ENSEMBL")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'input_up' not found

9.2 C2

c2 <- load_gmt_signatures(signatures = "reference/msigdb_v2024.1.Hs.db", signature_category = "c2",
                          id_type = "entrez")
c2_enricher <- simple_cp_enricher(sig_genes = input_up, de_table = table, db = c2)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'sig_genes' in selecting a method for function 'simple_cp_enricher': object 'input_up' not found
written <- write_xlsx(data = as.data.frame(c2_enricher), excel = "excel/c2_result.xlsx")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'write_xlsx': error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'c2_enricher' not found

9.3 C3

c3 <- load_gmt_signatures(signatures = "reference/msigdb_v2024.1.Hs.db", signature_category = "c3",
                          id_type = "entrez")
c3_enricher <- simple_cp_enricher(sig_genes = input_up, de_table = table, db = c3)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'sig_genes' in selecting a method for function 'simple_cp_enricher': object 'input_up' not found
written <- write_xlsx(data = as.data.frame(c3_enricher), excel = "excel/c3_result.xlsx")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'write_xlsx': error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'c3_enricher' not found

9.4 C4

c4 <- load_gmt_signatures(signatures = "reference/msigdb_v2024.1.Hs.db", signature_category = "c4",
                          id_type = "entrez")
c4_enricher <- simple_cp_enricher(sig_genes = input_up, de_table = table, db = c4)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'sig_genes' in selecting a method for function 'simple_cp_enricher': object 'input_up' not found
written <- write_xlsx(data = as.data.frame(c4_enricher), excel = "excel/c4_result.xlsx")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'write_xlsx': error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'c4_enricher' not found

9.5 C5

c5 <- load_gmt_signatures(signatures = "reference/msigdb_v2024.1.Hs.db", signature_category = "c5",
                          id_type = "entrez")
c5_enricher <- simple_cp_enricher(sig_genes = input_up, de_table = table, db = c5)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'sig_genes' in selecting a method for function 'simple_cp_enricher': object 'input_up' not found
written <- write_xlsx(data = as.data.frame(c5_enricher), excel = "excel/c5_result.xlsx")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'write_xlsx': error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'c5_enricher' not found

9.6 C6

C6 returns no hits.

c6 <- load_gmt_signatures(signatures = "reference/msigdb_v2024.1.Hs.db", signature_category = "c6",
                          id_type = "entrez")
c6_enricher <- simple_cp_enricher(sig_genes = input_up, de_table = table, db = c6)
written <- write_xlsx(data = as.data.frame(c6_enricher), excel = "excel/c6_result.xlsx")

9.7 C7

c7 <- load_gmt_signatures(signatures = "reference/msigdb_v2024.1.Hs.db", signature_category = "c7",
                          id_type = "entrez")
c7_enricher <- simple_cp_enricher(sig_genes = input_up, de_table = table, db = c7)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'sig_genes' in selecting a method for function 'simple_cp_enricher': object 'input_up' not found
written <- write_xlsx(data = as.data.frame(c7_enricher), excel = "excel/c7_result.xlsx")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'write_xlsx': error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'c7_enricher' not found
input_up <- as.data.frame(hs_sig[["deseq"]][["ups"]][[1]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'hs_sig' not found
input_down <- as.data.frame(hs_sig[["deseq"]][["downs"]][[1]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'hs_sig' not found
table <- hs_table[["data"]][[1]]
## Error: object 'hs_table' not found
up_gp <- simple_gprofiler(input_up)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'table' in selecting a method for function '%in%': object 'input_up' not found
up_cp_c8 <- simple_clusterprofiler(input_up, de_table = table,
                                   do_msigdb = TRUE, msigdb_category = "C8",
                                   do_mesh = TRUE, do_dose = TRUE, orgdb_from = "ENSEMBL")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'input_up' not found
write_xlsx(data = as.data.frame(up_cp_c8[["msigdb_data"]]), excel = "excel/c2_increased.xlsx")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'write_xlsx': error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'up_cp_c8' not found
LS0tCnRpdGxlOiAiUHJlcHJvY2Vzc2luZyBzb21lIGh1bWFuIHNhbXBsZXMuIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAgdGhlbWU6IHJlYWRhYmxlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBkZl9wcmludDogcGFnZWQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAgd2lkdGg6IDMwMAogICAga2VlcF9tZDogZmFsc2UKICAgIG1vZGU6IHNlbGZjb250YWluZWQKICAgIHRvY19mbG9hdDogdHJ1ZQogIEJpb2NTdHlsZTo6aHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSwgdGQgewogIGZvbnQtc2l6ZTogMTZweDsKfQpjb2RlLnJ7CiAgZm9udC1zaXplOiAxNnB4Owp9CnByZSB7CiAgZm9udC1zaXplOiAxNnB4Cn0KYm9keSAubWFpbi1jb250YWluZXIgewogICBtYXgtd2lkdGg6IDE2MDBweDsKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShyZXRpY3VsYXRlKQp0dCA8LSB0cnkoZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpKQprbml0cjo6b3B0c19rbml0JHNldCgKICBwcm9ncmVzcyA9IFRSVUUsIHZlcmJvc2UgPSBUUlVFLCB3aWR0aCA9IDkwLCBlY2hvID0gVFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVycm9yID0gVFJVRSwgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDgsIGZpZy5yZXRpbmEgPSAyLAogIG91dC53aWR0aCA9ICIxMDAlIiwgZGV2ID0gInBuZyIsCiAgZGV2LmFyZ3MgPSBsaXN0KHBuZyA9IGxpc3QodHlwZSA9ICJjYWlyby1wbmciKSkpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzID0gNCwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBrbml0ci5kdXBsaWNhdGUubGFiZWwgPSAiYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpKQp2ZXIgPC0gIjIwMjMwNSIKcHJldmlvdXNfZmlsZSA8LSAiIgp2ZXIgPC0gZm9ybWF0KFN5cy5EYXRlKCksICIlWSVtJWQiKQoKIyN0bXAgPC0gc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpCnJtZF9maWxlIDwtICJwcmVwcm9jZXNzLlJtZCIKYGBgCgojIEludHJvZHVjdGlvbgoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CmV4cG9ydCBIU19UWVBFPWdlbmUKZXhwb3J0IEhTX1RBRz1JRApgYGAKCiMjIFRlc3RpbmcgZGlyZWN0b3J5CgpJIHRoaW5rIGZvciBzcGVlZCBzYWtlLCBJIHdpbGwgcnVuIHRoZXNlIHRocm91Z2ggc2FsbW9uLgoKSSBoYXZlIGJlZW4gbWFraW5nIHNvbWUgY2hhbmdlcyB0byBteSBwaXBlbGluZSByZWNlbnRseTsgc28gSSB3aWxsIHB1dAoxMDBrIHJlYWRzIGludG8gYSB0ZXN0IGRpcmVjdG9yeS4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nCm1rZGlyIHRlc3QKY2QgdGVzdApsZXNzIC4uL1NSUi8qUjEqIHwgaGVhZCAtbiA0MDAwMDAgPiByMS5mYXN0cQpsZXNzIC4uL1NSUi8qUjIqIHwgaGVhZCAtbiA0MDAwMDAgPiByMi5mYXN0cQpnemlwICouZmFzdHEKaW5wdXRzPSQoL2Jpbi9scyBvdXRwdXRzLzEyZmFzdHAvKi1mYXN0cC5mYXN0cS54eiB8IHRyICdcbicgJzonKQpjeW9hIC0tbWV0aG9kIHNhbG1vbiAtLXNwZWNpZXMgaGczOF8xMTEgLS1pbnB1dCAkaW5wdXRzIC0tbGlidHlwZSBDRFMgLS1qcHJlZml4IDIwCmBgYAoKIyMgVHJpbW1pbmcgdmlhIGZhc3RwCgpJIGFtIGdvaW5nIHRvIHVzZSB0aGF0IHRyZWUgdG8gcnVuIGV2ZXJ5dGhpbmcgZmlyc3QsIG5vdGFibHkgSSB3YW50IG15CnRvb2xzIHRvIGNvbGxlY3QgbW9yZSB0aG9yb3VnaCBzdGF0aXN0aWNzIG9uIHJ1bnRpbWUgZXRjIHRvIGltcHJvdmUgbXkKbmFzY2VudCBoZXVyaXN0aWNzIHRvIGNob29zZSBtZW1vcnkvdGltZSBvbiB0aGUgY2x1c3Rlci4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzdGFydD0kKHB3ZCkKZm9yIGkgaW4gJCgvYmluL2xzIC1kIFNSKik7IGRvCiAgICBjZCAke3N0YXJ0fS8ke2l9CiAgICBta2RpciB1bnByb2Nlc3NlZAogICAgbXYgKi5mYXN0cS5neiB1bnByb2Nlc3NlZC8KICAgIGN5b2EgLS1tZXRob2QgZmFzdHAgLS1pbnB1dCAkKC9iaW4vbHMgLWQgdW5wcm9jZXNzZWQvKi5mYXN0cS5neiB8IHRyICdcbicgJzonKQpkb25lCmNkICRzdGFydApgYGAKCiMjIFNhbG1vbiBxdWFudGlmaWNhdGlvbgoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CnN0YXJ0PSQocHdkKQpmb3IgaSBpbiAkKC9iaW4vbHMgLWQgU1IqKTsgZG8KICAgIGNkICR7c3RhcnR9LyR7aX0KICAgIGlucHV0cz0kKC9iaW4vbHMgb3V0cHV0cy8xMmZhc3RwLyotZmFzdHAuZmFzdHEueHogfCB0ciAnXG4nICc6JykKICAgIGN5b2EgLS1tZXRob2Qgc2FsbW9uIC0tc3BlY2llcyBoZzM4XzExMSAtLWlucHV0ICRpbnB1dHMgLS1saWJ0eXBlIENEUyAtLWpwcmVmaXggMjAKZG9uZQpjZCAkc3RhcnQKYGBgCgojIExvYWQgYW5ub3RhdGlvbnMKCmBgYHtyfQpoc19hbm5vdCA8LSBsb2FkX2Jpb21hcnRfYW5ub3RhdGlvbnMoeWVhciA9IDIwMjEsIG1vbnRoID0gMDIpCmFubm90IDwtIGhzX2Fubm90W1siZ2VuZV9hbm5vdGF0aW9ucyJdXQpgYGAKCiMgQ29sbGVjdCBwcmVwcm9jZXNzaW5nIGluZm9ybWF0aW9uCgpgYGB7cn0KbWV0YSA8LSBnYXRoZXJfcHJlcHJvY2Vzc2luZ19tZXRhZGF0YSgic2FtcGxlX3NoZWV0cy9QUkpOQTY3NTA5MC54bHN4IikKYGBgCgojIENyZWF0ZSBTRQoKYGBge3J9CnR4X2dlbmVfbWFwIDwtIGhzX2Fubm90W1siZ2VuZV90eF9tYXAiXV0KdHhfZ2VuZV9tYXBbWyJ0cmFuc2NyaXB0Il1dIDwtIGdzdWIoeCA9IHR4X2dlbmVfbWFwW1sidHJhbnNjcmlwdCJdXSwgcGF0dGVybiA9ICJcXC5cXGQrJCIsIHJlcGxhY2VtZW50ID0gIiIpCnJvd25hbWVzKHR4X2dlbmVfbWFwKSA8LSBtYWtlLm5hbWVzKGdzdWIoeCA9IHJvd25hbWVzKHR4X2dlbmVfbWFwKSwgcGF0dGVybiA9ICJcXC5cXGQrJCIsIHJlcGxhY2VtZW50ID0gIiIpLCB1bmlxdWUgPSBUUlVFKQpoc19zZV90eCA8LSBjcmVhdGVfc2UobWV0YVtbIm5ld19tZXRhIl1dLCBnZW5lX2luZm8gPSBhbm5vdCwgZmlsZV9jb2x1bW4gPSAic2FsbW9uX2NvdW50X3RhYmxlIikKaHNfc2VfZ2VuZSA8LSBjcmVhdGVfc2UobWV0YVtbIm5ld19tZXRhIl1dLCBnZW5lX2luZm8gPSBhbm5vdCwgZmlsZV9jb2x1bW4gPSAic2FsbW9uX2NvdW50X3RhYmxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgdHhfZ2VuZV9tYXAgPSB0eF9nZW5lX21hcCkKCmBgYAoKIyBTZXQgY29uZGl0aW9uL2JhdGNoCgpJIGhhdmUgZXh0cmFjdGVkIHR3byBwb3RlbnRpYWxseSBpbnRlcmVzdGluZyBjb2x1bW5zIGZyb20gdGhlCm1ldGFkYXRhLCBhZnRlciB0aGF0IEkgd2lsbCBuZWVkIHRvIHJlYWQgbW9yZSBjYXJlZnVsbHkgaW4gdGhlIHBhcGVyCnRvIHRyeSB0byBnZXQgYSBzZW5zZSBvZiB3aGF0IGlzIHdoYXQuLi4KCmBgYHtyfQpoc19zZSA8LSBzZXRfc2VfY29uZGl0aW9ucyhoc19zZV9nZW5lLCBmYWN0ID0gImNvbnRyb2xwIikgJT4lCiAgc2V0X3NlX2JhdGNoZXMoZmFjdCA9ICJ0eXBlIikKYGBgCgojIEEgY291cGxlIHBsb3RzCgpgYGB7cn0KcGxvdF9sZWdlbmQoaHNfc2UpCnBsb3RfbGlic2l6ZShoc19zZSkKcGxvdF9ub256ZXJvKGhzX3NlKQpgYGAKClByZXN1bWFibHkgd2Ugd2lsbCBuZWVkIHRvIHNlcGFyYXRlIHRoZSBleG9tZSBhbmQgcm5hc2VxIGRhdGE7IGJ1dCBmb3IKdGhlIG1vbWVudCBJIHdpbGwgbGVhdmUgdGhlbSB0b2dldGhlciB0byBzZWUgd2hhdCBJIGNhbiBzZWUuCgpgYGB7cn0KaHNfbm9ybSA8LSBub3JtYWxpemUoaHNfc2UsIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLCBmaWx0ZXIgPSBUUlVFLCBub3JtID0gInF1YW50IikKcGxvdF9wY2EoaHNfbm9ybSkKaHNfbmIgPC0gbm9ybWFsaXplKGhzX3NlLCAgdHJhbnNmb3JtID0gImxvZzIiLCBjb252ZXJ0ID0gImNwbSIsIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gImNvbWJhdCIpCnBsb3RfcGNhKGhzX25iKQpgYGAKCk9rLCBuZXZlcm1pbmQsIHRoZSBleG9tZSBkYXRhIGlzIHRvbyBkaWZmZXJlbnQuCgpgYGB7cn0KaHNfcm5hIDwtIHN1YnNldF9zZShoc19zZSwgc3Vic2V0ID0gImJhdGNoPT0ncm5hc2VxJyIpCmhzX3JuYV9ub3JtIDwtIG5vcm1hbGl6ZShoc19ybmEsIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLCBmaWx0ZXIgPSBUUlVFLCBub3JtID0gInF1YW50IikKbm9ybV9wY2EgPC0gcGxvdF9wY2EoaHNfcm5hX25vcm0pCnBwKGZpbGUgPSAiaW1hZ2VzL25vcm1fcGNhLnBkZiIpCm5vcm1fcGNhCmRldi5vZmYoKQojI2hzX3JuYV9uYiA8LSBub3JtYWxpemUoaHNfcm5hLCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIiwgZmlsdGVyID0gVFJVRSwgYmF0Y2ggPSAic3Zhc2VxIikKIyNwbG90X3BjYShoc19ybmFfbmIpCmBgYAoKIyBFeGNsdWRlIG9kZCBzYW1wbGUKCkluIG91ciBpbml0aWFsIFBDQSBwbG90LCBTUlIxMjk5OTc0NiBsb29rcyBwYXJ0aWN1bGFybHkgc3RyYW5nZS4KCmBgYHtyfQpoc19pZHggPC0gY29sbmFtZXMoaHNfcm5hKSAhPSAiU1JSMTI5OTk3NDYiCmtlcHRfaWRzIDwtIGNvbG5hbWVzKGhzX3JuYSlbaHNfaWR4XQpoc19leGNsdWRlZCA8LSBzdWJzZXRfc2UoaHNfcm5hLCBpZHMgPSBrZXB0X2lkcykKZXhjbHVkZWRfbm9ybSA8LSBub3JtYWxpemUoaHNfZXhjbHVkZWQsIGZpbHRlciA9IFRSVUUsIGNvbnZlcnQgPSAiY3BtIiwgdHJhbnNmb3JtID0gImxvZzIiKQpwbG90X3BjYShleGNsdWRlZF9ub3JtKQpgYGAKCiMgRmlyc3QgdHJ5IERFCgpgYGB7cn0KaHNfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX2V4Y2x1ZGVkLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9zdnMgPSAic3Zhc2VxIiwKICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2ZzdHJpbmcgPSAifiAwICsgY29uZGl0aW9uIiwgZm9yY2UgPSBUUlVFKQpoc190YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcyhoc19kZSwgZXhjZWwgPSAiZXhjZWwvY29udHJvbF92c19oY20ueGxzeCIpCmhzX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKGhzX3RhYmxlLCBleGNlbCA9ICJleGNlbC9jb250cm9sX3ZzX2hjbS1zaWcueGxzeCIpCmBgYAoKIyBPbnRvbG9neSBzaGVuYW5pZ2FucwoKYGBge3J9CmhzX2dwIDwtIGFsbF9jcHJvZmlsZXIoaHNfc2lnLCBoc190YWJsZSkKYGBgCgpBIGZldyBzcGVjaWZpYyBtU2lnREIgY2F0ZWdvcmllczogQzgsIEM3LCBDNSwgQzMsIEMyCgpUaGlzIGlzIGFjdHVhbGx5IEMyIGJlY2F1c2UgSSBuZWVkIHRvIGRvd25sb2FkIGEgbmV3IGNvcHkgb2YgbXNpZ2RiIGluIHRoZSBuZXcgZm9ybWF0LgoKIyMgTmV3IGNvcHkgb2YgbXNpZ2RiCgpJIGRvd25sb2FkZWQgYSBmcmVzaCBjb3B5IG9mIHRoZSBodW1hbiBtU2lnREIgYmVjYXVzZSBteSBjb3B5IHdhcyBpbgp0aGUgb2xkIGZvcm1hdCBhbmQgdGhhdCBubyBsb25nZXIgcGFyc2VzIHdlbGwuCgojIyMgTG9hZCBtc2lnZGIKCmBgYHtyfQp1cF9jcF9jOCA8LSBzaW1wbGVfY2x1c3RlcnByb2ZpbGVyKGlucHV0X3VwLCBkZV90YWJsZSA9IHRhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zaWdfZGIgPSAicmVmZXJlbmNlL21zaWdkYl92MjAyNC4xLkhzLmRiIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb19tc2lnZGIgPSBUUlVFLCBtc2lnZGJfY2F0ZWdvcnkgPSAiQzgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvX21lc2ggPSBUUlVFLCBkb19kb3NlID0gVFJVRSwgb3JnZGJfZnJvbSA9ICJFTlNFTUJMIikKYGBgCgojIyBDMgoKYGBge3J9CmMyIDwtIGxvYWRfZ210X3NpZ25hdHVyZXMoc2lnbmF0dXJlcyA9ICJyZWZlcmVuY2UvbXNpZ2RiX3YyMDI0LjEuSHMuZGIiLCBzaWduYXR1cmVfY2F0ZWdvcnkgPSAiYzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGlkX3R5cGUgPSAiZW50cmV6IikKYzJfZW5yaWNoZXIgPC0gc2ltcGxlX2NwX2VucmljaGVyKHNpZ19nZW5lcyA9IGlucHV0X3VwLCBkZV90YWJsZSA9IHRhYmxlLCBkYiA9IGMyKQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGFzLmRhdGEuZnJhbWUoYzJfZW5yaWNoZXIpLCBleGNlbCA9ICJleGNlbC9jMl9yZXN1bHQueGxzeCIpCmBgYAoKIyMgQzMKCmBgYHtyfQpjMyA8LSBsb2FkX2dtdF9zaWduYXR1cmVzKHNpZ25hdHVyZXMgPSAicmVmZXJlbmNlL21zaWdkYl92MjAyNC4xLkhzLmRiIiwgc2lnbmF0dXJlX2NhdGVnb3J5ID0gImMzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBpZF90eXBlID0gImVudHJleiIpCmMzX2VucmljaGVyIDwtIHNpbXBsZV9jcF9lbnJpY2hlcihzaWdfZ2VuZXMgPSBpbnB1dF91cCwgZGVfdGFibGUgPSB0YWJsZSwgZGIgPSBjMykKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBhcy5kYXRhLmZyYW1lKGMzX2VucmljaGVyKSwgZXhjZWwgPSAiZXhjZWwvYzNfcmVzdWx0Lnhsc3giKQpgYGAKCiMjIEM0CgpgYGB7cn0KYzQgPC0gbG9hZF9nbXRfc2lnbmF0dXJlcyhzaWduYXR1cmVzID0gInJlZmVyZW5jZS9tc2lnZGJfdjIwMjQuMS5Icy5kYiIsIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJjNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWRfdHlwZSA9ICJlbnRyZXoiKQpjNF9lbnJpY2hlciA8LSBzaW1wbGVfY3BfZW5yaWNoZXIoc2lnX2dlbmVzID0gaW5wdXRfdXAsIGRlX3RhYmxlID0gdGFibGUsIGRiID0gYzQpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gYXMuZGF0YS5mcmFtZShjNF9lbnJpY2hlciksIGV4Y2VsID0gImV4Y2VsL2M0X3Jlc3VsdC54bHN4IikKYGBgCgojIyBDNQoKYGBge3J9CmM1IDwtIGxvYWRfZ210X3NpZ25hdHVyZXMoc2lnbmF0dXJlcyA9ICJyZWZlcmVuY2UvbXNpZ2RiX3YyMDI0LjEuSHMuZGIiLCBzaWduYXR1cmVfY2F0ZWdvcnkgPSAiYzUiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGlkX3R5cGUgPSAiZW50cmV6IikKYzVfZW5yaWNoZXIgPC0gc2ltcGxlX2NwX2VucmljaGVyKHNpZ19nZW5lcyA9IGlucHV0X3VwLCBkZV90YWJsZSA9IHRhYmxlLCBkYiA9IGM1KQp3cml0dGVuIDwtIHdyaXRlX3hsc3goZGF0YSA9IGFzLmRhdGEuZnJhbWUoYzVfZW5yaWNoZXIpLCBleGNlbCA9ICJleGNlbC9jNV9yZXN1bHQueGxzeCIpCmBgYAoKIyMgQzYKCkM2IHJldHVybnMgbm8gaGl0cy4KCmBgYHtyLCBldmFsPUZBTFNFfQpjNiA8LSBsb2FkX2dtdF9zaWduYXR1cmVzKHNpZ25hdHVyZXMgPSAicmVmZXJlbmNlL21zaWdkYl92MjAyNC4xLkhzLmRiIiwgc2lnbmF0dXJlX2NhdGVnb3J5ID0gImM2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBpZF90eXBlID0gImVudHJleiIpCmM2X2VucmljaGVyIDwtIHNpbXBsZV9jcF9lbnJpY2hlcihzaWdfZ2VuZXMgPSBpbnB1dF91cCwgZGVfdGFibGUgPSB0YWJsZSwgZGIgPSBjNikKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGEgPSBhcy5kYXRhLmZyYW1lKGM2X2VucmljaGVyKSwgZXhjZWwgPSAiZXhjZWwvYzZfcmVzdWx0Lnhsc3giKQpgYGAKCiMjIEM3CgpgYGB7cn0KYzcgPC0gbG9hZF9nbXRfc2lnbmF0dXJlcyhzaWduYXR1cmVzID0gInJlZmVyZW5jZS9tc2lnZGJfdjIwMjQuMS5Icy5kYiIsIHNpZ25hdHVyZV9jYXRlZ29yeSA9ICJjNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWRfdHlwZSA9ICJlbnRyZXoiKQpjN19lbnJpY2hlciA8LSBzaW1wbGVfY3BfZW5yaWNoZXIoc2lnX2dlbmVzID0gaW5wdXRfdXAsIGRlX3RhYmxlID0gdGFibGUsIGRiID0gYzcpCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhID0gYXMuZGF0YS5mcmFtZShjN19lbnJpY2hlciksIGV4Y2VsID0gImV4Y2VsL2M3X3Jlc3VsdC54bHN4IikKYGBgCgpgYGB7cn0KaW5wdXRfdXAgPC0gYXMuZGF0YS5mcmFtZShoc19zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbMV1dKQppbnB1dF9kb3duIDwtIGFzLmRhdGEuZnJhbWUoaHNfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dKQp0YWJsZSA8LSBoc190YWJsZVtbImRhdGEiXV1bWzFdXQoKdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihpbnB1dF91cCkKCnVwX2NwX2M4IDwtIHNpbXBsZV9jbHVzdGVycHJvZmlsZXIoaW5wdXRfdXAsIGRlX3RhYmxlID0gdGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9fbXNpZ2RiID0gVFJVRSwgbXNpZ2RiX2NhdGVnb3J5ID0gIkM4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb19tZXNoID0gVFJVRSwgZG9fZG9zZSA9IFRSVUUsIG9yZ2RiX2Zyb20gPSAiRU5TRU1CTCIpCndyaXRlX3hsc3goZGF0YSA9IGFzLmRhdGEuZnJhbWUodXBfY3BfYzhbWyJtc2lnZGJfZGF0YSJdXSksIGV4Y2VsID0gImV4Y2VsL2MyX2luY3JlYXNlZC54bHN4IikKYGBgCg==