1 Introduction

Thanks to my time playing with Carrie and the Taneyhill samples, I re-evaluated suppa and think there are some potentially compelling use-case scenarios. Thus, I want to take the improved processing I employed with that data and translate it to some of our other datasets, starting with Cecilia’s human macrophages infected with Leishmania major or amazonensis.

My reworked suppa invocation is able to use either salmon quantifications or htseq-count transcript tables. Thus I think I have everything I need in the multiple_leishmania project directory wherein I passed all of our samples across every project to a single salmon-based pipeline. In addition I have some sample sheets there which should make it relatively easy to pull out the relevant samples.

1.1 Setting up

This document is in its own tree, so I am going to symlink my preprocessing directory from the multiple_leishmania tree and copy the most relevant sample sheet here.

I thus pruned the master sample sheet to include only the mbio data, then separated that into two new sheets, one with every macrophage sample (e.g. no promastigotes), and one with only the major infections or uninfected (e.g. no amazonensis nor beads).

The most relevant metadata columns for my purposes are therefore:

(In the file ‘suppa_samples_only_major.xlsx’) sampleid, infect_state, expt_time, donor, hg38_111_salmon

With that in mind, let us attempt to spin up suppa to compare ‘yes’ vs ‘no’ from the infect_state column using the salmon data.

1.1.1 Some details

I wrote some code to simplify the usage of suppa so that I can feed it a sample sheet filename, column of interest, and numerator/denominator. The code then collects the quantifications associated with the relevant samples, and runs the various suppa tools to generate all the various intermediate files used to compare splicing events among the desired groups.

1.2 Annotations

hg38_111_annot <- load_biomart_annotations(archive = FALSE)
## The biomart annotations file already exists, loading from it.
annot <- hg38_111_annot[["annotation"]]

I deleted the annotations and genome for this older release of the human genome. Thus I will need to either remap or redownload them. I am thinking that those are old enough it is worth while to redo.

1.3 So redo salmon first

I decided also to use the newest human annotation set with the assumption that there are new fun splicing annotations available.

module add cyoa/202402
cd preprocessing
base=~/scratch/rnaseq/splicing_leishmania_2023/

start=$(pwd)
for i in $(/bin/cat  ${base}/sample_sheets/only_major_sampleids.txt); do
    cd $i
    cyoa --method salmon --species hg38_111 --input r1.fastq.xz:r2.fastq.xz
    cyoa --method hisat --species hg38_111 --input r1.fastq.xz:r2.fastq.xz --gff_type gene --gff_tag ID --stranded no
    cd $start
done


start=$(pwd)
for i in $(/bin/cat  ${base}/sample_sheets/bead_samples.txt); do
    cd $i
    cyoa --method salmon --species hg38_111 --input r1.fastq.xz:r2.fastq.xz
    cyoa --method hisat --species hg38_111 --input r1.fastq.xz:r2.fastq.xz --gff_type gene --gff_tag ID --stranded no
    cd $start
done

ok, so now the relevant metadata column is hg38_111_salmon

module add cyoa
module add suppa
cyoa --method suppa --species hg38_111 --input sample_sheets/suppa_samples_only_major.xlsx \
     --file_column hg38_111_salmon --condition_column infect_state

2 Gather output files and plot the result

output_prefix <- "outputs/90suppa_hg38_111_infect_state"
dpsi_prefix <- file.path(output_prefix, "diff")
tpm_prefix <- file.path(output_prefix, "tpm")
event_prefix <- file.path(output_prefix, "events")

numerator <- "yes"
denominator <- "no"
comparison_prefix <- glue("{numerator}_{denominator}")
tx_dpsi <- file.path(dpsi_prefix, glue("{comparison_prefix}_ioi_empirical.dpsi"))
tx_tpm <- file.path(dpsi_prefix, glue("{comparison_prefix}_ioi_empirical_avglogtpm.tab"))
## test_events_ioe <- file.path(event_prefix, "local_as_events_SE_strict.ioe")
tx_events <- file.path(event_prefix, "transcript_events.ioi")
tx_psi <- file.path(dpsi_prefix, glue("{comparison_prefix}_ioi_classical.psivec"))
## Attempt to see delta transcripts.
#tx_plot <- plot_suppa(file_prefix = output_prefix, type = "transcript", annot = annot,
#                      numerator = numerator, denominator = denominator)

3 By event types and infected/uninfected

inf_uninf_event_plot <- plot_suppa(file_prefix = "outputs/90suppa_hg38_111_infect_state",
                                   numerator = numerator,
                                   denominator = denominator, type = "type",
                                   annot = hg38_111_annot$gene_annotation,
                                   annot_column = "hgnc_symbol",
                                   alpha = 0.5)
