1 TODO

  1. Compare these samples to previous in-vitro L.major infected macrophages.
  2. Look at shared/unique genes with respect to antimonial treatment.
  3. Send along rpkm counts/tables.
  4. Perform enrichment analyses of high/low genes vs. DE genes.
  5. Compare to MSigDB and/or GSVA

2 Introduction

3 Annotation

We take the annotation data from ensembl’s biomart instance. The genome which was used to map the data was hg38 revision 91. My default when using biomart is to load the data from 1 year before the current date, which provides annotations which match hg38 91 almost perfectly.

hs_annot <- load_biomart_annotations(year="2020", month="jan")
## The biomart annotations file already exists, loading from it.
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")]

4 Sample Estimation

I used two mapping methods for this data, hisat2 and salmon. Most analyses use hisat2, which is a more traditional map-and-count method. In contrast, salmon uses what may be thought of as a indexed voting method (so that multi-matches are discounted and the votes split among all matches). Salmon also required a pre-existing database of known transcripts (though later versions may actually use mapping from things like hisat), while hisat uses the genome and a database of known transcripts (and optionally can search for splicing junctions to find new transcripts).

4.1 Generate expressionsets

The first thing to note is the large range in coverage. There are multiple samples with coverage which is too low to use. These will be removed shortly.

sanitize_columns <- c("donor", "drug", "condition", "batch", "macrophagetreatment",
                      "macrophageinfectionzymodeme")
macr <- create_expt("sample_sheets/tmrc2_macrophage_samples_202203.xlsx",
                    file_column = "hg38100hisatfile",
                    savefile = "tmrc2_macrophage.rda",
                    gene_info = hs_annot) %>%
  exclude_genes_expt(column = "gene_biotype", method = "keep",
                     pattern = "protein_coding") %>%
  subset_expt(nonzero = 11000) %>%
  set_expt_factors(columns = sanitize_columns) %>%
  set_expt_factors(columns=sanitize_columns, class="factor") %>%
  set_expt_batches(fact="macrophagetreatment") %>%
  set_expt_conditions(fact="macrophageinfectionzymodeme")
## Reading the sample metadata.
## The sample definitions comprises: 28 rows(samples) and 67 columns(metadata fields).
## Matched 21447 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## The final expressionset has 21481 rows and 28 columns.
## Before removal, there were 21481 genes, now there are 19923.
## The samples (and read coverage) removed when filtering 11000 non-zero genes are:
## named numeric(0)
## subset_expt(): There were 28, now there are 28 samples.

5 Macrophages

These samples are rather different from all of the others. The following section is therefore written primarily in response to a separate set of emails from Olga and Maria Adelaida; here is a snippet:

Dear all, about the samples corresponding to infected macrophages with three sensitive (2.2) and three resistant (2.3) clinical strains of L. (V.) panamensis, I send you the results of parasite burden by detection of 7SLRNA. I think these results are interesting, but the sample size is very small. Doctor Najib or Trey could you please send me the quality data and PCA analysis of these samples?

and

Hi Doctor, thank you. These samples corresponding to primary macrophages infected with clinical strains 2.2 (n=3) and 2.3 (n = 3). These information is in the file: TMRC project 3: excel Host TMRC3 v1.1, rows 137 to 150.

Thus I added 3 columns to the end of the sample sheet which seek to include this information. The first is ‘drug’ and encodes both the infection state (no for the two controls and yes for everything else), the second is zymodeme which I took from the tmrc2 sample sheet, the last is drug, which is either no or sb.

table(pData(macr)[["condition"]])
## 
## none z2.2 z2.3 
##    4   12   12
table(pData(macr)[["batch"]])
## 
##      inf   inf_sb    uninf uninf_sb 
##       12       12        2        2
table(pData(macr)[["macrophagetreatment"]])
## 
##      inf   inf_sb    uninf uninf_sb 
##       12       12        2        2
table(pData(macr)[["macrophageinfectionzymodeme"]])
## 
## none z2.2 z2.3 
##    4   12   12
macr_libsize <- plot_libsize(macr, yscale=TRUE)
dev <- pp(file="macrophage_side_experiment/macr_libsize.png")
macr_libsize$plot
closed <- dev.off()
macr_libsize$plot

macr_nonzero <- plot_nonzero(macr)
dev <- pp(file="macrophage_side_experiment/macr_nonzero.png")
macr_nonzero$plot
closed <- dev.off()
macr_nonzero$plot

macr_norm <- sm(normalize_expt(macr, transform="log2", norm="quant", convert="cpm", filter=TRUE))
norm_pca <- plot_pca(macr_norm, plot_labels=FALSE)
norm_pca$plot

dev <- pp(file="macrophage_side_experiment/pca_colors_zymodeme.png")
norm_pca$plot
closed <- dev.off()
norm_pca$plot

treatment_macr <- set_expt_conditions(macr, fact="macrophagetreatment") %>%
  set_expt_batches(fact="macrophageinfectionzymodeme")
treatment_norm <- sm(normalize_expt(treatment_macr, transform="log2", norm="quant", convert="cpm", filter=TRUE))
treatment_pca <- plot_pca(treatment_norm, plot_labels=FALSE)
treatment_pca$plot

dev <- pp(file="macrophage_side_experiment/pca_colors_treatment.png")
treatment_pca$plot
closed <- dev.off()
treatment_pca$plot

plot_3d_pca(norm_pca)$plot
macr_nb <- sm(normalize_expt(macr, norm = "quant", convert = "cpm",
                             transform = "log2", batch = "svaseq", filter = TRUE))
nb_pca <- plot_pca(macr_nb, plot_labels=FALSE)
dev <- pp(file="macrophage_side_experiment/normbatch_pca.png")
nb_pca$plot
closed <- dev.off()
nb_pca$plot

5.1 Write the data

macr_written <- sm(write_expt(macr, excel="macrophage_side_experiment/macrophage_expt.xlsx"))
## Error in checkModelStatus(fit, showWarnings = showWarnings, colinearityCutoff = colinearityCutoff,  : 
##   The variables specified in this model are redundant,
## so the design matrix is not full rank
## Error in checkModelStatus(fit, showWarnings = showWarnings, colinearityCutoff = colinearityCutoff,  : 
##   The variables specified in this model are redundant,
## so the design matrix is not full rank

5.2 Perform DE

There were a couple of contrasts explicitly requested for this data:

  • Macrophages infected with 2.3 without SbV vs macrophagues infected with 2.2 without SbV
  • Macrophages infected with 2.3 without SbV vs macrophages uninfected (M0)

Unfortunately, I think to really answer these questions we will require more replicates of a few of these conditions, most notably the uninfected samples.

treatment_macr <- set_expt_conditions(macr, fact="macrophagetreatment") %>%
  set_expt_batches(fact="macrophageinfectionzymodeme")
##tmp <- normalize_expt(macr, filter=TRUE)
##zy_de <- deseq_pairwise(tmp, model_batch="svaseq")
##zy_ed <- edger_pairwise(tmp, model_batch="svaseq")
combined_condition <- paste0(pData(macr)[["macrophagetreatment"]], "_",
                             pData(macr)[["macrophageinfectionzymodeme"]])
pData(macr[["expressionset"]])[["combined"]] <- combined_condition
macr <- set_expt_conditions(macr, fact = "combined")
zymo_de <- all_pairwise(macr, model_batch = "svaseq", filter = TRUE,
                        do_ebseq = FALSE)
## Removing 0 low-count genes (11425 remaining).
## Setting 801 low elements to zero.
## transform_counts: Found 801 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
keepers <- list(
    "z22_uninf" = c("infz22", "uninfnone"),
    "z23_uninf" = c("infz23", "uninfnone"),
    "z22_sbuninf" = c("infsbz22", "uninfsbnone"),
    "z23_sbuninf" = c("infsbz23", "uninfsbnone"),
    "zymo_nodrug" = c("infz23", "infz22"),
    "zymo_sb" = c("infsbz23", "infsbz22"))

zymo_table <- combine_de_tables(
    zymo_de, keepers=keepers,
    excel=glue::glue("excel/macrophage_de-v{ver}.xlsx"))

dev <- pp(file="images/z22_vs_uninfected_ma.png")
zymo_table$plots$z22_uninf$deseq_ma_plots$plot
closed <- dev.off()
zymo_table$plots$z22_uninf$deseq_ma_plots$plot
dev <- pp(file="images/z22_vs_sb_uninfected_ma.png")
zymo_table$plots$z22_sbuninf$deseq_ma_plots$plot
closed <- dev.off()
zymo_table$plots$z22_sbuninf$deseq_ma_plots$plot
dev <- pp(file="images/z23_vs_uninfected_ma.png")
zymo_table$plots$z23_uninf$deseq_ma_plots$plot
closed <- dev.off()
zymo_table$plots$z23_uninf$deseq_ma_plots$plot
dev <- pp(file="images/z23_vs_sb_uninfected_ma.png")
zymo_table$plots$z23_sbuninf$deseq_ma_plots$plot
closed <- dev.off()
zymo_table$plots$z23_sbuninf$deseq_ma_plots$plot
zymo_sig <- extract_significant_genes(zymo_table, according_to="deseq")

z22_ma <- plot_ma_de(zymo_table[["data"]][["z22_uninf"]], expr_col="deseq_basemean",
                 fc_col="deseq_logfc", p_col="deseq_adjp")
z22_ma$plot
z22_uninf_up_sig <- zymo_sig[["deseq"]][["ups"]][["z22_uninf"]]
dim(z22_uninf_up_sig)
## [1] 436  47
z22_uninf_down_sig <- zymo_sig[["deseq"]][["downs"]][["z22_uninf"]]
dim(z22_uninf_down_sig)
## [1]  6 47
z22_sbuninf_up_sig <- zymo_sig[["deseq"]][["ups"]][["z22_sbuninf"]]
dim(z22_sbuninf_up_sig)
## [1] 20 47
z22_sbuninf_down_sig <- zymo_sig[["deseq"]][["downs"]][["z22_sbuninf"]]
dim(z22_sbuninf_down_sig)
## [1]  0 47
z23_ma <- plot_ma_de(zymo_table[["data"]][["z23_uninf"]], expr_col="deseq_basemean",
                     fc_col="deseq_logfc", p_col="deseq_adjp")
z23_ma$plot
z23_uninf_up_sig <- zymo_sig[["deseq"]][["ups"]][["z23_uninf"]]
dim(z23_uninf_up_sig)
## [1] 643  47
z23_uninf_down_sig <- zymo_sig[["deseq"]][["downs"]][["z23_uninf"]]
dim(z23_uninf_down_sig)
## [1] 372  47
z23_sbuninf_up_sig <- zymo_sig[["deseq"]][["ups"]][["z23_sbuninf"]]
dim(z23_sbuninf_up_sig)
## [1] 530  47
z23_sbuninf_down_sig <- zymo_sig[["deseq"]][["downs"]][["z23_sbuninf"]]
dim(z23_sbuninf_down_sig)
## [1] 323  47

5.3 Compare groups of genes

z22_z23_nosb_groups <- list(
    "z22_up" = rownames(z22_uninf_up_sig),
    "z23_up" = rownames(z23_uninf_up_sig))
z22_z23_nosb_venn <- Vennerable::Venn(Sets = z22_z23_nosb_groups)
dev <- pp(file="images/z22_z23_nosb_venn.png")
z22_z23_nosb_venn_plot <- Vennerable::plot(z22_z23_nosb_venn, doWeights = FALSE)
closed <- dev.off()
Vennerable::plot(z22_z23_nosb_venn, doWeights = FALSE)

annot <- fData(macr)
z23_nosb_unique <- z22_z23_nosb_venn@IntersectionSets[["01"]]
wanted <- rownames(annot) %in% z23_nosb_unique
z23_wanted <- annot[wanted, ]
written <- write_xlsx(z23_wanted, excel="excel/z23_nosb_unique_genes.xlsx")

z22_nosb_unique <- z22_z23_nosb_venn@IntersectionSets[["10"]]
wanted <- rownames(annot) %in% z22_nosb_unique
z22_wanted <- annot[wanted, ]
written <- write_xlsx(z22_wanted, excel="excel/z22_nosb_unique_genes.xlsx")

z22_nosb_shared <- z22_z23_nosb_venn@IntersectionSets[["11"]]
wanted <- rownames(annot) %in% z22_nosb_shared
shared_wanted <- annot[wanted, ]
written <- write_xlsx(shared_wanted, excel="excel/z22_z23_nosb_shared_genes.xlsx")

z22_unique_gp <- simple_gprofiler(rownames(z22_wanted))
## Performing gProfiler GO search of 333 genes against hsapiens.
## GO search found 74 hits.
## Performing gProfiler KEGG search of 333 genes against hsapiens.
## KEGG search found 3 hits.
## Performing gProfiler REAC search of 333 genes against hsapiens.
## REAC search found 13 hits.
## Performing gProfiler MI search of 333 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 333 genes against hsapiens.
## TF search found 43 hits.
## Performing gProfiler CORUM search of 333 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 333 genes against hsapiens.
## HP search found 0 hits.
dev <- pp(file="images/z22_unique_bp.png", height=9, width=6)
z22_unique_gp[["pvalue_plots"]][["bpp_plot_over"]]
closed <- dev.off()
z22_unique_gp[["pvalue_plots"]][["bpp_plot_over"]]

dev <- pp(file="images/z22_unique_kegg.png")
z22_unique_gp[["pvalue_plots"]][["kegg_plot_over"]]
closed <- dev.off()
z22_unique_gp[["pvalue_plots"]][["kegg_plot_over"]]

dev <- pp(file="images/z22_unique_reac.png")
z22_unique_gp[["pvalue_plots"]][["reactome_plot_over"]]
closed <- dev.off()
z22_unique_gp[["pvalue_plots"]][["reactome_plot_over"]]

z23_unique_gp <- simple_gprofiler(rownames(z23_wanted))
## Performing gProfiler GO search of 540 genes against hsapiens.
## GO search found 459 hits.
## Performing gProfiler KEGG search of 540 genes against hsapiens.
## KEGG search found 16 hits.
## Performing gProfiler REAC search of 540 genes against hsapiens.
## REAC search found 27 hits.
## Performing gProfiler MI search of 540 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 540 genes against hsapiens.
## TF search found 85 hits.
## Performing gProfiler CORUM search of 540 genes against hsapiens.
## CORUM search found 2 hits.
## Performing gProfiler HP search of 540 genes against hsapiens.
## HP search found 0 hits.
dev <- pp(file="images/z23_unique_bp.png", height=9, width=6)
z23_unique_gp[["pvalue_plots"]][["bpp_plot_over"]]
closed <- dev.off()
z23_unique_gp[["pvalue_plots"]][["bpp_plot_over"]]

dev <- pp(file="images/z23_unique_kegg.png")
z23_unique_gp[["pvalue_plots"]][["kegg_plot_over"]]
closed <- dev.off()
z23_unique_gp[["pvalue_plots"]][["kegg_plot_over"]]

dev <- pp(file="images/z23_unique_reac.png")
z23_unique_gp[["pvalue_plots"]][["reactome_plot_over"]]
closed <- dev.off()
z23_unique_gp[["pvalue_plots"]][["reactome_plot_over"]]