inf_uninf_event_plot$ma
## Warning: Removed 121164 rows containing missing values or values outside the scale range (`geom_point()`).
## Warning: Removed 2 rows containing missing values or values outside the scale range (`geom_text_repel()`).
## Warning: ggrepel: 528 unlabeled data points (too many overlaps). Consider increasing max.overlaps

sig_events <- inf_uninf_event_plot[["sig"]]
## I think the following should not be needed next time I run this
## (e.g. I think I changed the function to take this into account.
rownames(sig_events) <- sig_events[["Row.names"]]
sig_events[["Row.names"]] <- NULL
inf_uninf_events <- merge(sig_events, annot,
                          by.x = "gene_name", by.y = "row.names",
                          all.x = TRUE)
write_xlsx(excel = glue("excel/{comparison_prefix}_testing_suppa_sigevents.xlsx"),
                        data = inf_uninf_events)
## Deleting the file excel/yes_no_testing_suppa_sigevents.xlsx before writing the tables.
## write_xlsx() wrote excel/yes_no_testing_suppa_sigevents.xlsx.
## The cursor is on sheet first, row: 570 column: 98.

4 Repeat, considering uninfected vs bead

module add cyoa
module add suppa
cyoa --method suppa --species hg38_111 --input sample_sheets/suppa_samples_uninf_bead.xlsx \
     --file_column hg38_111_salmon --condition_column pathogen_species

4.1 Look at the result

numerator <- "none"
denominator <- "bead"
comparison_prefix <- glue("{numerator}_{denominator}")
bead_uninf_plot <- plot_suppa(file_prefix = "outputs/90suppa_hg38_111_pathogen_species",
                              numerator = numerator,
                              denominator = denominator, type = "type",
                              annot = hg38_111_annot$gene_annotation,
                              annot_column = "hgnc_symbol",
                              alpha = 0.5)
## Error in read.table(t, sep = "\t"): duplicate 'row.names' are not allowed
bead_uninf_plot$ma
## Error in eval(expr, envir, enclos): object 'bead_uninf_plot' not found
sig_events <- bead_uninf_plot[["sig"]]
## Error in eval(expr, envir, enclos): object 'bead_uninf_plot' not found
## I think the following should not be needed next time I run this
## (e.g. I think I changed the function to take this into account.
rownames(sig_events) <- sig_events[["Row.names"]]
sig_events[["Row.names"]] <- NULL
bead_uninf_events <- merge(sig_events, annot,
                           by.x = "gene_name", by.y = "row.names",
                           all.x = TRUE)
write_xlsx(excel = glue("excel/{comparison_prefix}_testing_suppa_sigevents.xlsx"),
                        data = bead_uninf_events)
## Deleting the file excel/none_bead_testing_suppa_sigevents.xlsx before writing the tables.
## write_xlsx() wrote excel/none_bead_testing_suppa_sigevents.xlsx.
## The cursor is on sheet first, row: 570 column: 98.

4.2 Take a moment to examine these events

inf_uninf_gp <- simple_gprofiler(inf_uninf_events[["gene_name"]])
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
enrichplot::dotplot(inf_uninf_gp$GO_enrich)

pp(file = "images/inf_uninf_bp.png", height=20, width=12)
inf_uninf_gp$pvalue_plots$BP
dev.off()
## png 
##   2
bead_uninf_gp <- simple_gprofiler(bead_uninf_events[["gene_name"]])
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
enrichplot::dotplot(bead_uninf_gp$GO_enrich)

4.3 Consider 4 hr vs uninfected

module add cyoa
module add suppa
cyoa --method suppa --species hg38_111 --input sample_sheets/suppa_samples_uninf_all4hr.xlsx \
     --file_column hg38_111_salmon --condition_column infect_state \
     --numerator inf --denominator uninf
numerator <- "t4h"
denominator <- "no"
comparison_prefix <- glue("{numerator}_{denominator}")
uninf_4h_plot <- plot_suppa(file_prefix = "outputs/90suppa_hg38_111_infect_state",
                              numerator = numerator,
                              denominator = denominator, type = "type",
                              annot = hg38_111_annot$gene_annotation,
                              annot_column = "hgnc_symbol",
                              alpha = 0.5)
uninf_4h_plot$ma
## Warning: Removed 120087 rows containing missing values or values outside the scale range (`geom_point()`).
## Warning: Removed 6 rows containing missing values or values outside the scale range (`geom_text_repel()`).
## Warning: ggrepel: 824 unlabeled data points (too many overlaps). Consider increasing max.overlaps

sig_events <- uninf_4h_plot[["sig"]]
## I think the following should not be needed next time I run this
## (e.g. I think I changed the function to take this into account.
rownames(sig_events) <- sig_events[["Row.names"]]
sig_events[["Row.names"]] <- NULL
t4h_uninf_events <- merge(sig_events, annot,
                           by.x = "gene_name", by.y = "row.names",
                           all.x = TRUE)