dev <- pp(file="images/z23_unique_tf.png")
z23_unique_gp[["pvalue_plots"]][["tf_plot_over"]]
closed <- dev.off()
z23_unique_gp[["pvalue_plots"]][["tf_plot_over"]]

z22_z23_shared_gp <- simple_gprofiler(rownames(shared_wanted))
## Performing gProfiler GO search of 103 genes against hsapiens.
## GO search found 92 hits.
## Performing gProfiler KEGG search of 103 genes against hsapiens.
## KEGG search found 15 hits.
## Performing gProfiler REAC search of 103 genes against hsapiens.
## REAC search found 6 hits.
## Performing gProfiler MI search of 103 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 103 genes against hsapiens.
## TF search found 14 hits.
## Performing gProfiler CORUM search of 103 genes against hsapiens.
## CORUM search found 4 hits.
## Performing gProfiler HP search of 103 genes against hsapiens.
## HP search found 0 hits.
dev <- pp(file="images/z23_shared_bp.png", height=9, width=6)
z22_z23_shared_gp[["pvalue_plots"]][["bpp_plot_over"]]
closed <- dev.off()
z22_z23_shared_gp[["pvalue_plots"]][["bpp_plot_over"]]

dev <- pp(file="images/z23_shared_kegg.png")
z22_z23_shared_gp[["pvalue_plots"]][["kegg_plot_over"]]
closed <- dev.off()
z22_z23_shared_gp[["pvalue_plots"]][["kegg_plot_over"]]

dev <- pp(file="images/z23_shared_reac.png")
z22_z23_shared_gp[["pvalue_plots"]][["reactome_plot_over"]]
closed <- dev.off()
z22_z23_shared_gp[["pvalue_plots"]][["reactome_plot_over"]]

dev <- pp(file="images/z23_shared_tf.png")
z22_z23_shared_gp[["pvalue_plots"]][["tf_plot_over"]]
closed <- dev.off()
z22_z23_shared_gp[["pvalue_plots"]][["tf_plot_over"]]

z22_uninf_up_gp <- simple_gprofiler(z22_uninf_up_sig)
## Performing gProfiler GO search of 436 genes against hsapiens.
## GO search found 146 hits.
## Performing gProfiler KEGG search of 436 genes against hsapiens.
## KEGG search found 8 hits.
## Performing gProfiler REAC search of 436 genes against hsapiens.
## REAC search found 18 hits.
## Performing gProfiler MI search of 436 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 436 genes against hsapiens.
## TF search found 63 hits.
## Performing gProfiler CORUM search of 436 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 436 genes against hsapiens.
## HP search found 3 hits.
dev <- pp(file="images/z22_uninf_up_gp_bp.png", height=20, width=10)
z22_uninf_up_gp$pvalue_plots$bpp_plot_over
closed <- dev.off()
z22_uninf_up_gp$pvalue_plots$bpp_plot_over

z22_uninf_down_gp <- simple_gprofiler(z22_uninf_down_sig)
## Performing gProfiler GO search of 6 genes against hsapiens.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 6 genes against hsapiens.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 6 genes against hsapiens.
## REAC search found 0 hits.
## Performing gProfiler MI search of 6 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 6 genes against hsapiens.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 6 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 6 genes against hsapiens.
## HP search found 0 hits.
z22_sbuninf_up_gp <- simple_gprofiler(z22_sbuninf_up_sig)
## Performing gProfiler GO search of 20 genes against hsapiens.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 20 genes against hsapiens.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 20 genes against hsapiens.
## REAC search found 0 hits.
## Performing gProfiler MI search of 20 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 20 genes against hsapiens.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 20 genes against hsapiens.
## CORUM search found 4 hits.
## Performing gProfiler HP search of 20 genes against hsapiens.
## HP search found 0 hits.
z22_sbuninf_down_gp <- simple_gprofiler(z22_sbuninf_down_sig)
## Performing gProfiler GO search of 0 genes against hsapiens.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 0 genes against hsapiens.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 0 genes against hsapiens.
## REAC search found 0 hits.
## Performing gProfiler MI search of 0 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 0 genes against hsapiens.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 0 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 0 genes against hsapiens.
## HP search found 0 hits.
z23_uninf_up_gp <- simple_gprofiler(z23_uninf_up_sig)
## Performing gProfiler GO search of 643 genes against hsapiens.
## GO search found 498 hits.
## Performing gProfiler KEGG search of 643 genes against hsapiens.
## KEGG search found 27 hits.
## Performing gProfiler REAC search of 643 genes against hsapiens.
## REAC search found 46 hits.
## Performing gProfiler MI search of 643 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 643 genes against hsapiens.
## TF search found 102 hits.
## Performing gProfiler CORUM search of 643 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 643 genes against hsapiens.
## HP search found 7 hits.
dev <- pp(file="images/z23_uninf_up_gp_bp.png", height=20, width=10)
z23_uninf_up_gp$pvalue_plots$bpp_plot_over
closed <- dev.off()
z23_uninf_up_gp$pvalue_plots$bpp_plot_over

6 Parasite reads

sanitize_columns <- c("donor", "drug", "condition", "batch", "macrophagetreatment",
                      "macrophageinfectionzymodeme")
library(org.Lpanamensis.MHOMCOL81L13.v46.eg.db)
## Loading required package: AnnotationDbi
## 
pan_db <- org.Lpanamensis.MHOMCOL81L13.v46.eg.db
all_lp_annot <- sm(load_orgdb_annotations(
    pan_db,
    keytype = "gid",
    fields = c("annot_gene_entrez_id", "annot_gene_name",
               "annot_strand", "annot_chromosome", "annot_cds_length",
               "annot_gene_product")))$genes
macr_lp <- create_expt(metadata="sample_sheets/tmrc2_macrophage_samples_202203.xlsx",
                       gene_info=all_lp_annot, file_column = "lpanamensisv36hisatfile")
## Reading the sample metadata.
## The sample definitions comprises: 28 rows(samples) and 67 columns(metadata fields).
## Warning in file(file, "rt"): cannot open file '/mnt/cbcb/fs01_abelew/
## cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019/
## preprocessing/TMRC30051/outputs/hisat2_lpanamensis_v36/
## r1_trimmed.count_lpanamensis_v36_sno_gene_ID.count.xz': No such file or
## directory
## Error in file(file, "rt"): cannot open the connection
  exclude_genes_expt(column = "gene_biotype", method = "keep",
                     pattern = "protein_coding") %>%
  subset_expt(subset="typeofcells=='Macrophages'") %>%
  subset_expt(nonzero = 11000) %>%
  set_expt_factors(columns = sanitize_columns) %>%
  set_expt_factors(columns=sanitize_columns, class="factor") %>%
  set_expt_batches(fact="macrophagetreatment") %>%
  set_expt_conditions(fact="macrophageinfectionzymodeme")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': error in evaluating the argument 'object' in selecting a method for function 'pData': error in evaluating the argument 'object' in selecting a method for function 'fData': error in evaluating the argument 'object' in selecting a method for function 'fData': error in evaluating the argument 'object' in selecting a method for function 'sampleNames': error in evaluating the argument 'object' in selecting a method for function 'sampleNames': argument "expt" is missing, with no default