write_xlsx(excel = glue("excel/{comparison_prefix}_testing_suppa_sigevents.xlsx"),
                        data = t4h_uninf_events)
## Deleting the file excel/t4h_no_testing_suppa_sigevents.xlsx before writing the tables.
## write_xlsx() wrote excel/t4h_no_testing_suppa_sigevents.xlsx.
## The cursor is on sheet first, row: 877 column: 79.
t4h_uninf_gp <- simple_gprofiler(t4h_uninf_events[["gene_name"]])
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
enrichplot::dotplot(t4h_uninf_gp$GO_enrich)

pp(file = "images/inf_uninf_bp.png", height=20, width=12)
t4h_uninf_gp$pvalue_plots$BP
dev.off()
## png 
##   2
bead_uninf_gp <- simple_gprofiler(bead_uninf_events[["gene_name"]])
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## No results to show
## Please make sure that the organism is correct or set significant = FALSE
## Add a little logic here to use enrichplot::dotplot().
enrichplot::dotplot(bead_uninf_gp$GO_enrich)

LS0tCnRpdGxlOiAiRXhwbG9yaW5nIHNwbGljaW5nIGluIG91ciBpbmZlY3RlZC91bmluZmVjdGVkIG1hY3JvcGhhZ2Ugc2FtcGxlcy4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCiAgcm1kZm9ybWF0czo6cmVhZHRoZWRvd246CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGRmX3ByaW50OiBwYWdlZAogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGZpZ19oZWlnaHQ6IDcKICAgIGZpZ193aWR0aDogNwogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICB3aWR0aDogMzAwCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgdG9jX2Zsb2F0OiB0cnVlCiAgQmlvY1N0eWxlOjpodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgpib2R5LCB0ZCB7CiAgZm9udC1zaXplOiAxNnB4Owp9CmNvZGUucnsKICBmb250LXNpemU6IDE2cHg7Cn0KcHJlIHsKIGZvbnQtc2l6ZTogMTZweAp9CmJvZHkgLm1haW4tY29udGFpbmVyIHsKICBtYXgtd2lkdGg6IDE2MDBweDsKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShocGdsdG9vbHMpCmxpYnJhcnkocmV0aWN1bGF0ZSkKdHQgPC0gdHJ5KGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKSkKa25pdHI6Om9wdHNfa25pdCRzZXQoCiAgcHJvZ3Jlc3MgPSBUUlVFLCB2ZXJib3NlID0gVFJVRSwgd2lkdGggPSA5MCwgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlcnJvciA9IFRSVUUsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA4LCBmaWcucmV0aW5hID0gMiwKICBmaWcucG9zID0gInQiLCBmaWcuYWxpZ24gPSAiY2VudGVyIiwgZHBpID0gaWYgKGtuaXRyOjppc19sYXRleF9vdXRwdXQoKSkgNzIgZWxzZSAzMDAsCiAgb3V0LndpZHRoID0gIjEwMCUiLCBkZXYgPSAicG5nIiwKICBkZXYuYXJncyA9IGxpc3QocG5nID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKSkKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWwgPSAiYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplID0gMTIpKQp2ZXIgPC0gIjIwMjMwNSIKcHJldmlvdXNfZmlsZSA8LSAiIgp2ZXIgPC0gZm9ybWF0KFN5cy5EYXRlKCksICIlWSVtJWQiKQoKIyN0bXAgPC0gc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpCnJtZF9maWxlIDwtICJpbmRleC5SbWQiCmBgYAoKIyBJbnRyb2R1Y3Rpb24KClRoYW5rcyB0byBteSB0aW1lIHBsYXlpbmcgd2l0aCBDYXJyaWUgYW5kIHRoZSBUYW5leWhpbGwgc2FtcGxlcywgSQpyZS1ldmFsdWF0ZWQgc3VwcGEgYW5kIHRoaW5rIHRoZXJlIGFyZSBzb21lIHBvdGVudGlhbGx5IGNvbXBlbGxpbmcKdXNlLWNhc2Ugc2NlbmFyaW9zLiAgVGh1cywgSSB3YW50IHRvIHRha2UgdGhlIGltcHJvdmVkIHByb2Nlc3NpbmcgSQplbXBsb3llZCB3aXRoIHRoYXQgZGF0YSBhbmQgdHJhbnNsYXRlIGl0IHRvIHNvbWUgb2Ygb3VyIG90aGVyCmRhdGFzZXRzLCBzdGFydGluZyB3aXRoIENlY2lsaWEncyBodW1hbiBtYWNyb3BoYWdlcyBpbmZlY3RlZCB3aXRoCkxlaXNobWFuaWEgbWFqb3Igb3IgYW1hem9uZW5zaXMuCgpNeSByZXdvcmtlZCBzdXBwYSBpbnZvY2F0aW9uIGlzIGFibGUgdG8gdXNlIGVpdGhlciBzYWxtb24KcXVhbnRpZmljYXRpb25zIG9yIGh0c2VxLWNvdW50IHRyYW5zY3JpcHQgdGFibGVzLiAgVGh1cyBJIHRoaW5rIEkgaGF2ZQpldmVyeXRoaW5nIEkgbmVlZCBpbiB0aGUgbXVsdGlwbGVfbGVpc2htYW5pYSBwcm9qZWN0IGRpcmVjdG9yeSB3aGVyZWluCkkgcGFzc2VkIGFsbCBvZiBvdXIgc2FtcGxlcyBhY3Jvc3MgZXZlcnkgcHJvamVjdCB0byBhIHNpbmdsZQpzYWxtb24tYmFzZWQgcGlwZWxpbmUuICBJbiBhZGRpdGlvbiBJIGhhdmUgc29tZSBzYW1wbGUgc2hlZXRzIHRoZXJlCndoaWNoIHNob3VsZCBtYWtlIGl0IHJlbGF0aXZlbHkgZWFzeSB0byBwdWxsIG91dCB0aGUgcmVsZXZhbnQgc2FtcGxlcy4KCiMjIFNldHRpbmcgdXAKClRoaXMgZG9jdW1lbnQgaXMgaW4gaXRzIG93biB0cmVlLCBzbyBJIGFtIGdvaW5nIHRvIHN5bWxpbmsgbXkKcHJlcHJvY2Vzc2luZyBkaXJlY3RvcnkgZnJvbSB0aGUgbXVsdGlwbGVfbGVpc2htYW5pYSB0cmVlIGFuZCBjb3B5IHRoZQptb3N0IHJlbGV2YW50IHNhbXBsZSBzaGVldCBoZXJlLgoKSSB0aHVzIHBydW5lZCB0aGUgbWFzdGVyIHNhbXBsZSBzaGVldCB0byBpbmNsdWRlIG9ubHkgdGhlIG1iaW8gZGF0YSwKdGhlbiBzZXBhcmF0ZWQgdGhhdCBpbnRvIHR3byBuZXcgc2hlZXRzLCBvbmUgd2l0aCBldmVyeSBtYWNyb3BoYWdlCnNhbXBsZSAoZS5nLiBubyBwcm9tYXN0aWdvdGVzKSwgYW5kIG9uZSB3aXRoIG9ubHkgdGhlIG1ham9yIGluZmVjdGlvbnMKb3IgdW5pbmZlY3RlZCAoZS5nLiBubyBhbWF6b25lbnNpcyBub3IgYmVhZHMpLgoKVGhlIG1vc3QgcmVsZXZhbnQgbWV0YWRhdGEgY29sdW1ucyBmb3IgbXkgcHVycG9zZXMgYXJlIHRoZXJlZm9yZToKCihJbiB0aGUgZmlsZSAnc3VwcGFfc2FtcGxlc19vbmx5X21ham9yLnhsc3gnKQpzYW1wbGVpZCwgaW5mZWN0X3N0YXRlLCBleHB0X3RpbWUsIGRvbm9yLCBoZzM4XzExMV9zYWxtb24KCldpdGggdGhhdCBpbiBtaW5kLCBsZXQgdXMgYXR0ZW1wdCB0byBzcGluIHVwIHN1cHBhIHRvIGNvbXBhcmUgJ3llcycgdnMKJ25vJyBmcm9tIHRoZSBpbmZlY3Rfc3RhdGUgY29sdW1uIHVzaW5nIHRoZSBzYWxtb24gZGF0YS4KCiMjIyBTb21lIGRldGFpbHMKCkkgd3JvdGUgc29tZSBjb2RlIHRvIHNpbXBsaWZ5IHRoZSB1c2FnZSBvZiBzdXBwYSBzbyB0aGF0IEkgY2FuIGZlZWQgaXQKYSBzYW1wbGUgc2hlZXQgZmlsZW5hbWUsIGNvbHVtbiBvZiBpbnRlcmVzdCwgYW5kCm51bWVyYXRvci9kZW5vbWluYXRvci4gIFRoZSBjb2RlIHRoZW4gY29sbGVjdHMgdGhlIHF1YW50aWZpY2F0aW9ucwphc3NvY2lhdGVkIHdpdGggdGhlIHJlbGV2YW50IHNhbXBsZXMsIGFuZCBydW5zIHRoZSB2YXJpb3VzIHN1cHBhIHRvb2xzCnRvIGdlbmVyYXRlIGFsbCB0aGUgdmFyaW91cyBpbnRlcm1lZGlhdGUgZmlsZXMgdXNlZCB0byBjb21wYXJlCnNwbGljaW5nIGV2ZW50cyBhbW9uZyB0aGUgZGVzaXJlZCBncm91cHMuCgojIyBBbm5vdGF0aW9ucwoKYGBge3J9CmhnMzhfMTExX2Fubm90IDwtIGxvYWRfYmlvbWFydF9hbm5vdGF0aW9ucyhhcmNoaXZlID0gRkFMU0UpCmFubm90IDwtIGhnMzhfMTExX2Fubm90W1siYW5ub3RhdGlvbiJdXQpgYGAKCkkgZGVsZXRlZCB0aGUgYW5ub3RhdGlvbnMgYW5kIGdlbm9tZSBmb3IgdGhpcyBvbGRlciByZWxlYXNlIG9mIHRoZQpodW1hbiBnZW5vbWUuICBUaHVzIEkgd2lsbCBuZWVkIHRvIGVpdGhlciByZW1hcCBvciByZWRvd25sb2FkIHRoZW0uICBJCmFtIHRoaW5raW5nIHRoYXQgdGhvc2UgYXJlIG9sZCBlbm91Z2ggaXQgaXMgd29ydGggd2hpbGUgdG8gcmVkby4KCiMjIFNvIHJlZG8gc2FsbW9uIGZpcnN0CgpJIGRlY2lkZWQgYWxzbyB0byB1c2UgdGhlIG5ld2VzdCBodW1hbiBhbm5vdGF0aW9uIHNldCB3aXRoIHRoZQphc3N1bXB0aW9uIHRoYXQgdGhlcmUgYXJlIG5ldyBmdW4gc3BsaWNpbmcgYW5ub3RhdGlvbnMgYXZhaWxhYmxlLgoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm1vZHVsZSBhZGQgY3lvYS8yMDI0MDIKY2QgcHJlcHJvY2Vzc2luZwpiYXNlPX4vc2NyYXRjaC9ybmFzZXEvc3BsaWNpbmdfbGVpc2htYW5pYV8yMDIzLwoKc3RhcnQ9JChwd2QpCmZvciBpIGluICQoL2Jpbi9jYXQgICR7YmFzZX0vc2FtcGxlX3NoZWV0cy9vbmx5X21ham9yX3NhbXBsZWlkcy50eHQpOyBkbwogICAgY2QgJGkKICAgIGN5b2EgLS1tZXRob2Qgc2FsbW9uIC0tc3BlY2llcyBoZzM4XzExMSAtLWlucHV0IHIxLmZhc3RxLnh6OnIyLmZhc3RxLnh6CiAgICBjeW9hIC0tbWV0aG9kIGhpc2F0IC0tc3BlY2llcyBoZzM4XzExMSAtLWlucHV0IHIxLmZhc3RxLnh6OnIyLmZhc3RxLnh6IC0tZ2ZmX3R5cGUgZ2VuZSAtLWdmZl90YWcgSUQgLS1zdHJhbmRlZCBubwogICAgY2QgJHN0YXJ0CmRvbmUKCgpzdGFydD0kKHB3ZCkKZm9yIGkgaW4gJCgvYmluL2NhdCAgJHtiYXNlfS9zYW1wbGVfc2hlZXRzL2JlYWRfc2FtcGxlcy50eHQpOyBkbwogICAgY2QgJGkKICAgIGN5b2EgLS1tZXRob2Qgc2FsbW9uIC0tc3BlY2llcyBoZzM4XzExMSAtLWlucHV0IHIxLmZhc3RxLnh6OnIyLmZhc3RxLnh6CiAgICBjeW9hIC0tbWV0aG9kIGhpc2F0IC0tc3BlY2llcyBoZzM4XzExMSAtLWlucHV0IHIxLmZhc3RxLnh6OnIyLmZhc3RxLnh6IC0tZ2ZmX3R5cGUgZ2VuZSAtLWdmZl90YWcgSUQgLS1zdHJhbmRlZCBubwogICAgY2QgJHN0YXJ0CmRvbmUKYGBgCgpvaywgc28gbm93IHRoZSByZWxldmFudCBtZXRhZGF0YSBjb2x1bW4gaXMgaGczOF8xMTFfc2FsbW9uCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbW9kdWxlIGFkZCBjeW9hCm1vZHVsZSBhZGQgc3VwcGEKY3lvYSAtLW1ldGhvZCBzdXBwYSAtLXNwZWNpZXMgaGczOF8xMTEgLS1pbnB1dCBzYW1wbGVfc2hlZXRzL3N1cHBhX3NhbXBsZXNfb25seV9tYWpvci54bHN4IFwKICAgICAtLWZpbGVfY29sdW1uIGhnMzhfMTExX3NhbG1vbiAtLWNvbmRpdGlvbl9jb2x1bW4gaW5mZWN0X3N0YXRlCmBgYAoKIyBHYXRoZXIgb3V0cHV0IGZpbGVzIGFuZCBwbG90IHRoZSByZXN1bHQKCmBgYHtyfQpvdXRwdXRfcHJlZml4IDwtICJvdXRwdXRzLzkwc3VwcGFfaGczOF8xMTFfaW5mZWN0X3N0YXRlIgpkcHNpX3ByZWZpeCA8LSBmaWxlLnBhdGgob3V0cHV0X3ByZWZpeCwgImRpZmYiKQp0cG1fcHJlZml4IDwtIGZpbGUucGF0aChvdXRwdXRfcHJlZml4LCAidHBtIikKZXZlbnRfcHJlZml4IDwtIGZpbGUucGF0aChvdXRwdXRfcHJlZml4LCAiZXZlbnRzIikKCm51bWVyYXRvciA8LSAieWVzIgpkZW5vbWluYXRvciA8LSAibm8iCmNvbXBhcmlzb25fcHJlZml4IDwtIGdsdWUoIntudW1lcmF0b3J9X3tkZW5vbWluYXRvcn0iKQp0eF9kcHNpIDwtIGZpbGUucGF0aChkcHNpX3ByZWZpeCwgZ2x1ZSgie2NvbXBhcmlzb25fcHJlZml4fV9pb2lfZW1waXJpY2FsLmRwc2kiKSkKdHhfdHBtIDwtIGZpbGUucGF0aChkcHNpX3ByZWZpeCwgZ2x1ZSgie2NvbXBhcmlzb25fcHJlZml4fV9pb2lfZW1waXJpY2FsX2F2Z2xvZ3RwbS50YWIiKSkKIyMgdGVzdF9ldmVudHNfaW9lIDwtIGZpbGUucGF0aChldmVudF9wcmVmaXgsICJsb2NhbF9hc19ldmVudHNfU0Vfc3RyaWN0LmlvZSIpCnR4X2V2ZW50cyA8LSBmaWxlLnBhdGgoZXZlbnRfcHJlZml4LCAidHJhbnNjcmlwdF9ldmVudHMuaW9pIikKdHhfcHNpIDwtIGZpbGUucGF0aChkcHNpX3ByZWZpeCwgZ2x1ZSgie2NvbXBhcmlzb25fcHJlZml4fV9pb2lfY2xhc3NpY2FsLnBzaXZlYyIpKQojIyBBdHRlbXB0IHRvIHNlZSBkZWx0YSB0cmFuc2NyaXB0cy4KI3R4X3Bsb3QgPC0gcGxvdF9zdXBwYShmaWxlX3ByZWZpeCA9IG91dHB1dF9wcmVmaXgsIHR5cGUgPSAidHJhbnNjcmlwdCIsIGFubm90ID0gYW5ub3QsCiMgICAgICAgICAgICAgICAgICAgICAgbnVtZXJhdG9yID0gbnVtZXJhdG9yLCBkZW5vbWluYXRvciA9IGRlbm9taW5hdG9yKQpgYGAKCiMgQnkgZXZlbnQgdHlwZXMgYW5kIGluZmVjdGVkL3VuaW5mZWN0ZWQKCmBgYHtyfQppbmZfdW5pbmZfZXZlbnRfcGxvdCA8LSBwbG90X3N1cHBhKGZpbGVfcHJlZml4ID0gIm91dHB1dHMvOTBzdXBwYV9oZzM4XzExMV9pbmZlY3Rfc3RhdGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bWVyYXRvciA9IG51bWVyYXRvciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZW5vbWluYXRvciA9IGRlbm9taW5hdG9yLCB0eXBlID0gInR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90ID0gaGczOF8xMTFfYW5ub3QkZ2VuZV9hbm5vdGF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90X2NvbHVtbiA9ICJoZ25jX3N5bWJvbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjUpCmluZl91bmluZl9ldmVudF9wbG90JG1hCgpzaWdfZXZlbnRzIDwtIGluZl91bmluZl9ldmVudF9wbG90W1sic2lnIl1dCiMjIEkgdGhpbmsgdGhlIGZvbGxvd2luZyBzaG91bGQgbm90IGJlIG5lZWRlZCBuZXh0IHRpbWUgSSBydW4gdGhpcwojIyAoZS5nLiBJIHRoaW5rIEkgY2hhbmdlZCB0aGUgZnVuY3Rpb24gdG8gdGFrZSB0aGlzIGludG8gYWNjb3VudC4Kcm93bmFtZXMoc2lnX2V2ZW50cykgPC0gc2lnX2V2ZW50c1tbIlJvdy5uYW1lcyJdXQpzaWdfZXZlbnRzW1siUm93Lm5hbWVzIl1dIDwtIE5VTEwKaW5mX3VuaW5mX2V2ZW50cyA8LSBtZXJnZShzaWdfZXZlbnRzLCBhbm5vdCwKICAgICAgICAgICAgICAgICAgICAgICAgICBieS54ID0gImdlbmVfbmFtZSIsIGJ5LnkgPSAicm93Lm5hbWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBhbGwueCA9IFRSVUUpCndyaXRlX3hsc3goZXhjZWwgPSBnbHVlKCJleGNlbC97Y29tcGFyaXNvbl9wcmVmaXh9X3Rlc3Rpbmdfc3VwcGFfc2lnZXZlbnRzLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGluZl91bmluZl9ldmVudHMpCmBgYAoKIyBSZXBlYXQsIGNvbnNpZGVyaW5nIHVuaW5mZWN0ZWQgdnMgYmVhZAoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm1vZHVsZSBhZGQgY3lvYQptb2R1bGUgYWRkIHN1cHBhCmN5b2EgLS1tZXRob2Qgc3VwcGEgLS1zcGVjaWVzIGhnMzhfMTExIC0taW5wdXQgc2FtcGxlX3NoZWV0cy9zdXBwYV9zYW1wbGVzX3VuaW5mX2JlYWQueGxzeCBcCiAgICAgLS1maWxlX2NvbHVtbiBoZzM4XzExMV9zYWxtb24gLS1jb25kaXRpb25fY29sdW1uIHBhdGhvZ2VuX3NwZWNpZXMKYGBgCgojIyBMb29rIGF0IHRoZSByZXN1bHQKCmBgYHtyfQpudW1lcmF0b3IgPC0gIm5vbmUiCmRlbm9taW5hdG9yIDwtICJiZWFkIgpjb21wYXJpc29uX3ByZWZpeCA8LSBnbHVlKCJ7bnVtZXJhdG9yfV97ZGVub21pbmF0b3J9IikKYmVhZF91bmluZl9wbG90IDwtIHBsb3Rfc3VwcGEoZmlsZV9wcmVmaXggPSAib3V0cHV0cy85MHN1cHBhX2hnMzhfMTExX3BhdGhvZ2VuX3NwZWNpZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1lcmF0b3IgPSBudW1lcmF0b3IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbm9taW5hdG9yID0gZGVub21pbmF0b3IsIHR5cGUgPSAidHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90ID0gaGczOF8xMTFfYW5ub3QkZ2VuZV9hbm5vdGF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdF9jb2x1bW4gPSAiaGduY19zeW1ib2wiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNSkKYmVhZF91bmluZl9wbG90JG1hCgpzaWdfZXZlbnRzIDwtIGJlYWRfdW5pbmZfcGxvdFtbInNpZyJdXQojIyBJIHRoaW5rIHRoZSBmb2xsb3dpbmcgc2hvdWxkIG5vdCBiZSBuZWVkZWQgbmV4dCB0aW1lIEkgcnVuIHRoaXMKIyMgKGUuZy4gSSB0aGluayBJIGNoYW5nZWQgdGhlIGZ1bmN0aW9uIHRvIHRha2UgdGhpcyBpbnRvIGFjY291bnQuCnJvd25hbWVzKHNpZ19ldmVudHMpIDwtIHNpZ19ldmVudHNbWyJSb3cubmFtZXMiXV0Kc2lnX2V2ZW50c1tbIlJvdy5uYW1lcyJdXSA8LSBOVUxMCmJlYWRfdW5pbmZfZXZlbnRzIDwtIG1lcmdlKHNpZ19ldmVudHMsIGFubm90LAogICAgICAgICAgICAgICAgICAgICAgICAgICBieS54ID0gImdlbmVfbmFtZSIsIGJ5LnkgPSAicm93Lm5hbWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsLnggPSBUUlVFKQp3cml0ZV94bHN4KGV4Y2VsID0gZ2x1ZSgiZXhjZWwve2NvbXBhcmlzb25fcHJlZml4fV90ZXN0aW5nX3N1cHBhX3NpZ2V2ZW50cy54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBiZWFkX3VuaW5mX2V2ZW50cykKYGBgCgojIyBUYWtlIGEgbW9tZW50IHRvIGV4YW1pbmUgdGhlc2UgZXZlbnRzCgpgYGB7cn0KaW5mX3VuaW5mX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoaW5mX3VuaW5mX2V2ZW50c1tbImdlbmVfbmFtZSJdXSkKZW5yaWNocGxvdDo6ZG90cGxvdChpbmZfdW5pbmZfZ3AkR09fZW5yaWNoKQpwcChmaWxlID0gImltYWdlcy9pbmZfdW5pbmZfYnAucG5nIiwgaGVpZ2h0PTIwLCB3aWR0aD0xMikKaW5mX3VuaW5mX2dwJHB2YWx1ZV9wbG90cyRCUApkZXYub2ZmKCkKCmJlYWRfdW5pbmZfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihiZWFkX3VuaW5mX2V2ZW50c1tbImdlbmVfbmFtZSJdXSkKZW5yaWNocGxvdDo6ZG90cGxvdChiZWFkX3VuaW5mX2dwJEdPX2VucmljaCkKYGBgCgojIyBDb25zaWRlciA0IGhyIHZzIHVuaW5mZWN0ZWQKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQptb2R1bGUgYWRkIGN5b2EKbW9kdWxlIGFkZCBzdXBwYQpjeW9hIC0tbWV0aG9kIHN1cHBhIC0tc3BlY2llcyBoZzM4XzExMSAtLWlucHV0IHNhbXBsZV9zaGVldHMvc3VwcGFfc2FtcGxlc191bmluZl9hbGw0aHIueGxzeCBcCiAgICAgLS1maWxlX2NvbHVtbiBoZzM4XzExMV9zYWxtb24gLS1jb25kaXRpb25fY29sdW1uIGluZmVjdF9zdGF0ZSBcCiAgICAgLS1udW1lcmF0b3IgaW5mIC0tZGVub21pbmF0b3IgdW5pbmYKYGBgCgpgYGB7cn0KbnVtZXJhdG9yIDwtICJ0NGgiCmRlbm9taW5hdG9yIDwtICJubyIKY29tcGFyaXNvbl9wcmVmaXggPC0gZ2x1ZSgie251bWVyYXRvcn1fe2Rlbm9taW5hdG9yfSIpCnVuaW5mXzRoX3Bsb3QgPC0gcGxvdF9zdXBwYShmaWxlX3ByZWZpeCA9ICJvdXRwdXRzLzkwc3VwcGFfaGczOF8xMTFfaW5mZWN0X3N0YXRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtZXJhdG9yID0gbnVtZXJhdG9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZW5vbWluYXRvciA9IGRlbm9taW5hdG9yLCB0eXBlID0gInR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdCA9IGhnMzhfMTExX2Fubm90JGdlbmVfYW5ub3RhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RfY29sdW1uID0gImhnbmNfc3ltYm9sIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjUpCnVuaW5mXzRoX3Bsb3QkbWEKCnNpZ19ldmVudHMgPC0gdW5pbmZfNGhfcGxvdFtbInNpZyJdXQojIyBJIHRoaW5rIHRoZSBmb2xsb3dpbmcgc2hvdWxkIG5vdCBiZSBuZWVkZWQgbmV4dCB0aW1lIEkgcnVuIHRoaXMKIyMgKGUuZy4gSSB0aGluayBJIGNoYW5nZWQgdGhlIGZ1bmN0aW9uIHRvIHRha2UgdGhpcyBpbnRvIGFjY291bnQuCnJvd25hbWVzKHNpZ19ldmVudHMpIDwtIHNpZ19ldmVudHNbWyJSb3cubmFtZXMiXV0Kc2lnX2V2ZW50c1tbIlJvdy5uYW1lcyJdXSA8LSBOVUxMCnQ0aF91bmluZl9ldmVudHMgPC0gbWVyZ2Uoc2lnX2V2ZW50cywgYW5ub3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5LnggPSAiZ2VuZV9uYW1lIiwgYnkueSA9ICJyb3cubmFtZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBhbGwueCA9IFRSVUUpCndyaXRlX3hsc3goZXhjZWwgPSBnbHVlKCJleGNlbC97Y29tcGFyaXNvbl9wcmVmaXh9X3Rlc3Rpbmdfc3VwcGFfc2lnZXZlbnRzLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHQ0aF91bmluZl9ldmVudHMpCmBgYAoKCmBgYHtyfQp0NGhfdW5pbmZfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcih0NGhfdW5pbmZfZXZlbnRzW1siZ2VuZV9uYW1lIl1dKQplbnJpY2hwbG90Ojpkb3RwbG90KHQ0aF91bmluZl9ncCRHT19lbnJpY2gpCnBwKGZpbGUgPSAiaW1hZ2VzL2luZl91bmluZl9icC5wbmciLCBoZWlnaHQ9MjAsIHdpZHRoPTEyKQp0NGhfdW5pbmZfZ3AkcHZhbHVlX3Bsb3RzJEJQCmRldi5vZmYoKQoKYmVhZF91bmluZl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGJlYWRfdW5pbmZfZXZlbnRzW1siZ2VuZV9uYW1lIl1dKQplbnJpY2hwbG90Ojpkb3RwbG90KGJlYWRfdW5pbmZfZ3AkR09fZW5yaWNoKQpgYGAK