if (!isTRUE(get0("skip_load"))) {
  pander::pander(sessionInfo())
  message(paste0("This is hpgltools commit: ", get_git_commit()))
  message(paste0("Saving to ", savefile))
  tmp <- sm(saveme(filename=savefile))
}
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 64dc311322615b4a8bfef4517ab3c4ba0d0b0e59
## This is hpgltools commit: Mon Apr 4 16:43:54 2022 -0400: 64dc311322615b4a8bfef4517ab3c4ba0d0b0e59
## Saving to tmrc2_macrophage_202203.rda.xz
tmp <- loadme(filename=savefile)
LS0tCnRpdGxlOiAiVE1SQzIgSW5mZWN0aW5nIG1hY3JvcGhhZ2VzOiAyMDIyMDMiCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICBjb2xsYXBzZWQ6IGZhbHNlCiAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4OwogIH0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoaHBnbHRvb2xzKQp0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIi9kYXRhL2hwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgd2lkdGg9OTAsCiAgICAgICAgICAgICAgICAgICAgIGVjaG89VFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGg9OCwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQ9OCwKICAgICAgICAgICAgICAgICAgICAgIGRwaT05NikKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHM9NCwKICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbD0iYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplPTEyKSkKdmVyIDwtICIyMDIyMDMiCnByZXZpb3VzX2ZpbGUgPC0gcGFzdGUwKCJub25lIiwgdmVyLCAiLlJtZCIpCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdD0iJVklbSVkIikKdG1wIDwtIHRyeShzbShsb2FkbWUoZmlsZW5hbWU9Z3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSJcXC5yZGFcXC54eiIsIHg9cHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gInRtcmMyX21hY3JvcGhhZ2VfMjAyMjAzLlJtZCIKc2F2ZWZpbGUgPC0gZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSJcXC5yZGFcXC54eiIsIHg9cm1kX2ZpbGUpCmBgYAoKIyBUT0RPCgoxLiAgQ29tcGFyZSB0aGVzZSBzYW1wbGVzIHRvIHByZXZpb3VzIGluLXZpdHJvIEwubWFqb3IgaW5mZWN0ZWQgbWFjcm9waGFnZXMuCjIuICBMb29rIGF0IHNoYXJlZC91bmlxdWUgZ2VuZXMgd2l0aCByZXNwZWN0IHRvIGFudGltb25pYWwgdHJlYXRtZW50LgozLiAgU2VuZCBhbG9uZyBycGttIGNvdW50cy90YWJsZXMuCjQuICBQZXJmb3JtIGVucmljaG1lbnQgYW5hbHlzZXMgb2YgaGlnaC9sb3cgZ2VuZXMgdnMuIERFIGdlbmVzLgo1LiAgQ29tcGFyZSB0byBNU2lnREIgYW5kL29yIEdTVkEKCiMgSW50cm9kdWN0aW9uCgojIEFubm90YXRpb24KCldlIHRha2UgdGhlIGFubm90YXRpb24gZGF0YSBmcm9tIGVuc2VtYmwncyBiaW9tYXJ0IGluc3RhbmNlLiAgVGhlIGdlbm9tZSB3aGljaAp3YXMgdXNlZCB0byBtYXAgdGhlIGRhdGEgd2FzIGhnMzggcmV2aXNpb24gOTEuICBNeSBkZWZhdWx0IHdoZW4gdXNpbmcgYmlvbWFydCBpcwp0byBsb2FkIHRoZSBkYXRhIGZyb20gMSB5ZWFyIGJlZm9yZSB0aGUgY3VycmVudCBkYXRlLCB3aGljaCBwcm92aWRlcyBhbm5vdGF0aW9ucwp3aGljaCBtYXRjaCBoZzM4IDkxIGFsbW9zdCBwZXJmZWN0bHkuCgpgYGB7ciBoc19hbm5vdH0KaHNfYW5ub3QgPC0gbG9hZF9iaW9tYXJ0X2Fubm90YXRpb25zKHllYXI9IjIwMjAiLCBtb250aD0iamFuIikKaHNfYW5ub3QgPC0gaHNfYW5ub3RbWyJhbm5vdGF0aW9uIl1dCmhzX2Fubm90W1sidHJhbnNjcmlwdCJdXSA8LSBwYXN0ZTAocm93bmFtZXMoaHNfYW5ub3QpLCAiLiIsIGhzX2Fubm90W1sidmVyc2lvbiJdXSkKcm93bmFtZXMoaHNfYW5ub3QpIDwtIG1ha2UubmFtZXMoaHNfYW5ub3RbWyJlbnNlbWJsX2dlbmVfaWQiXV0sIHVuaXF1ZT1UUlVFKQp0eF9nZW5lX21hcCA8LSBoc19hbm5vdFssIGMoInRyYW5zY3JpcHQiLCAiZW5zZW1ibF9nZW5lX2lkIildCmBgYAoKIyBTYW1wbGUgRXN0aW1hdGlvbgoKSSB1c2VkIHR3byBtYXBwaW5nIG1ldGhvZHMgZm9yIHRoaXMgZGF0YSwgaGlzYXQyIGFuZCBzYWxtb24uICBNb3N0IGFuYWx5c2VzIHVzZQpoaXNhdDIsIHdoaWNoIGlzIGEgbW9yZSB0cmFkaXRpb25hbCBtYXAtYW5kLWNvdW50IG1ldGhvZC4gIEluIGNvbnRyYXN0LCBzYWxtb24KdXNlcyB3aGF0IG1heSBiZSB0aG91Z2h0IG9mIGFzIGEgaW5kZXhlZCB2b3RpbmcgbWV0aG9kIChzbyB0aGF0IG11bHRpLW1hdGNoZXMgYXJlCmRpc2NvdW50ZWQgYW5kIHRoZSB2b3RlcyBzcGxpdCBhbW9uZyBhbGwgbWF0Y2hlcykuICBTYWxtb24gYWxzbyByZXF1aXJlZCBhCnByZS1leGlzdGluZyBkYXRhYmFzZSBvZiBrbm93biB0cmFuc2NyaXB0cyAodGhvdWdoIGxhdGVyIHZlcnNpb25zIG1heSBhY3R1YWxseQp1c2UgbWFwcGluZyBmcm9tIHRoaW5ncyBsaWtlIGhpc2F0KSwgd2hpbGUgaGlzYXQgdXNlcyB0aGUgZ2Vub21lIGFuZCBhIGRhdGFiYXNlCm9mIGtub3duIHRyYW5zY3JpcHRzIChhbmQgb3B0aW9uYWxseSBjYW4gc2VhcmNoIGZvciBzcGxpY2luZyBqdW5jdGlvbnMgdG8gZmluZApuZXcgdHJhbnNjcmlwdHMpLgoKIyMgR2VuZXJhdGUgZXhwcmVzc2lvbnNldHMKClRoZSBmaXJzdCB0aGluZyB0byBub3RlIGlzIHRoZSBsYXJnZSByYW5nZSBpbiBjb3ZlcmFnZS4gIFRoZXJlIGFyZSBtdWx0aXBsZQpzYW1wbGVzIHdpdGggY292ZXJhZ2Ugd2hpY2ggaXMgdG9vIGxvdyB0byB1c2UuICBUaGVzZSB3aWxsIGJlIHJlbW92ZWQgc2hvcnRseS4KCmBgYHtyIGFsbF9uZXdfaGlzYXQyfQpzYW5pdGl6ZV9jb2x1bW5zIDwtIGMoImRvbm9yIiwgImRydWciLCAiY29uZGl0aW9uIiwgImJhdGNoIiwgIm1hY3JvcGhhZ2V0cmVhdG1lbnQiLAogICAgICAgICAgICAgICAgICAgICAgIm1hY3JvcGhhZ2VpbmZlY3Rpb256eW1vZGVtZSIpCm1hY3IgPC0gY3JlYXRlX2V4cHQoInNhbXBsZV9zaGVldHMvdG1yYzJfbWFjcm9waGFnZV9zYW1wbGVzXzIwMjIwMy54bHN4IiwKICAgICAgICAgICAgICAgICAgICBmaWxlX2NvbHVtbiA9ICJoZzM4MTAwaGlzYXRmaWxlIiwKICAgICAgICAgICAgICAgICAgICBzYXZlZmlsZSA9ICJ0bXJjMl9tYWNyb3BoYWdlLnJkYSIsCiAgICAgICAgICAgICAgICAgICAgZ2VuZV9pbmZvID0gaHNfYW5ub3QpICU+JQogIGV4Y2x1ZGVfZ2VuZXNfZXhwdChjb2x1bW4gPSAiZ2VuZV9iaW90eXBlIiwgbWV0aG9kID0gImtlZXAiLAogICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gInByb3RlaW5fY29kaW5nIikgJT4lCiAgc3Vic2V0X2V4cHQobm9uemVybyA9IDExMDAwKSAlPiUKICBzZXRfZXhwdF9mYWN0b3JzKGNvbHVtbnMgPSBzYW5pdGl6ZV9jb2x1bW5zKSAlPiUKICBzZXRfZXhwdF9mYWN0b3JzKGNvbHVtbnM9c2FuaXRpemVfY29sdW1ucywgY2xhc3M9ImZhY3RvciIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0ibWFjcm9waGFnZXRyZWF0bWVudCIpICU+JQogIHNldF9leHB0X2NvbmRpdGlvbnMoZmFjdD0ibWFjcm9waGFnZWluZmVjdGlvbnp5bW9kZW1lIikKYGBgCgojIE1hY3JvcGhhZ2VzCgpUaGVzZSBzYW1wbGVzIGFyZSByYXRoZXIgZGlmZmVyZW50IGZyb20gYWxsIG9mIHRoZSBvdGhlcnMuICBUaGUgZm9sbG93aW5nCnNlY3Rpb24gaXMgdGhlcmVmb3JlIHdyaXR0ZW4gcHJpbWFyaWx5IGluIHJlc3BvbnNlIHRvIGEgc2VwYXJhdGUgc2V0IG9mIGVtYWlscwpmcm9tIE9sZ2EgYW5kIE1hcmlhIEFkZWxhaWRhOyBoZXJlIGlzIGEgc25pcHBldDoKCiBEZWFyIGFsbCwgYWJvdXQgdGhlIHNhbXBsZXMgY29ycmVzcG9uZGluZyB0byBpbmZlY3RlZCBtYWNyb3BoYWdlcyB3aXRoIHRocmVlCiBzZW5zaXRpdmUgKDIuMikgYW5kIHRocmVlIHJlc2lzdGFudCAoMi4zKSBjbGluaWNhbCBzdHJhaW5zIG9mIEwuIChWLikKIHBhbmFtZW5zaXMsIEkgc2VuZCB5b3UgdGhlIHJlc3VsdHMgb2YgcGFyYXNpdGUgYnVyZGVuIGJ5IGRldGVjdGlvbiBvZiA3U0xSTkEuIEkKIHRoaW5rIHRoZXNlIHJlc3VsdHMgYXJlIGludGVyZXN0aW5nLCBidXQgdGhlIHNhbXBsZSBzaXplIGlzIHZlcnkgc21hbGwuCkRvY3RvciBOYWppYiBvciBUcmV5IGNvdWxkIHlvdSBwbGVhc2Ugc2VuZCBtZSB0aGUgcXVhbGl0eSBkYXRhIGFuZCBQQ0EgYW5hbHlzaXMKIG9mIHRoZXNlIHNhbXBsZXM/CgphbmQKCiBIaSBEb2N0b3IsIHRoYW5rIHlvdS4gIFRoZXNlIHNhbXBsZXMgY29ycmVzcG9uZGluZyB0byBwcmltYXJ5IG1hY3JvcGhhZ2VzCiBpbmZlY3RlZCB3aXRoIGNsaW5pY2FsIHN0cmFpbnMgMi4yIChuPTMpIGFuZCAyLjMgKG4gPSAzKS4gVGhlc2UgaW5mb3JtYXRpb24gaXMKIGluIHRoZSBmaWxlOiBUTVJDIHByb2plY3QgMzogZXhjZWwgSG9zdCBUTVJDMyB2MS4xLCByb3dzIDEzNyB0byAxNTAuCgpUaHVzIEkgYWRkZWQgMyBjb2x1bW5zIHRvIHRoZSBlbmQgb2YgdGhlIHNhbXBsZSBzaGVldCB3aGljaCBzZWVrIHRvCmluY2x1ZGUgdGhpcyBpbmZvcm1hdGlvbi4gIFRoZSBmaXJzdCBpcyAnZHJ1ZycgYW5kIGVuY29kZXMgYm90aCB0aGUgaW5mZWN0aW9uCnN0YXRlIChubyBmb3IgdGhlIHR3byBjb250cm9scyBhbmQgeWVzIGZvciBldmVyeXRoaW5nIGVsc2UpLCB0aGUgc2Vjb25kIGlzCnp5bW9kZW1lIHdoaWNoIEkgdG9vayBmcm9tIHRoZSB0bXJjMiBzYW1wbGUgc2hlZXQsIHRoZSBsYXN0IGlzIGRydWcsIHdoaWNoIGlzCmVpdGhlciBubyBvciBzYi4KCmBgYHtyIG1hY3JvcGhhZ2Vfenltb2RlbWVfZXhwZXJpbWVudH0KdGFibGUocERhdGEobWFjcilbWyJjb25kaXRpb24iXV0pCnRhYmxlKHBEYXRhKG1hY3IpW1siYmF0Y2giXV0pCnRhYmxlKHBEYXRhKG1hY3IpW1sibWFjcm9waGFnZXRyZWF0bWVudCJdXSkKdGFibGUocERhdGEobWFjcilbWyJtYWNyb3BoYWdlaW5mZWN0aW9uenltb2RlbWUiXV0pCm1hY3JfbGlic2l6ZSA8LSBwbG90X2xpYnNpemUobWFjciwgeXNjYWxlPVRSVUUpCmRldiA8LSBwcChmaWxlPSJtYWNyb3BoYWdlX3NpZGVfZXhwZXJpbWVudC9tYWNyX2xpYnNpemUucG5nIikKbWFjcl9saWJzaXplJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQptYWNyX2xpYnNpemUkcGxvdAoKbWFjcl9ub256ZXJvIDwtIHBsb3Rfbm9uemVybyhtYWNyKQpkZXYgPC0gcHAoZmlsZT0ibWFjcm9waGFnZV9zaWRlX2V4cGVyaW1lbnQvbWFjcl9ub256ZXJvLnBuZyIpCm1hY3Jfbm9uemVybyRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbWFjcl9ub256ZXJvJHBsb3QKCm1hY3Jfbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdChtYWNyLCB0cmFuc2Zvcm09ImxvZzIiLCBub3JtPSJxdWFudCIsIGNvbnZlcnQ9ImNwbSIsIGZpbHRlcj1UUlVFKSkKbm9ybV9wY2EgPC0gcGxvdF9wY2EobWFjcl9ub3JtLCBwbG90X2xhYmVscz1GQUxTRSkKbm9ybV9wY2EkcGxvdAoKZGV2IDwtIHBwKGZpbGU9Im1hY3JvcGhhZ2Vfc2lkZV9leHBlcmltZW50L3BjYV9jb2xvcnNfenltb2RlbWUucG5nIikKbm9ybV9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCm5vcm1fcGNhJHBsb3QKCnRyZWF0bWVudF9tYWNyIDwtIHNldF9leHB0X2NvbmRpdGlvbnMobWFjciwgZmFjdD0ibWFjcm9waGFnZXRyZWF0bWVudCIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0ibWFjcm9waGFnZWluZmVjdGlvbnp5bW9kZW1lIikKdHJlYXRtZW50X25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQodHJlYXRtZW50X21hY3IsIHRyYW5zZm9ybT0ibG9nMiIsIG5vcm09InF1YW50IiwgY29udmVydD0iY3BtIiwgZmlsdGVyPVRSVUUpKQp0cmVhdG1lbnRfcGNhIDwtIHBsb3RfcGNhKHRyZWF0bWVudF9ub3JtLCBwbG90X2xhYmVscz1GQUxTRSkKdHJlYXRtZW50X3BjYSRwbG90CmRldiA8LSBwcChmaWxlPSJtYWNyb3BoYWdlX3NpZGVfZXhwZXJpbWVudC9wY2FfY29sb3JzX3RyZWF0bWVudC5wbmciKQp0cmVhdG1lbnRfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQp0cmVhdG1lbnRfcGNhJHBsb3QKCnBsb3RfM2RfcGNhKG5vcm1fcGNhKSRwbG90CgptYWNyX25iIDwtIHNtKG5vcm1hbGl6ZV9leHB0KG1hY3IsIG5vcm0gPSAicXVhbnQiLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCBiYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKSkKbmJfcGNhIDwtIHBsb3RfcGNhKG1hY3JfbmIsIHBsb3RfbGFiZWxzPUZBTFNFKQpkZXYgPC0gcHAoZmlsZT0ibWFjcm9waGFnZV9zaWRlX2V4cGVyaW1lbnQvbm9ybWJhdGNoX3BjYS5wbmciKQpuYl9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCm5iX3BjYSRwbG90CmBgYAoKIyMgV3JpdGUgdGhlIGRhdGEKCmBgYHtyIHdyaXRlLCBmaWcuc2hvdz0iaGlkZSJ9Cm1hY3Jfd3JpdHRlbiA8LSBzbSh3cml0ZV9leHB0KG1hY3IsIGV4Y2VsPSJtYWNyb3BoYWdlX3NpZGVfZXhwZXJpbWVudC9tYWNyb3BoYWdlX2V4cHQueGxzeCIpKQpgYGAKCiMjIFBlcmZvcm0gREUKClRoZXJlIHdlcmUgYSBjb3VwbGUgb2YgY29udHJhc3RzIGV4cGxpY2l0bHkgcmVxdWVzdGVkIGZvciB0aGlzIGRhdGE6CgoqIE1hY3JvcGhhZ2VzIGluZmVjdGVkIHdpdGggMi4zIHdpdGhvdXQgU2JWIHZzIG1hY3JvcGhhZ3VlcyBpbmZlY3RlZCB3aXRoIDIuMiB3aXRob3V0IFNiVgoqIE1hY3JvcGhhZ2VzIGluZmVjdGVkIHdpdGggMi4zIHdpdGhvdXQgU2JWIHZzIG1hY3JvcGhhZ2VzIHVuaW5mZWN0ZWQgKE0wKQoKVW5mb3J0dW5hdGVseSwgSSB0aGluayB0byByZWFsbHkgYW5zd2VyIHRoZXNlIHF1ZXN0aW9ucyB3ZSB3aWxsCnJlcXVpcmUgbW9yZSByZXBsaWNhdGVzIG9mIGEgZmV3IG9mIHRoZXNlIGNvbmRpdGlvbnMsIG1vc3Qgbm90YWJseSB0aGUKdW5pbmZlY3RlZCBzYW1wbGVzLgoKYGBge3IgZGUsIGZpZy5zaG93PSJoaWRlIn0KdHJlYXRtZW50X21hY3IgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhtYWNyLCBmYWN0PSJtYWNyb3BoYWdldHJlYXRtZW50IikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJtYWNyb3BoYWdlaW5mZWN0aW9uenltb2RlbWUiKQojI3RtcCA8LSBub3JtYWxpemVfZXhwdChtYWNyLCBmaWx0ZXI9VFJVRSkKIyN6eV9kZSA8LSBkZXNlcV9wYWlyd2lzZSh0bXAsIG1vZGVsX2JhdGNoPSJzdmFzZXEiKQojI3p5X2VkIDwtIGVkZ2VyX3BhaXJ3aXNlKHRtcCwgbW9kZWxfYmF0Y2g9InN2YXNlcSIpCmNvbWJpbmVkX2NvbmRpdGlvbiA8LSBwYXN0ZTAocERhdGEobWFjcilbWyJtYWNyb3BoYWdldHJlYXRtZW50Il1dLCAiXyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcERhdGEobWFjcilbWyJtYWNyb3BoYWdlaW5mZWN0aW9uenltb2RlbWUiXV0pCnBEYXRhKG1hY3JbWyJleHByZXNzaW9uc2V0Il1dKVtbImNvbWJpbmVkIl1dIDwtIGNvbWJpbmVkX2NvbmRpdGlvbgptYWNyIDwtIHNldF9leHB0X2NvbmRpdGlvbnMobWFjciwgZmFjdCA9ICJjb21iaW5lZCIpCnp5bW9fZGUgPC0gYWxsX3BhaXJ3aXNlKG1hY3IsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgIGRvX2Vic2VxID0gRkFMU0UpCmtlZXBlcnMgPC0gbGlzdCgKICAgICJ6MjJfdW5pbmYiID0gYygiaW5mejIyIiwgInVuaW5mbm9uZSIpLAogICAgInoyM191bmluZiIgPSBjKCJpbmZ6MjMiLCAidW5pbmZub25lIiksCiAgICAiejIyX3NidW5pbmYiID0gYygiaW5mc2J6MjIiLCAidW5pbmZzYm5vbmUiKSwKICAgICJ6MjNfc2J1bmluZiIgPSBjKCJpbmZzYnoyMyIsICJ1bmluZnNibm9uZSIpLAogICAgInp5bW9fbm9kcnVnIiA9IGMoImluZnoyMyIsICJpbmZ6MjIiKSwKICAgICJ6eW1vX3NiIiA9IGMoImluZnNiejIzIiwgImluZnNiejIyIikpCgp6eW1vX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgenltb19kZSwga2VlcGVycz1rZWVwZXJzLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvbWFjcm9waGFnZV9kZS12e3Zlcn0ueGxzeCIpKQoKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy96MjJfdnNfdW5pbmZlY3RlZF9tYS5wbmciKQp6eW1vX3RhYmxlJHBsb3RzJHoyMl91bmluZiRkZXNlcV9tYV9wbG90cyRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKenltb190YWJsZSRwbG90cyR6MjJfdW5pbmYkZGVzZXFfbWFfcGxvdHMkcGxvdAoKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy96MjJfdnNfc2JfdW5pbmZlY3RlZF9tYS5wbmciKQp6eW1vX3RhYmxlJHBsb3RzJHoyMl9zYnVuaW5mJGRlc2VxX21hX3Bsb3RzJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQp6eW1vX3RhYmxlJHBsb3RzJHoyMl9zYnVuaW5mJGRlc2VxX21hX3Bsb3RzJHBsb3QKCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvejIzX3ZzX3VuaW5mZWN0ZWRfbWEucG5nIikKenltb190YWJsZSRwbG90cyR6MjNfdW5pbmYkZGVzZXFfbWFfcGxvdHMkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCnp5bW9fdGFibGUkcGxvdHMkejIzX3VuaW5mJGRlc2VxX21hX3Bsb3RzJHBsb3QKCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvejIzX3ZzX3NiX3VuaW5mZWN0ZWRfbWEucG5nIikKenltb190YWJsZSRwbG90cyR6MjNfc2J1bmluZiRkZXNlcV9tYV9wbG90cyRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKenltb190YWJsZSRwbG90cyR6MjNfc2J1bmluZiRkZXNlcV9tYV9wbG90cyRwbG90Cgp6eW1vX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKHp5bW9fdGFibGUsIGFjY29yZGluZ190bz0iZGVzZXEiKQoKejIyX21hIDwtIHBsb3RfbWFfZGUoenltb190YWJsZVtbImRhdGEiXV1bWyJ6MjJfdW5pbmYiXV0sIGV4cHJfY29sPSJkZXNlcV9iYXNlbWVhbiIsCiAgICAgICAgICAgICAgICAgZmNfY29sPSJkZXNlcV9sb2dmYyIsIHBfY29sPSJkZXNlcV9hZGpwIikKejIyX21hJHBsb3QKejIyX3VuaW5mX3VwX3NpZyA8LSB6eW1vX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIyX3VuaW5mIl1dCmRpbSh6MjJfdW5pbmZfdXBfc2lnKQp6MjJfdW5pbmZfZG93bl9zaWcgPC0genltb19zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIyX3VuaW5mIl1dCmRpbSh6MjJfdW5pbmZfZG93bl9zaWcpCgp6MjJfc2J1bmluZl91cF9zaWcgPC0genltb19zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyMl9zYnVuaW5mIl1dCmRpbSh6MjJfc2J1bmluZl91cF9zaWcpCnoyMl9zYnVuaW5mX2Rvd25fc2lnIDwtIHp5bW9fc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyMl9zYnVuaW5mIl1dCmRpbSh6MjJfc2J1bmluZl9kb3duX3NpZykKCgp6MjNfbWEgPC0gcGxvdF9tYV9kZSh6eW1vX3RhYmxlW1siZGF0YSJdXVtbInoyM191bmluZiJdXSwgZXhwcl9jb2w9ImRlc2VxX2Jhc2VtZWFuIiwKICAgICAgICAgICAgICAgICAgICAgZmNfY29sPSJkZXNlcV9sb2dmYyIsIHBfY29sPSJkZXNlcV9hZGpwIikKejIzX21hJHBsb3QKejIzX3VuaW5mX3VwX3NpZyA8LSB6eW1vX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siejIzX3VuaW5mIl1dCmRpbSh6MjNfdW5pbmZfdXBfc2lnKQp6MjNfdW5pbmZfZG93bl9zaWcgPC0genltb19zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siejIzX3VuaW5mIl1dCmRpbSh6MjNfdW5pbmZfZG93bl9zaWcpCgp6MjNfc2J1bmluZl91cF9zaWcgPC0genltb19zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInoyM19zYnVuaW5mIl1dCmRpbSh6MjNfc2J1bmluZl91cF9zaWcpCnoyM19zYnVuaW5mX2Rvd25fc2lnIDwtIHp5bW9fc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInoyM19zYnVuaW5mIl1dCmRpbSh6MjNfc2J1bmluZl9kb3duX3NpZykKYGBgCgojIyBDb21wYXJlIGdyb3VwcyBvZiBnZW5lcwoKYGBge3IgY29tcGFyZV9nZW5lX2dyb3Vwc30KejIyX3oyM19ub3NiX2dyb3VwcyA8LSBsaXN0KAogICAgInoyMl91cCIgPSByb3duYW1lcyh6MjJfdW5pbmZfdXBfc2lnKSwKICAgICJ6MjNfdXAiID0gcm93bmFtZXMoejIzX3VuaW5mX3VwX3NpZykpCnoyMl96MjNfbm9zYl92ZW5uIDwtIFZlbm5lcmFibGU6OlZlbm4oU2V0cyA9IHoyMl96MjNfbm9zYl9ncm91cHMpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvejIyX3oyM19ub3NiX3Zlbm4ucG5nIikKejIyX3oyM19ub3NiX3Zlbm5fcGxvdCA8LSBWZW5uZXJhYmxlOjpwbG90KHoyMl96MjNfbm9zYl92ZW5uLCBkb1dlaWdodHMgPSBGQUxTRSkKY2xvc2VkIDwtIGRldi5vZmYoKQpWZW5uZXJhYmxlOjpwbG90KHoyMl96MjNfbm9zYl92ZW5uLCBkb1dlaWdodHMgPSBGQUxTRSkKCmFubm90IDwtIGZEYXRhKG1hY3IpCnoyM19ub3NiX3VuaXF1ZSA8LSB6MjJfejIzX25vc2JfdmVubkBJbnRlcnNlY3Rpb25TZXRzW1siMDEiXV0Kd2FudGVkIDwtIHJvd25hbWVzKGFubm90KSAlaW4lIHoyM19ub3NiX3VuaXF1ZQp6MjNfd2FudGVkIDwtIGFubm90W3dhbnRlZCwgXQp3cml0dGVuIDwtIHdyaXRlX3hsc3goejIzX3dhbnRlZCwgZXhjZWw9ImV4Y2VsL3oyM19ub3NiX3VuaXF1ZV9nZW5lcy54bHN4IikKCnoyMl9ub3NiX3VuaXF1ZSA8LSB6MjJfejIzX25vc2JfdmVubkBJbnRlcnNlY3Rpb25TZXRzW1siMTAiXV0Kd2FudGVkIDwtIHJvd25hbWVzKGFubm90KSAlaW4lIHoyMl9ub3NiX3VuaXF1ZQp6MjJfd2FudGVkIDwtIGFubm90W3dhbnRlZCwgXQp3cml0dGVuIDwtIHdyaXRlX3hsc3goejIyX3dhbnRlZCwgZXhjZWw9ImV4Y2VsL3oyMl9ub3NiX3VuaXF1ZV9nZW5lcy54bHN4IikKCnoyMl9ub3NiX3NoYXJlZCA8LSB6MjJfejIzX25vc2JfdmVubkBJbnRlcnNlY3Rpb25TZXRzW1siMTEiXV0Kd2FudGVkIDwtIHJvd25hbWVzKGFubm90KSAlaW4lIHoyMl9ub3NiX3NoYXJlZApzaGFyZWRfd2FudGVkIDwtIGFubm90W3dhbnRlZCwgXQp3cml0dGVuIDwtIHdyaXRlX3hsc3goc2hhcmVkX3dhbnRlZCwgZXhjZWw9ImV4Y2VsL3oyMl96MjNfbm9zYl9zaGFyZWRfZ2VuZXMueGxzeCIpCgp6MjJfdW5pcXVlX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIocm93bmFtZXMoejIyX3dhbnRlZCkpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvejIyX3VuaXF1ZV9icC5wbmciLCBoZWlnaHQ9OSwgd2lkdGg9NikKejIyX3VuaXF1ZV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KY2xvc2VkIDwtIGRldi5vZmYoKQp6MjJfdW5pcXVlX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQoKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy96MjJfdW5pcXVlX2tlZ2cucG5nIikKejIyX3VuaXF1ZV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImtlZ2dfcGxvdF9vdmVyIl1dCmNsb3NlZCA8LSBkZXYub2ZmKCkKejIyX3VuaXF1ZV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImtlZ2dfcGxvdF9vdmVyIl1dCgpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL3oyMl91bmlxdWVfcmVhYy5wbmciKQp6MjJfdW5pcXVlX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sicmVhY3RvbWVfcGxvdF9vdmVyIl1dCmNsb3NlZCA8LSBkZXYub2ZmKCkKejIyX3VuaXF1ZV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQoKejIzX3VuaXF1ZV9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHJvd25hbWVzKHoyM193YW50ZWQpKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL3oyM191bmlxdWVfYnAucG5nIiwgaGVpZ2h0PTksIHdpZHRoPTYpCnoyM191bmlxdWVfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCmNsb3NlZCA8LSBkZXYub2ZmKCkKejIzX3VuaXF1ZV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvejIzX3VuaXF1ZV9rZWdnLnBuZyIpCnoyM191bmlxdWVfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJrZWdnX3Bsb3Rfb3ZlciJdXQpjbG9zZWQgPC0gZGV2Lm9mZigpCnoyM191bmlxdWVfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJrZWdnX3Bsb3Rfb3ZlciJdXQoKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy96MjNfdW5pcXVlX3JlYWMucG5nIikKejIzX3VuaXF1ZV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpjbG9zZWQgPC0gZGV2Lm9mZigpCnoyM191bmlxdWVfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJyZWFjdG9tZV9wbG90X292ZXIiXV0KCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvejIzX3VuaXF1ZV90Zi5wbmciKQp6MjNfdW5pcXVlX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sidGZfcGxvdF9vdmVyIl1dCmNsb3NlZCA8LSBkZXYub2ZmKCkKejIzX3VuaXF1ZV9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInRmX3Bsb3Rfb3ZlciJdXQoKejIyX3oyM19zaGFyZWRfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihyb3duYW1lcyhzaGFyZWRfd2FudGVkKSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy96MjNfc2hhcmVkX2JwLnBuZyIsIGhlaWdodD05LCB3aWR0aD02KQp6MjJfejIzX3NoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KY2xvc2VkIDwtIGRldi5vZmYoKQp6MjJfejIzX3NoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvejIzX3NoYXJlZF9rZWdnLnBuZyIpCnoyMl96MjNfc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sia2VnZ19wbG90X292ZXIiXV0KY2xvc2VkIDwtIGRldi5vZmYoKQp6MjJfejIzX3NoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImtlZ2dfcGxvdF9vdmVyIl1dCgpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL3oyM19zaGFyZWRfcmVhYy5wbmciKQp6MjJfejIzX3NoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpjbG9zZWQgPC0gZGV2Lm9mZigpCnoyMl96MjNfc2hhcmVkX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sicmVhY3RvbWVfcGxvdF9vdmVyIl1dCgpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL3oyM19zaGFyZWRfdGYucG5nIikKejIyX3oyM19zaGFyZWRfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJ0Zl9wbG90X292ZXIiXV0KY2xvc2VkIDwtIGRldi5vZmYoKQp6MjJfejIzX3NoYXJlZF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInRmX3Bsb3Rfb3ZlciJdXQpgYGAKCgpgYGB7ciBncHJvZmlsZXJ9CnoyMl91bmluZl91cF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHoyMl91bmluZl91cF9zaWcpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvejIyX3VuaW5mX3VwX2dwX2JwLnBuZyIsIGhlaWdodD0yMCwgd2lkdGg9MTApCnoyMl91bmluZl91cF9ncCRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpjbG9zZWQgPC0gZGV2Lm9mZigpCnoyMl91bmluZl91cF9ncCRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgoKejIyX3VuaW5mX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcih6MjJfdW5pbmZfZG93bl9zaWcpCgp6MjJfc2J1bmluZl91cF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHoyMl9zYnVuaW5mX3VwX3NpZykKejIyX3NidW5pbmZfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHoyMl9zYnVuaW5mX2Rvd25fc2lnKQoKejIzX3VuaW5mX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoejIzX3VuaW5mX3VwX3NpZykKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy96MjNfdW5pbmZfdXBfZ3BfYnAucG5nIiwgaGVpZ2h0PTIwLCB3aWR0aD0xMCkKejIzX3VuaW5mX3VwX2dwJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCmNsb3NlZCA8LSBkZXYub2ZmKCkKejIzX3VuaW5mX3VwX2dwJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCmBgYAoKIyBQYXJhc2l0ZSByZWFkcwoKYGBge3IgcGFyYXNpdGVfZXhwdH0Kc2FuaXRpemVfY29sdW1ucyA8LSBjKCJkb25vciIsICJkcnVnIiwgImNvbmRpdGlvbiIsICJiYXRjaCIsICJtYWNyb3BoYWdldHJlYXRtZW50IiwKICAgICAgICAgICAgICAgICAgICAgICJtYWNyb3BoYWdlaW5mZWN0aW9uenltb2RlbWUiKQpsaWJyYXJ5KG9yZy5McGFuYW1lbnNpcy5NSE9NQ09MODFMMTMudjQ2LmVnLmRiKQpwYW5fZGIgPC0gb3JnLkxwYW5hbWVuc2lzLk1IT01DT0w4MUwxMy52NDYuZWcuZGIKYWxsX2xwX2Fubm90IDwtIHNtKGxvYWRfb3JnZGJfYW5ub3RhdGlvbnMoCiAgICBwYW5fZGIsCiAgICBrZXl0eXBlID0gImdpZCIsCiAgICBmaWVsZHMgPSBjKCJhbm5vdF9nZW5lX2VudHJlel9pZCIsICJhbm5vdF9nZW5lX25hbWUiLAogICAgICAgICAgICAgICAiYW5ub3Rfc3RyYW5kIiwgImFubm90X2Nocm9tb3NvbWUiLCAiYW5ub3RfY2RzX2xlbmd0aCIsCiAgICAgICAgICAgICAgICJhbm5vdF9nZW5lX3Byb2R1Y3QiKSkpJGdlbmVzCm1hY3JfbHAgPC0gY3JlYXRlX2V4cHQobWV0YWRhdGE9InNhbXBsZV9zaGVldHMvdG1yYzJfbWFjcm9waGFnZV9zYW1wbGVzXzIwMjIwMy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89YWxsX2xwX2Fubm90LCBmaWxlX2NvbHVtbiA9ICJscGFuYW1lbnNpc3YzNmhpc2F0ZmlsZSIpCgoKICBleGNsdWRlX2dlbmVzX2V4cHQoY29sdW1uID0gImdlbmVfYmlvdHlwZSIsIG1ldGhvZCA9ICJrZWVwIiwKICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJwcm90ZWluX2NvZGluZyIpICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0idHlwZW9mY2VsbHM9PSdNYWNyb3BoYWdlcyciKSAlPiUKICBzdWJzZXRfZXhwdChub256ZXJvID0gMTEwMDApICU+JQogIHNldF9leHB0X2ZhY3RvcnMoY29sdW1ucyA9IHNhbml0aXplX2NvbHVtbnMpICU+JQogIHNldF9leHB0X2ZhY3RvcnMoY29sdW1ucz1zYW5pdGl6ZV9jb2x1bW5zLCBjbGFzcz0iZmFjdG9yIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJtYWNyb3BoYWdldHJlYXRtZW50IikgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0PSJtYWNyb3BoYWdlaW5mZWN0aW9uenltb2RlbWUiKQpgYGAKCmBgYHtyIHNhdmVtZX0KaWYgKCFpc1RSVUUoZ2V0MCgic2tpcF9sb2FkIikpKSB7CiAgcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKICBtZXNzYWdlKHBhc3RlMCgiVGhpcyBpcyBocGdsdG9vbHMgY29tbWl0OiAiLCBnZXRfZ2l0X2NvbW1pdCgpKSkKICBtZXNzYWdlKHBhc3RlMCgiU2F2aW5nIHRvICIsIHNhdmVmaWxlKSkKICB0bXAgPC0gc20oc2F2ZW1lKGZpbGVuYW1lPXNhdmVmaWxlKSkKfQpgYGAKCmBgYHtyIGxvYWRtZV9hZnRlciwgZXZhbD1GQUxTRX0KdG1wIDwtIGxvYWRtZShmaWxlbmFtZT1zYXZlZmlsZSkKYGBgCg==