1 Overview

batch condition media treatment induced exp_6
SK064 1 LB-IPTG LB DMSO yes control
SK065 2 LB-IPTG LB DMSO yes control
SK066 3 LB-IPTG LB DMSO yes control
SK079 1 LB-EbS-IPTG LB EbS yes treatment
SK080 2 LB-EbS-IPTG LB EbS yes treatment
SK081 3 LB-EbS-IPTG LB EbS yes treatment

2 Project variables

##       batch   condition media treatment induced     exp_6
## SK064     1     LB-IPTG    LB      DMSO     yes   control
## SK065     2     LB-IPTG    LB      DMSO     yes   control
## SK066     3     LB-IPTG    LB      DMSO     yes   control
## SK079     1 LB-EbS-IPTG    LB       EbS     yes treatment
## SK080     2 LB-EbS-IPTG    LB       EbS     yes treatment
## SK081     3 LB-EbS-IPTG    LB       EbS     yes treatment
## [1] "The control is: LB-IPTG"
## [1] "The treatment is: LB-EbS-IPTG"
# Load raw count data
rawcounts <- read.csv("../../raw-data/htseq_SK_unfiltered_reverse_strand_count.csv", 
                      row.names = 1, header = TRUE)

# Append a prefix to the batch and run columns to turn to character class
metadata[["batch"]] <- paste0("b", metadata[["batch"]])
metadata[["run"]] <- paste0("r", metadata[["run"]])

# Subset the rawcounts dataframe to only include samples that are present in experiment
samples <- rownames(metadata)
rawcounts <- select(rawcounts, all_of(samples))

# Ensure that the order of samples in metadata matches the order of columns in rawcounts
all(rownames(metadata) == colnames(rawcounts))  # Should return TRUE if order is correct
## [1] TRUE
# Define the design formula for DESeq2, including main condition and batch effect
design_formula <- ~ exp_6 + batch

# Create DESeq2 dataset object from the filtered count matrix and metadata
dds <- DESeqDataSetFromMatrix(
  countData = rawcounts,
  colData = metadata,
  design = design_formula
)
## Warning in DESeqDataSet(se, design = design, ignoreRank): some variables in
## design formula are characters, converting to factors

3 Library size per sample

# Sum up the counts for each sample
rawcounts_sums <- colSums(rawcounts)

# Turn it into a data frame
data <- data.frame(
  Category = names(rawcounts_sums),
  Count = as.numeric(rawcounts_sums)
)

# Make sure sample order is consistent
data <- data %>%
  mutate(Category = factor(Category, levels = sort(unique(Category))))

# Plot bar chart of library sizes
p <- ggplot(data, aes(x = Category, y = Count, fill = Category)) +
  geom_bar(stat = "identity") +
  # coord_flip() # flip if too many samples to read labels easily
  labs(y = "Library size (M)", x = NULL) +  # remove x label, rename y axis
  # scale_fill_brewer(palette = "Dark2") +  # optional color palette
  scale_y_continuous(
    labels = scales::label_number(scale = 1e-6),  # show counts in millions
    limits = c(0, (max(data$Count) + 1e6))        # add a bit of space on top
  ) +
  theme(
    panel.grid = element_blank(),
    panel.background = element_blank(),
    axis.text = element_text(size = text.size, angle = 45, hjust = 1),  # slant labels
    axis.title = element_text(size = axis.text.size),
    legend.text = element_text(size = text.size),
    legend.title = element_text(size = axis.text.size),
    panel.border = element_rect(fill = NA),
    legend.position = "none",  # no legend needed since each bar is a different sample
    axis.ticks = element_line(linewidth = 0.2),
    legend.key = element_blank()
  )

# Show the plot
p

# Save the plot as a PDF with today’s date and project name
ggsave(paste0(Sys.Date(), "_library_size_", exp, "_", treatment,".vs.", control, ".pdf"), device = "pdf")
## Saving 7 x 5 in image

4 Expression distribution

# Stack rawcounts into single vector 
dat <- stack(rawcounts)

# Format expression distribution plot with the expression level and density 
expression_dist <- ggplot(dat, aes(x = log2(values+1),  fill=ind, label = ind )) + 
  geom_density(alpha = 0.5, position = "identity") + 
  ylab("Density") + 
  geom_textdensity(hjust = "ymax", vjust = 0,
           text_only = TRUE, text_smoothing = 20) + 
    theme(panel.grid = element_blank(),
        panel.background = element_blank(),
        axis.text = element_text(size = text.size),
        axis.title = element_text(size = axis.text.size),
        legend.text = element_text(size = text.size),
        legend.title = element_text(size = axis.text.size),
        panel.border = element_rect(fill = NA),
        legend.position = "none",
        axis.ticks = element_line(linewidth = 0.2),
        legend.key = element_blank()) +
  coord_cartesian(xlim = c(0, 15))

expression_dist

#save figure
cairo_pdf(paste0(Sys.Date(), "_expression_dist_", exp, "_", treatment, ".vs.", control, ".pdf"))
expression_dist
dev.off() 
## quartz_off_screen 
##                 2

5 Non-zero genes observed

# Prepare data by getting library sizes and non-zero counts
x <- colSums(rawcounts)
y <- colSums(rawcounts != 0) 
df <- data.frame(x,y)
df$ind <- rownames(df)

# Calculate axis limits
x_min <- min(df$x)
x_max <- max(df$x)
y_min <- min(df$y)
y_max <- max(df$y)

# Non-zero plot
nonzero <- ggplot(data = df, aes(x = x, y = y, color = ind, label = ind)) +
  geom_point(size = 3) +
  geom_text(hjust = -0.1, vjust = -0.1, color = "black", size = 5) +
  scale_y_continuous(limits=c(y_min, y_max)) + 
  scale_x_continuous(
    limits = c(x_min-1e3, x_max+9e5),
    labels = scales::comma_format(scale = 1e-6,  accuracy = 1)  # Format labels without decimals
  ) +
  xlab("Millions of reads") + ylab("Number of non-zero genes observed") +
  labs(color = "Sample") + 
    theme(panel.grid = element_blank(),
        panel.background = element_blank(),
        axis.text = element_text(size = text.size),
        axis.title = element_text(size = axis.text.size),
        legend.text = element_text(size = text.size),
        legend.title = element_text(size = axis.text.size),
        panel.border = element_rect(fill = NA),
        legend.position = "none",
        axis.ticks = element_line(linewidth = 0.2),
        legend.key = element_blank()) +
  coord_cartesian()

# Show nonzero plot
nonzero

# Save plot

cairo_pdf(paste0(Sys.Date(), "_non-zero_", exp, "_", treatment, ".vs.", control, ".pdf"))
nonzero
dev.off() 
## quartz_off_screen 
##                 2

6 RPKM and CPM transformations

# Load GFF annotation 
gff_annot <- load_gff_annotations("../../raw-data/paeruginosa_pa14.gff", 
                                  id_col = "gene_id", type = "gene")
## Returning a df with 16 columns and 5979 rows.
rownames(gff_annot) <- gff_annot$gene_id

head(gff_annot)
##               seqnames start  end width strand    source type score phase
## gene1650835 chromosome   483 2027  1545      + PseudoCAP gene    NA     0
## gene1650837 chromosome  2056 3159  1104      + PseudoCAP gene    NA     0
## gene1650839 chromosome  3169 4278  1110      + PseudoCAP gene    NA     0
## gene1650841 chromosome  4275 6695  2421      + PseudoCAP gene    NA     0
## gene1650843 chromosome  7018 7791   774      - PseudoCAP gene    NA     0
## gene1650845 chromosome  7803 8339   537      - PseudoCAP gene    NA     0
##                 gene_id Name         Dbxref      Alias       name Parent locus
## gene1650835 gene1650835      GeneID:4384099 PA14_00010       dnaA         <NA>
## gene1650837 gene1650837      GeneID:4384100 PA14_00020       dnaN         <NA>
## gene1650839 gene1650839      GeneID:4384101 PA14_00030       recF         <NA>
## gene1650841 gene1650841      GeneID:4384102 PA14_00050       gyrB         <NA>
## gene1650843 gene1650843      GeneID:4385186 PA14_00060 PA14_00060         <NA>
## gene1650845 gene1650845      GeneID:4385187 PA14_00070 PA14_00070         <NA>
head(rawcounts)
##             SK064 SK065 SK066 SK079 SK080 SK081
## gene1650835  2234  2528  1719  1417  1053   855
## gene1650837  1266  1754  1368  1011   811   679
## gene1650839   722   770   657   361   255   252
## gene1650841  3671  4307  3347  2655  2085  1874
## gene1650843   436   435   313   197   190   182
## gene1650845   257   299   177   110    99    87
dim(gff_annot)
## [1] 5979   16
dim(rawcounts)
## [1] 5979    6
summary(rownames(gff_annot) == rownames(rawcounts))
##    Mode   FALSE    TRUE 
## logical     932    5047
gff_annot <- gff_annot[rownames(rawcounts),]
summary(rownames(gff_annot) == rownames(rawcounts))
##    Mode    TRUE 
## logical    5979
# Create an expression object with counts, metadata, and gene info
expt <- create_expt(count_dataframe = rawcounts,
                    metadata = metadata, 
                    gene_info = gff_annot)
## Reading the sample metadata.
## Did not find the column: sampleid.
## The rownames do not appear numeric, using them.
## The sample definitions comprises: 6 rows(samples) and 8 columns(metadata fields).
## Matched 5979 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## Saving the expressionset to 'expt.rda'.
## The final expressionset has 5979 features and 6 samples.
# Normalize counts log2 CPM
cpm_normalized_exp <- normalize_expt(expt, 
                                     transform = "log2", 
                                     norm = "raw", 
                                     convert = "cpm", 
                                     row_min = "10")
## transform_counts: Found 322 values equal to 0, adding 1 to the matrix.
####### Calculate RPKM ########

# Grab gene lengths from GFF (should be in base pairs)
gene_lengths <- gff_annot$width  
names(gene_lengths) <- rownames(gff_annot)  # set gene names

# Make sure gene_lengths are in the same order as rawcounts rows
gene_lengths <- gene_lengths[rownames(rawcounts)]

# Make DGEList object for edgeR
dge <- DGEList(counts = rawcounts)

# Calculate RPKM (reads per kilobase per million)
rpkm <- rpkm(dge, gene.length = gene_lengths)

# Wrap RPKM in an experiment object too
expt_rpkm <- create_expt(count_dataframe = rpkm,
                         metadata = metadata, 
                         gene_info = gff_annot)
## Reading the sample metadata.
## Did not find the column: sampleid.
## The rownames do not appear numeric, using them.
## The sample definitions comprises: 6 rows(samples) and 8 columns(metadata fields).
## Matched 5979 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## Saving the expressionset to 'expt.rda'.
## The final expressionset has 5979 features and 6 samples.
# log2 transform the RPKM (again, no normalization beyond log)
rpkm_normalized_exp <- normalize_expt(expt_rpkm, 
                                      transform = "log2", 
                                      norm = "raw")
## transform_counts: Found 322 values equal to 0, adding 1 to the matrix.
# Get the actual expression matrices from the experiment objects
rpkm <- exprs(rpkm_normalized_exp)
cpm <- exprs(cpm_normalized_exp)

# Merge CPM and RPKM matrices with gene annotation info
cpm_annotated <- merge(gff_annot, cpm, by = 0)
rpkm_annotated <- merge(gff_annot, rpkm, by = 0)

6.1 Heatmap of alginate genes

This generates a small heatmap of the alginate genes across samples to visualize expression.

# Loop through CPM and RPKM to plot both heatmaps
for (type in c("cpm", "rpkm")) {
  
  # Define gene list
  alg_operon_genes <- c(
    "algA", "algF", "algJ", "algI", "algL", "algX", "algG", "algE",
    "algK", "alg44", "alg8", "algD", "mucC", "mucB", "algU", "algW",
    "algP", "algQ", "algR", "algZ", "algC", "algB"
  )

  # Get the right data per type of transformation
  data_annot <- get(paste0(type, "_annotated"))
  
  # Fix rownames using gene name (make unique)
  rownames(data_annot) <- make.names(data_annot$name, unique = TRUE)
  
  # Drop undesired metadata columns
  cols_to_exclude <- c("Row.names","seqnames","start","end","width",
                       "strand","source","type","score","phase",
                       "gene_id","Name","Dbxref","Alias","name",
                       "Parent","locus")
  keep <- !names(data_annot) %in% cols_to_exclude
  expr_data <- data_annot[, keep]
  
  # Extract matrix for alg genes
  alg_genes <- expr_data[alg_operon_genes, , drop = FALSE]
  mat <- alg_genes - rowMeans(alg_genes)
  
  # Pull sample annotations
  anno <- as.data.frame(metadata[, c("condition", "induced")])
  colnames(anno) <- c("Condition", "Induced")
  
  # Color settings for annotation
 # ann_colors <- list(
 #  Condition = c("LB-DMSO" = "#D95F02", "LB-IPTG" = "#66A61E"),
 #  Induced = c("no" = "lightgrey", "yes" = "gray27")
 # )
  
  # Scale data by row (Z-score per gene)
  scaled_mat <- t(scale(t(mat)))

  # Build heatmap
  ht <- Heatmap(
    scaled_mat,
    name = "Z-score",
    top_annotation = HeatmapAnnotation(df = anno#, 
                                       #col = ann_colors
                                       ),
    cluster_rows = TRUE,
    cluster_columns = TRUE,
    row_names_side = "left",
    column_names_side = "bottom",
    column_names_rot = 45,
    row_names_gp = gpar(fontsize = 10),
    column_names_gp = gpar(fontsize = 10),
    show_row_dend = TRUE,
    show_column_dend = TRUE
  )
  
  # Draw and save
  draw(ht)
  
  cairo_pdf(paste0(Sys.Date(), "_alg_heatmap_", type, "_", exp, "_", treatment, ".vs.", control, ".pdf"))
  draw(ht)
  dev.off()
}

7 DESeq

# Create DESeqDataSet
dds <- DESeqDataSetFromMatrix(
  countData = rawcounts,
  colData = metadata,
  design = design_formula
)
## Warning in DESeqDataSet(se, design = design, ignoreRank): some variables in
## design formula are characters, converting to factors
# Check number of genes before filtering
print("Number of genes before filtering:")
## [1] "Number of genes before filtering:"
nrow(dds)
## [1] 5979
# Filter: keep genes with counts >=10 in at least 2 samples
print("Filtering genes with counts >=10 in at least 2 samples")
## [1] "Filtering genes with counts >=10 in at least 2 samples"
keep <- rowSums(counts(dds) >= 10) >= 2 
dds_filtered <- dds[keep, ]

# Check number of genes after filtering
print("Number of genes after filtering:")
## [1] "Number of genes after filtering:"
nrow(dds_filtered)
## [1] 5712
# Run DESeq on the filtered dataset
dds_final <- DESeq(dds_filtered)
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
# Show available results
resultsNames(dds_final)
## [1] "Intercept"                  "exp_6_treatment_vs_control"
## [3] "batch_b2_vs_b1"             "batch_b3_vs_b1"
# Plot dispersion estimates
plotDispEsts(dds_final)

8 Save DE tables

res <- results(dds_final, contrast = c("exp_6", "treatment", "control"))
resdf <- as.data.frame(res)
resdf$gene_id <- rownames(resdf)

cpm <- as.data.frame(cpm)
rpkm <- as.data.frame(rpkm)

# append type of value to the dataframe   
colnames(rpkm) <- paste0(colnames(rpkm), "_rpkm")
colnames(cpm) <- paste0(colnames(cpm), "_cpm")
rawcounts2 <- rawcounts
colnames(rawcounts2) <- paste0(colnames(rawcounts2), "_rawcounts")

# ensure column gene_id is there
rpkm$gene_id <- rownames(rpkm)
cpm$gene_id <- rownames(cpm)
rawcounts2$gene_id <- rownames(rawcounts2)

gff_annot <- gff_annot[rownames(resdf),]

dim(resdf)
## [1] 5712    7
# merge with siggenes
resdf <- full_join(resdf, gff_annot, by = "gene_id", copy = FALSE)
head(resdf)
##    baseMean log2FoldChange     lfcSE      stat       pvalue         padj
## 1 1516.5749     -0.3569257 0.1518223 -2.350944 1.872587e-02 0.0493595534
## 2 1084.6093     -0.1968712 0.1688912 -1.165669 2.437483e-01 0.3786484593
## 3  460.2331     -0.7058229 0.1769334 -3.989201 6.629618e-05 0.0003760514
## 4 2831.9018     -0.1649209 0.1463361 -1.127001 2.597419e-01 0.3969089939
## 5  272.1281     -0.4242725 0.2042889 -2.076826 3.781763e-02 0.0872284632
## 6  155.6598     -0.6664666 0.2337651 -2.851010 4.358061e-03 0.0145659715
##       gene_id   seqnames start  end width strand    source type score phase
## 1 gene1650835 chromosome   483 2027  1545      + PseudoCAP gene    NA     0
## 2 gene1650837 chromosome  2056 3159  1104      + PseudoCAP gene    NA     0
## 3 gene1650839 chromosome  3169 4278  1110      + PseudoCAP gene    NA     0
## 4 gene1650841 chromosome  4275 6695  2421      + PseudoCAP gene    NA     0
## 5 gene1650843 chromosome  7018 7791   774      - PseudoCAP gene    NA     0
## 6 gene1650845 chromosome  7803 8339   537      - PseudoCAP gene    NA     0
##   Name         Dbxref      Alias       name Parent locus
## 1      GeneID:4384099 PA14_00010       dnaA         <NA>
## 2      GeneID:4384100 PA14_00020       dnaN         <NA>
## 3      GeneID:4384101 PA14_00030       recF         <NA>
## 4      GeneID:4384102 PA14_00050       gyrB         <NA>
## 5      GeneID:4385186 PA14_00060 PA14_00060         <NA>
## 6      GeneID:4385187 PA14_00070 PA14_00070         <NA>
pa_go <- read.csv("../../raw-data/208963_microbes.online.csv", header = TRUE)
head(pa_go)
##   locusId   accession        GI scaffoldId start stop strand      Alias
## 1 2194572 YP_788156.1 116053721       4582   483 2027      + PA14_00010
## 2 2194573 YP_788157.1 116053722       4582  2056 3159      + PA14_00020
## 3 2194574 YP_788158.1 116053723       4582  3169 4278      + PA14_00030
## 4 2194575 YP_788159.1 116053724       4582  4275 6695      + PA14_00050
## 5 2194576 YP_788160.1 116053725       4582  7791 7018      - PA14_00060
## 6 2194577 YP_788161.1 116053726       4582  8339 7803      - PA14_00070
##         name                                                  desc     COG
## 1       dnaA chromosomal replication initiator protein DnaA (NCBI)  COG593
## 2       dnaN                 DNA polymerase III, beta chain (NCBI)  COG592
## 3       recF        DNA replication and repair protein RecF (NCBI) COG1195
## 4       gyrB                           DNA gyrase subunit B (NCBI)  COG187
## 5 PA14_00060                       putative acyltransferase (NCBI)  COG204
## 6 PA14_00070                putative histidinol-phosphatase (NCBI)  COG241
##   COGFun
## 1      L
## 2      L
## 3      L
## 4      L
## 5      I
## 6      E
##                                                                    COGDesc
## 1                            ATPase involved in DNA replication initiation
## 2                      DNA polymerase sliding clamp subunit (PCNA homolog)
## 3                         Recombinational DNA repair ATPase (RecF pathway)
## 4 Type IIA topoisomerase (DNA gyrase/topo II, topoisomerase IV), B subunit
## 5                           1-acyl-sn-glycerol-3-phosphate acyltransferase
## 6                          Histidinol phosphatase and related phosphatases
##                                                                                  TIGRFam
## 1                        TIGR00362 chromosomal replication initiator protein DnaA [dnaA]
## 2                                      TIGR00663 DNA polymerase III, beta subunit [dnaN]
## 3                               TIGR00611 DNA replication and repair protein RecF [recF]
## 4                                                 TIGR01059 DNA gyrase, B subunit [gyrB]
## 5                                                                                       
## 6 TIGR01656 histidinol-phosphate phosphatase domain,TIGR01662 HAD hydrolase, family IIIA
##                                                   TIGRRoles
## 1 DNA metabolism:DNA replication, recombination, and repair
## 2 DNA metabolism:DNA replication, recombination, and repair
## 3 DNA metabolism:DNA replication, recombination, and repair
## 4 DNA metabolism:DNA replication, recombination, and repair
## 5                                                          
## 6           Unknown function:Enzymes of unknown specificity
##                                                                                                                                                                                           GO
## 1                                                                                                                                     GO:0006270,GO:0006275,GO:0003688,GO:0017111,GO:0005524
## 2 GO:0006260,GO:0003677,GO:0003893,GO:0008408,GO:0016449,GO:0019984,GO:0003889,GO:0003894,GO:0015999,GO:0016450,GO:0003890,GO:0003895,GO:0016000,GO:0016451,GO:0003891,GO:0016448,GO:0016452
## 3                                                                                                                                     GO:0006281,GO:0005694,GO:0005524,GO:0017111,GO:0003697
## 4                                                                                                                                     GO:0006304,GO:0006265,GO:0005694,GO:0003918,GO:0005524
## 5                                                                                                                                                                      GO:0008152,GO:0003841
## 6                                                                                                                                                                      GO:0000105,GO:0004401
##         EC                                        ECDesc
## 1                                                       
## 2  2.7.7.7                  DNA-directed DNA polymerase.
## 3                                                       
## 4 5.99.1.3          DNA topoisomerase (ATP-hydrolyzing).
## 5 2.3.1.51 1-acylglycerol-3-phosphate O-acyltransferase.
## 6  3.1.3.-
col_to_remove <- intersect(colnames(pa_go),colnames(resdf))
col_to_remove <- setdiff(col_to_remove, "Alias") # returns all except the second vector

pa_go <- pa_go %>% select(-all_of(col_to_remove))

resdf <- full_join(resdf, rpkm, by = "gene_id", copy = FALSE)
resdf <- full_join(resdf, cpm, by = "gene_id", copy = FALSE)
resdf <- full_join(resdf, rawcounts2, by = "gene_id", copy = FALSE)
#resdf <- full_join(resdf, pa_go, by = "Alias", copy = FALSE)
resdf <- merge(resdf, pa_go, by = "Alias", copy = FALSE)

head(resdf)
##        Alias  baseMean log2FoldChange     lfcSE      stat       pvalue
## 1 PA14_00010 1516.5749     -0.3569257 0.1518223 -2.350944 1.872587e-02
## 2 PA14_00020 1084.6093     -0.1968712 0.1688912 -1.165669 2.437483e-01
## 3 PA14_00030  460.2331     -0.7058229 0.1769334 -3.989201 6.629618e-05
## 4 PA14_00050 2831.9018     -0.1649209 0.1463361 -1.127001 2.597419e-01
## 5 PA14_00060  272.1281     -0.4242725 0.2042889 -2.076826 3.781763e-02
## 6 PA14_00070  155.6598     -0.6664666 0.2337651 -2.851010 4.358061e-03
##           padj     gene_id   seqnames start  end width strand    source type
## 1 0.0493595534 gene1650835 chromosome   483 2027  1545      + PseudoCAP gene
## 2 0.3786484593 gene1650837 chromosome  2056 3159  1104      + PseudoCAP gene
## 3 0.0003760514 gene1650839 chromosome  3169 4278  1110      + PseudoCAP gene
## 4 0.3969089939 gene1650841 chromosome  4275 6695  2421      + PseudoCAP gene
## 5 0.0872284632 gene1650843 chromosome  7018 7791   774      - PseudoCAP gene
## 6 0.0145659715 gene1650845 chromosome  7803 8339   537      - PseudoCAP gene
##   score phase Name         Dbxref       name Parent locus SK064_rpkm SK065_rpkm
## 1    NA     0      GeneID:4384099       dnaA         <NA>   8.176179   8.165287
## 2    NA     0      GeneID:4384100       dnaN         <NA>   7.842995   8.122956
## 3    NA     0      GeneID:4384101       recF         <NA>   7.029755   6.934080
## 4    NA     0      GeneID:4384102       gyrB         <NA>   8.244496   8.285574
## 5    NA     0      GeneID:4385186 PA14_00060         <NA>   6.823946   6.633153
## 6    NA     0      GeneID:4385187 PA14_00070         <NA>   6.591050   6.619830
##   SK066_rpkm SK079_rpkm SK080_rpkm SK081_rpkm SK064_cpm SK065_cpm SK066_cpm
## 1   7.893669   7.520610   7.429972   7.238556  8.802026  8.791120  8.519135
## 2   8.048415   7.518432   7.537503   7.389952  7.985143  8.265208  8.190642
## 3   6.988440   6.039118   5.877444   5.966771  7.179220  7.083470  7.137873
## 4   8.205787   7.777199   7.765771   7.719958  9.517304  9.558461  9.478520
## 5   6.444121   5.691550   5.971525   6.016644  6.458065  6.267796  6.079357
## 6   6.152874   5.385024   5.566040   5.489228  5.706889  5.735417  5.273245
##   SK079_cpm SK080_cpm SK081_cpm SK064_rawcounts SK065_rawcounts SK066_rawcounts
## 1  8.145443  8.054625  7.862789            2234            2528            1719
## 2  7.660431  7.679511  7.531882            1266            1754            1368
## 3  6.187502  6.025570  6.115043             722             770             657
## 4  9.048937  9.037478  8.991540            3671            4307            3347
## 5  5.330084  5.608628  5.653541             436             435             313
## 6  4.517482  4.695054  4.619652             257             299             177
##   SK079_rawcounts SK080_rawcounts SK081_rawcounts locusId   accession        GI
## 1            1417            1053             855 2194572 YP_788156.1 116053721
## 2            1011             811             679 2194573 YP_788157.1 116053722
## 3             361             255             252 2194574 YP_788158.1 116053723
## 4            2655            2085            1874 2194575 YP_788159.1 116053724
## 5             197             190             182 2194576 YP_788160.1 116053725
## 6             110              99              87 2194577 YP_788161.1 116053726
##   scaffoldId stop                                                  desc     COG
## 1       4582 2027 chromosomal replication initiator protein DnaA (NCBI)  COG593
## 2       4582 3159                 DNA polymerase III, beta chain (NCBI)  COG592
## 3       4582 4278        DNA replication and repair protein RecF (NCBI) COG1195
## 4       4582 6695                           DNA gyrase subunit B (NCBI)  COG187
## 5       4582 7018                       putative acyltransferase (NCBI)  COG204
## 6       4582 7803                putative histidinol-phosphatase (NCBI)  COG241
##   COGFun
## 1      L
## 2      L
## 3      L
## 4      L
## 5      I
## 6      E
##                                                                    COGDesc
## 1                            ATPase involved in DNA replication initiation
## 2                      DNA polymerase sliding clamp subunit (PCNA homolog)
## 3                         Recombinational DNA repair ATPase (RecF pathway)
## 4 Type IIA topoisomerase (DNA gyrase/topo II, topoisomerase IV), B subunit
## 5                           1-acyl-sn-glycerol-3-phosphate acyltransferase
## 6                          Histidinol phosphatase and related phosphatases
##                                                                                  TIGRFam
## 1                        TIGR00362 chromosomal replication initiator protein DnaA [dnaA]
## 2                                      TIGR00663 DNA polymerase III, beta subunit [dnaN]
## 3                               TIGR00611 DNA replication and repair protein RecF [recF]
## 4                                                 TIGR01059 DNA gyrase, B subunit [gyrB]
## 5                                                                                       
## 6 TIGR01656 histidinol-phosphate phosphatase domain,TIGR01662 HAD hydrolase, family IIIA
##                                                   TIGRRoles
## 1 DNA metabolism:DNA replication, recombination, and repair
## 2 DNA metabolism:DNA replication, recombination, and repair
## 3 DNA metabolism:DNA replication, recombination, and repair
## 4 DNA metabolism:DNA replication, recombination, and repair
## 5                                                          
## 6           Unknown function:Enzymes of unknown specificity
##                                                                                                                                                                                           GO
## 1                                                                                                                                     GO:0006270,GO:0006275,GO:0003688,GO:0017111,GO:0005524
## 2 GO:0006260,GO:0003677,GO:0003893,GO:0008408,GO:0016449,GO:0019984,GO:0003889,GO:0003894,GO:0015999,GO:0016450,GO:0003890,GO:0003895,GO:0016000,GO:0016451,GO:0003891,GO:0016448,GO:0016452
## 3                                                                                                                                     GO:0006281,GO:0005694,GO:0005524,GO:0017111,GO:0003697
## 4                                                                                                                                     GO:0006304,GO:0006265,GO:0005694,GO:0003918,GO:0005524
## 5                                                                                                                                                                      GO:0008152,GO:0003841
## 6                                                                                                                                                                      GO:0000105,GO:0004401
##         EC                                        ECDesc
## 1                                                       
## 2  2.7.7.7                  DNA-directed DNA polymerase.
## 3                                                       
## 4 5.99.1.3          DNA topoisomerase (ATP-hydrolyzing).
## 5 2.3.1.51 1-acylglycerol-3-phosphate O-acyltransferase.
## 6  3.1.3.-
write.csv(resdf, paste0(Sys.Date() , "_results_",exp, "_", treatment,".vs.", control,".csv"), row.names = FALSE)

9 Save DEG list

# filter for significantly differentially expressed genes (LFC >= 3, padj < pval_cutoff)
dim(resdf)
## [1] 5705   54
head(resdf)
##        Alias  baseMean log2FoldChange     lfcSE      stat       pvalue
## 1 PA14_00010 1516.5749     -0.3569257 0.1518223 -2.350944 1.872587e-02
## 2 PA14_00020 1084.6093     -0.1968712 0.1688912 -1.165669 2.437483e-01
## 3 PA14_00030  460.2331     -0.7058229 0.1769334 -3.989201 6.629618e-05
## 4 PA14_00050 2831.9018     -0.1649209 0.1463361 -1.127001 2.597419e-01
## 5 PA14_00060  272.1281     -0.4242725 0.2042889 -2.076826 3.781763e-02
## 6 PA14_00070  155.6598     -0.6664666 0.2337651 -2.851010 4.358061e-03
##           padj     gene_id   seqnames start  end width strand    source type
## 1 0.0493595534 gene1650835 chromosome   483 2027  1545      + PseudoCAP gene
## 2 0.3786484593 gene1650837 chromosome  2056 3159  1104      + PseudoCAP gene
## 3 0.0003760514 gene1650839 chromosome  3169 4278  1110      + PseudoCAP gene
## 4 0.3969089939 gene1650841 chromosome  4275 6695  2421      + PseudoCAP gene
## 5 0.0872284632 gene1650843 chromosome  7018 7791   774      - PseudoCAP gene
## 6 0.0145659715 gene1650845 chromosome  7803 8339   537      - PseudoCAP gene
##   score phase Name         Dbxref       name Parent locus SK064_rpkm SK065_rpkm
## 1    NA     0      GeneID:4384099       dnaA         <NA>   8.176179   8.165287
## 2    NA     0      GeneID:4384100       dnaN         <NA>   7.842995   8.122956
## 3    NA     0      GeneID:4384101       recF         <NA>   7.029755   6.934080
## 4    NA     0      GeneID:4384102       gyrB         <NA>   8.244496   8.285574
## 5    NA     0      GeneID:4385186 PA14_00060         <NA>   6.823946   6.633153
## 6    NA     0      GeneID:4385187 PA14_00070         <NA>   6.591050   6.619830
##   SK066_rpkm SK079_rpkm SK080_rpkm SK081_rpkm SK064_cpm SK065_cpm SK066_cpm
## 1   7.893669   7.520610   7.429972   7.238556  8.802026  8.791120  8.519135
## 2   8.048415   7.518432   7.537503   7.389952  7.985143  8.265208  8.190642
## 3   6.988440   6.039118   5.877444   5.966771  7.179220  7.083470  7.137873
## 4   8.205787   7.777199   7.765771   7.719958  9.517304  9.558461  9.478520
## 5   6.444121   5.691550   5.971525   6.016644  6.458065  6.267796  6.079357
## 6   6.152874   5.385024   5.566040   5.489228  5.706889  5.735417  5.273245
##   SK079_cpm SK080_cpm SK081_cpm SK064_rawcounts SK065_rawcounts SK066_rawcounts
## 1  8.145443  8.054625  7.862789            2234            2528            1719
## 2  7.660431  7.679511  7.531882            1266            1754            1368
## 3  6.187502  6.025570  6.115043             722             770             657
## 4  9.048937  9.037478  8.991540            3671            4307            3347
## 5  5.330084  5.608628  5.653541             436             435             313
## 6  4.517482  4.695054  4.619652             257             299             177
##   SK079_rawcounts SK080_rawcounts SK081_rawcounts locusId   accession        GI
## 1            1417            1053             855 2194572 YP_788156.1 116053721
## 2            1011             811             679 2194573 YP_788157.1 116053722
## 3             361             255             252 2194574 YP_788158.1 116053723
## 4            2655            2085            1874 2194575 YP_788159.1 116053724
## 5             197             190             182 2194576 YP_788160.1 116053725
## 6             110              99              87 2194577 YP_788161.1 116053726
##   scaffoldId stop                                                  desc     COG
## 1       4582 2027 chromosomal replication initiator protein DnaA (NCBI)  COG593
## 2       4582 3159                 DNA polymerase III, beta chain (NCBI)  COG592
## 3       4582 4278        DNA replication and repair protein RecF (NCBI) COG1195
## 4       4582 6695                           DNA gyrase subunit B (NCBI)  COG187
## 5       4582 7018                       putative acyltransferase (NCBI)  COG204
## 6       4582 7803                putative histidinol-phosphatase (NCBI)  COG241
##   COGFun
## 1      L
## 2      L
## 3      L
## 4      L
## 5      I
## 6      E
##                                                                    COGDesc
## 1                            ATPase involved in DNA replication initiation
## 2                      DNA polymerase sliding clamp subunit (PCNA homolog)
## 3                         Recombinational DNA repair ATPase (RecF pathway)
## 4 Type IIA topoisomerase (DNA gyrase/topo II, topoisomerase IV), B subunit
## 5                           1-acyl-sn-glycerol-3-phosphate acyltransferase
## 6                          Histidinol phosphatase and related phosphatases
##                                                                                  TIGRFam
## 1                        TIGR00362 chromosomal replication initiator protein DnaA [dnaA]
## 2                                      TIGR00663 DNA polymerase III, beta subunit [dnaN]
## 3                               TIGR00611 DNA replication and repair protein RecF [recF]
## 4                                                 TIGR01059 DNA gyrase, B subunit [gyrB]
## 5                                                                                       
## 6 TIGR01656 histidinol-phosphate phosphatase domain,TIGR01662 HAD hydrolase, family IIIA
##                                                   TIGRRoles
## 1 DNA metabolism:DNA replication, recombination, and repair
## 2 DNA metabolism:DNA replication, recombination, and repair
## 3 DNA metabolism:DNA replication, recombination, and repair
## 4 DNA metabolism:DNA replication, recombination, and repair
## 5                                                          
## 6           Unknown function:Enzymes of unknown specificity
##                                                                                                                                                                                           GO
## 1                                                                                                                                     GO:0006270,GO:0006275,GO:0003688,GO:0017111,GO:0005524
## 2 GO:0006260,GO:0003677,GO:0003893,GO:0008408,GO:0016449,GO:0019984,GO:0003889,GO:0003894,GO:0015999,GO:0016450,GO:0003890,GO:0003895,GO:0016000,GO:0016451,GO:0003891,GO:0016448,GO:0016452
## 3                                                                                                                                     GO:0006281,GO:0005694,GO:0005524,GO:0017111,GO:0003697
## 4                                                                                                                                     GO:0006304,GO:0006265,GO:0005694,GO:0003918,GO:0005524
## 5                                                                                                                                                                      GO:0008152,GO:0003841
## 6                                                                                                                                                                      GO:0000105,GO:0004401
##         EC                                        ECDesc
## 1                                                       
## 2  2.7.7.7                  DNA-directed DNA polymerase.
## 3                                                       
## 4 5.99.1.3          DNA topoisomerase (ATP-hydrolyzing).
## 5 2.3.1.51 1-acylglycerol-3-phosphate O-acyltransferase.
## 6  3.1.3.-
summary(is.na(resdf$log2FoldChange))
##    Mode   FALSE 
## logical    5705
summary(is.na(resdf$padj))
##    Mode   FALSE 
## logical    5705
sig_genes <- resdf[abs(resdf$log2FoldChange) >= logfc_cutoff & resdf$padj < pval_cutoff, ]  %>% drop_na(log2FoldChange)
sig_genes$direction <- ifelse(sig_genes$log2FoldChange > 0, "up", "down")

summary(is.na(sig_genes$log2FoldChange))
##    Mode   FALSE 
## logical      71
summary(is.na(sig_genes$padj))
##    Mode   FALSE 
## logical      71
dim(sig_genes)
## [1] 71 55
head(sig_genes)
##        Alias     baseMean log2FoldChange     lfcSE       stat       pvalue
## 1 PA14_04300 17819.806138       2.326419 0.1520139  15.303986 7.191363e-53
## 2 PA14_06420   150.466093      -2.126105 0.2670637  -7.961039 1.706003e-15
## 3 PA14_06450    95.868754      -2.160546 0.3261977  -6.623426 3.509687e-11
## 4 PA14_07355   197.528489       3.177465 0.2444854  12.996542 1.280019e-38
## 5 PA14_09660   191.299647      -2.461510 0.2358467 -10.436907 1.682028e-25
## 6 PA14_14570     8.641151      -3.018266 0.9821516  -3.073116 2.118362e-03
##           padj     gene_id   seqnames   start     end width strand    source
## 1 8.215413e-50 gene1651523 chromosome  384875  385207   333      - PseudoCAP
## 2 6.911126e-14 gene1651855 chromosome  564699  565457   759      + PseudoCAP
## 3 7.370342e-10 gene1651859 chromosome  565793  567169  1377      + PseudoCAP
## 4 5.222478e-36 gene1651999 chromosome  631670  632008   339      + PseudoCAP
## 5 2.234359e-23 gene1652389 chromosome  829037  830659  1623      - PseudoCAP
## 6 7.697256e-03 gene1653167 chromosome 1244743 1244826    84      - PseudoCAP
##   type score phase Name         Dbxref       name Parent locus SK064_rpkm
## 1 gene    NA     0      GeneID:4383734 PA14_04300         <NA>  11.972453
## 2 gene    NA     0      GeneID:4383861 PA14_06420         <NA>   6.436684
## 3 gene    NA     0      GeneID:4383863 PA14_06450         <NA>   4.811072
## 4 gene    NA     0      GeneID:4384180 PA14_07355         <NA>   5.007502
## 5 gene    NA     0      GeneID:4382208 PA14_09660         <NA>   5.633430
## 6 gene    NA     0      GeneID:4384131 PA14_14570         <NA>   5.970477
##   SK065_rpkm SK066_rpkm SK079_rpkm SK080_rpkm SK081_rpkm SK064_cpm SK065_cpm
## 1  12.044165  12.233940  14.126349  13.994070  14.125677 10.386766 10.458443
## 2   6.367097   6.140465   4.109816   3.451878   4.209503  6.044135  5.974808
## 3   4.854655   4.864503   2.962812   2.654812   1.982931  5.258461  5.302467
## 4   4.502150   5.099123   7.669912   7.664135   7.706730  3.531763  3.060589
## 5   5.749129   5.531173   2.953782   3.103405   2.972328  6.320893  6.437459
## 6   5.185216   5.285668   3.019960   1.998053   2.079688  2.628331  1.989946
##   SK066_cpm  SK079_cpm  SK080_cpm  SK081_cpm SK064_rawcounts SK065_rawcounts
## 1 10.648134 12.5401043 12.4078409 12.5394329            6711            8042
## 2  5.749116  3.7382793  3.0953173  3.8362252             326             354
## 3  5.312408  3.3727669  3.0522169  2.3409093             187             220
## 4  3.618301  6.1230168  6.1172944  6.1594904              53              42
## 5  6.217810  3.5791361  3.7361493  3.5986428             396             490
## 6  2.067847  0.6756912  0.3237122  0.3460562              26              17
##   SK066_rawcounts SK079_rawcounts SK080_rawcounts SK081_rawcounts locusId
## 1            7535           29906           21599           21957 2194915
## 2             248              62              30              49 2195081
## 3             182              47              29              15 2195083
## 4              53             345             272             260 2195152
## 5             345              55              49              41 2195337
## 6              15               3               1               1 1544111
##     accession        GI scaffoldId    stop
## 1 YP_788499.1 116054056       4582  384875
## 2 YP_788665.1 116054221       4582  565457
## 3 YP_788667.1 116054223       4582  567169
## 4 YP_788736.1 116054407       4582  632008
## 5 YP_788921.1 116052235       4582  829037
## 6                    NA       4582 1244743
##                                           desc     COG COGFun
## 1                  hypothetical protein (NCBI) COG3422      S
## 2   putative lactam utilization protein (NCBI) COG1540      R
## 3 putative acyl-CoA carboxylase subunit (NCBI)  COG439      I
## 4                  hypothetical protein (NCBI)  COG599      S
## 5           putative AMP-binding enzyme (NCBI)  COG318     IQ
## 6                              tRNA-Leu (NCBI)               
##                                                                       COGDesc
## 1                                           Uncharacterized conserved protein
## 2          Uncharacterized proteins, homologs of lactam utilization protein B
## 3                                                          Biotin carboxylase
## 4 Uncharacterized homolog of gamma-carboxymuconolactone decarboxylase subunit
## 5                      Acyl-CoA synthetases (AMP-forming)/AMP-acid ligases II
## 6                                                                            
##                                                  TIGRFam
## 1                                                       
## 2                                                       
## 3                                                       
## 4 TIGR00778 alkylhydroperoxidase AhpD family core domain
## 5                                                       
## 6                                                       
##                  TIGRRoles
## 1                         
## 2                         
## 3                         
## 4 Unknown function:General
## 5                         
## 6                         
##                                                       GO       EC
## 1                                                                
## 2                                  GO:0005975,GO:0003824         
## 3 GO:0008152,GO:0009343,GO:0004075,GO:0009374,GO:0005524 6.3.4.14
## 4                                                                
## 5                                  GO:0008152,GO:0003824  6.2.1.-
## 6                                                                
##                ECDesc direction
## 1                            up
## 2                          down
## 3 Biotin carboxylase.      down
## 4                            up
## 5                          down
## 6                          down
write.csv(sig_genes, paste0(Sys.Date(),"_significantgenes_", exp, "_", treatment,".vs.", control,".csv"), row.names = FALSE)

10 PCA plot

vst <- DESeqDataSetFromMatrix(countData = rawcounts, colData = metadata, design = ~ exp_6 + batch)
## Warning in DESeqDataSet(se, design = design, ignoreRank): some variables in
## design formula are characters, converting to factors
# Variance stabilizing transformations
vsd <- vst(vst, blind = TRUE)

# PCA plot
pcaData <- plotPCA(vsd, intgroup = c("exp_6", "batch", "condition"), returnData = TRUE)
## using ntop=500 top features by variance
percentVar <- round(100 * attr(pcaData, "percentVar"))

# Calculate the maximum absolute value among PC1 and PC2
max_abs_val <- max(c(abs(min(pcaData$PC1)), abs(min(pcaData$PC2)), abs(max(pcaData$PC1)), abs(max(pcaData$PC2))))

axis_size <- 10
theme_set(theme_minimal(base_family = "Arial"))

pca <- ggplot(pcaData, aes(PC1, PC2, color = condition, shape = condition)) +
  geom_point(size = 3) +
  xlab(paste0("PC1: ", percentVar[1], "% variance")) +
  ylab(paste0("PC2: ", percentVar[2], "% variance")) +
  scale_colour_brewer(palette = "Dark2") +
  scale_shape_manual(values = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)) +
  coord_fixed(ratio = 1, xlim = c(-max_abs_val, max_abs_val), ylim = c(-max_abs_val, max_abs_val)) +
  labs(color = "condition", shape = "condition") +
  guides(shape = guide_legend(title = "Condition"),  # Adjust size of shape legend
    color = guide_legend(title = "Condition")) +
  theme(
    panel.grid = element_blank(),
    panel.background = element_blank(),
    axis.text = element_text(size = axis_size),
    axis.ticks = element_line(linewidth = 0.2),
     axis.line = element_line(linewidth = 0, color = "black"),  # Set the axis line linewidth
   panel.border = element_rect(fill = NA, linewidth = 0.5),  # Set the panel border linewidth
  legend.key = element_rect(fill = "white", color = NA)  # Set legend key background to white and remove border
  )

print(pca)

cairo_pdf(paste0(Sys.Date(),"_pca_",exp, "_", treatment,".vs.", control,".pdf", sep = ""))
pca
dev.off()
## quartz_off_screen 
##                 2

11 Volcano plot

sequence <- c("treatment")

for (i in sequence) {
    set.seed(0)
    res <- results(dds_final, contrast = c("exp_6", i, "control"))

  gp2 <- wes_palettes$Zissou1
  key <- read.csv("../../raw-data/pa14_gene_key.csv",  header = TRUE)

  rownames(key) <- key$gene_id

  res <- merge(key, as.data.frame(res), by=0)
  res <- as.data.frame(res)
  res$Alias <- rownames(res)

 # Define gene list
  alg_genes <- c(
    "algA", "algF", "algJ", "algI", "algL", "algX", "algG", "algE",
    "algK", "alg44", "alg8", "algD", "mucC", "mucB", "algU", "algW",
    "algP", "algQ", "algR", "algZ", "algC", "algB"
  )

logfc_cutoff
keyvals <- ifelse(
 res$log2FoldChange <= -logfc_cutoff & res$padj <= pval_cutoff, gp2[1],
  ifelse(res$log2FoldChange >= logfc_cutoff & res$padj <= pval_cutoff, gp2[5],
         'lightgrey'))
keyvals[is.na(keyvals)] <- 'lightgrey'
names(keyvals)[keyvals == gp2[5]] <- 'Up-regulated'
names(keyvals)[keyvals == 'lightgrey'] <- 'NS'
names(keyvals)[keyvals == gp2[1]] <- 'Down-regulated'

volcano <- EnhancedVolcano(res,
                     lab = res[["name"]],
                     selectLab = alg_genes,
                     x = 'log2FoldChange',
                     y = 'padj',
                     xlab = bquote(~Log[2]~ 'fold change'),
                     pCutoff = pval_cutoff,
                     FCcutoff = logfc_cutoff,
                     cutoffLineType = "dashed",
                     pointSize = 1,
                     labSize = 3.0,
                     axisLabSize = 14,
                     labCol = 'black',
                     labFace = 'bold',
                     #col = c('grey', gp2[2], gp2[3], gp2[1]),
                     colCustom = keyvals,
                     colAlpha = 5/5,
                     legendPosition = 'bottom',
                     legendLabSize = 12,
                     legendIconSize = 4.0,
                     drawConnectors = TRUE,
                     arrowheads = FALSE,
                     widthConnectors = 0.2,
                     gridlines.major = FALSE,
                     borderWidth = 0.3,
                     gridlines.minor = FALSE,
                     title = paste0(treatment," vs ", control, sep = ""),
                     subtitle = "",
                     #caption = paste0("total = ", nrow(toptable), " variables"),
                     caption = paste0("Volcano plot with log2 FC of ", logfc_cutoff," and P value of ",pval_cutoff, "."),
                     max.overlaps = 30,
                     #ylim = c(0,10),
                     colConnectors = 'black') + 
      theme(axis.ticks=element_line(linewidth =0.2)) # +
 # scale_x_continuous(breaks = c(-5, -2.5, 0, 2.5, 5), limits = c(-6,6))

print(volcano)

cairo_pdf(paste0(Sys.Date(),"_volcano_", exp, "_", treatment,".vs.", control,".pdf", sep = ""))
print(volcano)
dev.off()
}

12 MA plot

sequence <- c("treatment")

for (i in sequence) {
    set.seed(0)

res <- results(dds_final, contrast = c("exp_6", i, "control"))

gp2 <- wes_palettes$Zissou1

res$gene_id <- rownames(res)
res <- as.data.frame(res)
head(res)
res <- full_join(key, as.data.frame(res), by="gene_id")
rownames(res) <- res$Alias

any(is.na(res))  # Check if there are any NAs

res <- res %>% filter(!is.na(baseMean))


ma <- ggmaplot(res, 
               fdr = pval_cutoff, 
               fc = 2^(logfc_cutoff), 
               size = 1,
               palette = c((gp2[5]), (gp2[1])),
               select.top.method = "fc",
             #  ylim = c(-15,15),
               legend = "bottom", 
               title = paste0(treatment," vs ", control, sep = ""),
              subtitle = paste0("Volcano plot with log2 FC of ", logfc_cutoff," and P value of ",pval_cutoff, "."),
               font.label = c( 12), 
             label.rectangle = FALSE,
              genenames = res$name,
              font.legend = c(12),
               font.main = c("bold", 14),
               alpha = 1.5,
               ggtheme = ggplot2::theme(panel.grid =element_blank(),
                                        axis.text = element_text(size = 12),
                                        axis.title = element_text(size = 14),
                                        panel.background = element_blank(),
                                        panel.border = element_rect(fill = NA))) 
print(ma)

cairo_pdf(paste0(Sys.Date(),"_ma_", exp, "_", treatment,".vs.", control,".pdf"))
print(ma)
dev.off()
}

LS0tCnRpdGxlOiAiMjAyNV9leHBfNl9hbGdpbmF0ZV9ERUciCmF1dGhvcjogIk5vdXIgRWwgSHVzc2VpbmkiCmRhdGU6ICIyMDI1IgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19jb2xsYXBzZWQ6IGZhbHNlICAjIEVuc3VyZXMgVE9DIGlzIGV4cGFuZGVkIGJ5IGRlZmF1bHQKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGhpZ2hsaWdodDoga2F0ZQogICAgdGhlbWU6CiAgICAgIGJvb3Rzd2F0Y2g6IHplcGh5cgogICAgY3NzOiBzdHlsZS5jc3MgICMgTGluayB0byB5b3VyIGN1c3RvbSBDU1MgZmlsZQplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKICBtYXJrZG93bjogCiAgICB3cmFwOiA3MgotLS0KCgpgYGB7ciBsb2FkX2xpYnJhcmllcywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSgiREVTZXEyIikKbGlicmFyeSgiZ2dwbG90MiIpCmxpYnJhcnkoImthYmxlRXh0cmEiKQpsaWJyYXJ5KCJkcGx5ciIpCmxpYnJhcnkoImdnZm9yY2UiKQpsaWJyYXJ5KCJSQ29sb3JCcmV3ZXIiKQpsaWJyYXJ5KCJwaGVhdG1hcCIpCmxpYnJhcnkoIndlc2FuZGVyc29uIikKbGlicmFyeSgiRW5oYW5jZWRWb2xjYW5vIikKbGlicmFyeSgiZ2dwdWJyIikKbGlicmFyeSgiaHBnbHRvb2xzIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJ0aWJibGUiKSAKbGlicmFyeSgiZWRnZVIiKQpsaWJyYXJ5KCJnZW5lZmlsdGVyIikKbGlicmFyeSgicGhlYXRtYXAiKQpsaWJyYXJ5KCJkcGx5ciIpCmxpYnJhcnkoInRpZHl2ZXJzZSIpCmxpYnJhcnkoIkRFU2VxMiIpCmxpYnJhcnkoIkNvbXBsZXhIZWF0bWFwIikKbGlicmFyeSgiZ29zZXEiKQpsaWJyYXJ5KCJwbHlyIikKbGlicmFyeSgiZ2VvbXRleHRwYXRoIikKYGBgCgojIE92ZXJ2aWV3CgpgYGB7ciBzYW1wbGVfdGFibGUsIGVjaG89RkFMU0V9CiMgTG9hZCBtZXRhZGF0YSBDU1YgZmlsZSBpbnRvIGEgZGF0YWZyYW1lLCB1c2luZyB0aGUgZmlyc3QgY29sdW1uIGFzIHJvdyBuYW1lcwptZXRhZGF0YSA8LSByZWFkLmNzdigiLi4vLi4vcmF3LWRhdGEvbWV0YWRhdGFfYWxnaW5hdGVfdnRsLmNzdiIsIHJvdy5uYW1lcyA9IDEsIGhlYWRlciA9IFRSVUUpCgojIEZpbHRlciB0aGUgZGF0YSB0byBpbmNsdWRlIG9ubHkgcm93cyB3aGVyZSBleHBfNiBpcyBlaXRoZXIgImNvbnRyb2wiIG9yICJ0cmVhdG1lbnQiCiMgVGhlbiByZW1vdmUgb3RoZXIgZXhwZXJpbWVudHMgKGV4cF8yIHRvIGV4cF82KQptZXRhZGF0YSA8LSBmaWx0ZXIobWV0YWRhdGEsIGV4cF82ICVpbiUgYygiY29udHJvbCIsICJ0cmVhdG1lbnQiKSkgJT4lCiAgICBzZWxlY3QoYmF0Y2gsIGNvbmRpdGlvbiwgbWVkaWEsIHRyZWF0bWVudCwgaW5kdWNlZCwgZXhwXzYpIAoKIyBEaXNwbGF5IHRoZSBjbGVhbmVkIG1ldGFkYXRhIHRhYmxlIHVzaW5nIGtuaXRyOjprYWJsZSBhbmQga2FibGVFeHRyYSBzdHlsaW5nCm1ldGFkYXRhICU+JQogIGtibCgpICU+JSAgIyBDcmVhdGUgYSBiYXNpYyB0YWJsZQogIGthYmxlX2NsYXNzaWMoZnVsbF93aWR0aCA9IFRSVUUpICAjIEFwcGx5IGEgY2xhc3NpYyB0YWJsZSBzdHlsZSB3aXRoIGZ1bGwgd2lkdGgKYGBgIAoKIyBQcm9qZWN0IHZhcmlhYmxlcwpgYGB7ciBwcm9qZWN0X3BhcmFtZXRlcnMsIGVjaG89RkFMU0V9CiMgRGVmaW5lIHRoZSBsYWJlbHMgZm9yIGNvbnRyb2wgYW5kIHRyZWF0bWVudCBncm91cHMgdXNlZCBpbiB0aGUgZXhwZXJpbWVudApoZWFkKG1ldGFkYXRhKQojIEV4dHJhY3QgY29udHJvbCBhbmQgdHJlYXRtZW50IGNvbmRpdGlvbnMgYmFzZWQgb24gYGV4cF82YCBsYWJlbHMKY29udHJvbCA8LSBtZXRhZGF0YVttZXRhZGF0YSRleHBfNiA9PSAiY29udHJvbCIsIF0KdHJlYXRtZW50IDwtIG1ldGFkYXRhW21ldGFkYXRhJGV4cF82ID09ICJ0cmVhdG1lbnQiLCBdCgpjb250cm9sIDwtIHVuaXF1ZShjb250cm9sJGNvbmRpdGlvbikKdHJlYXRtZW50IDwtIHVuaXF1ZSh0cmVhdG1lbnQkY29uZGl0aW9uKQoKcHJpbnQocGFzdGUwKCJUaGUgY29udHJvbCBpczogIiwgY29udHJvbCkpCnByaW50KHBhc3RlMCgiVGhlIHRyZWF0bWVudCBpczogIiwgdHJlYXRtZW50KSkKCiMgU2V0IGRlZmF1bHQgdGV4dCBzaXplcyBmb3IgcGxvdHMKdGV4dC5zaXplIDwtIDEyICAgIApheGlzLnRleHQuc2l6ZSA8LSAxNAoKbG9nZmNfY3V0b2ZmIDwtIDIKcHZhbF9jdXRvZmYgPC0gMC4wMQoKIyBTZXQgdmFyaWFibGVzIGZvciB0aGUgcHJvamVjdCB1c2VkIGluIGZpbGVuYW1lcyBhbmQgcGxvdCB0aXRsZXMKcHJvamVjdCA8LSAib3JuX2FsZ2luYXRlX3JuYXNlcSIKZXhwIDwtICJleHBfNiIgICAgICAgICAgICAgICAgICAgIApgYGAKCmBgYHtyIHJhd2RhdGF9CiMgTG9hZCByYXcgY291bnQgZGF0YQpyYXdjb3VudHMgPC0gcmVhZC5jc3YoIi4uLy4uL3Jhdy1kYXRhL2h0c2VxX1NLX3VuZmlsdGVyZWRfcmV2ZXJzZV9zdHJhbmRfY291bnQuY3N2IiwgCiAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSAxLCBoZWFkZXIgPSBUUlVFKQoKIyBBcHBlbmQgYSBwcmVmaXggdG8gdGhlIGJhdGNoIGFuZCBydW4gY29sdW1ucyB0byB0dXJuIHRvIGNoYXJhY3RlciBjbGFzcwptZXRhZGF0YVtbImJhdGNoIl1dIDwtIHBhc3RlMCgiYiIsIG1ldGFkYXRhW1siYmF0Y2giXV0pCm1ldGFkYXRhW1sicnVuIl1dIDwtIHBhc3RlMCgiciIsIG1ldGFkYXRhW1sicnVuIl1dKQoKIyBTdWJzZXQgdGhlIHJhd2NvdW50cyBkYXRhZnJhbWUgdG8gb25seSBpbmNsdWRlIHNhbXBsZXMgdGhhdCBhcmUgcHJlc2VudCBpbiBleHBlcmltZW50CnNhbXBsZXMgPC0gcm93bmFtZXMobWV0YWRhdGEpCnJhd2NvdW50cyA8LSBzZWxlY3QocmF3Y291bnRzLCBhbGxfb2Yoc2FtcGxlcykpCgojIEVuc3VyZSB0aGF0IHRoZSBvcmRlciBvZiBzYW1wbGVzIGluIG1ldGFkYXRhIG1hdGNoZXMgdGhlIG9yZGVyIG9mIGNvbHVtbnMgaW4gcmF3Y291bnRzCmFsbChyb3duYW1lcyhtZXRhZGF0YSkgPT0gY29sbmFtZXMocmF3Y291bnRzKSkgICMgU2hvdWxkIHJldHVybiBUUlVFIGlmIG9yZGVyIGlzIGNvcnJlY3QKCiMgRGVmaW5lIHRoZSBkZXNpZ24gZm9ybXVsYSBmb3IgREVTZXEyLCBpbmNsdWRpbmcgbWFpbiBjb25kaXRpb24gYW5kIGJhdGNoIGVmZmVjdApkZXNpZ25fZm9ybXVsYSA8LSB+IGV4cF82ICsgYmF0Y2gKCiMgQ3JlYXRlIERFU2VxMiBkYXRhc2V0IG9iamVjdCBmcm9tIHRoZSBmaWx0ZXJlZCBjb3VudCBtYXRyaXggYW5kIG1ldGFkYXRhCmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KAogIGNvdW50RGF0YSA9IHJhd2NvdW50cywKICBjb2xEYXRhID0gbWV0YWRhdGEsCiAgZGVzaWduID0gZGVzaWduX2Zvcm11bGEKKQpgYGAKCgojIExpYnJhcnkgc2l6ZSBwZXIgc2FtcGxlCmBgYHtyIGxpYnJhcnlfc2l6ZX0KIyBTdW0gdXAgdGhlIGNvdW50cyBmb3IgZWFjaCBzYW1wbGUKcmF3Y291bnRzX3N1bXMgPC0gY29sU3VtcyhyYXdjb3VudHMpCgojIFR1cm4gaXQgaW50byBhIGRhdGEgZnJhbWUKZGF0YSA8LSBkYXRhLmZyYW1lKAogIENhdGVnb3J5ID0gbmFtZXMocmF3Y291bnRzX3N1bXMpLAogIENvdW50ID0gYXMubnVtZXJpYyhyYXdjb3VudHNfc3VtcykKKQoKIyBNYWtlIHN1cmUgc2FtcGxlIG9yZGVyIGlzIGNvbnNpc3RlbnQKZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZShDYXRlZ29yeSA9IGZhY3RvcihDYXRlZ29yeSwgbGV2ZWxzID0gc29ydCh1bmlxdWUoQ2F0ZWdvcnkpKSkpCgojIFBsb3QgYmFyIGNoYXJ0IG9mIGxpYnJhcnkgc2l6ZXMKcCA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHggPSBDYXRlZ29yeSwgeSA9IENvdW50LCBmaWxsID0gQ2F0ZWdvcnkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAjIGNvb3JkX2ZsaXAoKSAjIGZsaXAgaWYgdG9vIG1hbnkgc2FtcGxlcyB0byByZWFkIGxhYmVscyBlYXNpbHkKICBsYWJzKHkgPSAiTGlicmFyeSBzaXplIChNKSIsIHggPSBOVUxMKSArICAjIHJlbW92ZSB4IGxhYmVsLCByZW5hbWUgeSBheGlzCiAgIyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKyAgIyBvcHRpb25hbCBjb2xvciBwYWxldHRlCiAgc2NhbGVfeV9jb250aW51b3VzKAogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoc2NhbGUgPSAxZS02KSwgICMgc2hvdyBjb3VudHMgaW4gbWlsbGlvbnMKICAgIGxpbWl0cyA9IGMoMCwgKG1heChkYXRhJENvdW50KSArIDFlNikpICAgICAgICAjIGFkZCBhIGJpdCBvZiBzcGFjZSBvbiB0b3AKICApICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0LnNpemUsIGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksICAjIHNsYW50IGxhYmVscwogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYXhpcy50ZXh0LnNpemUpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHRleHQuc2l6ZSksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGF4aXMudGV4dC5zaXplKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAgIyBubyBsZWdlbmQgbmVlZGVkIHNpbmNlIGVhY2ggYmFyIGlzIGEgZGlmZmVyZW50IHNhbXBsZQogICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShsaW5ld2lkdGggPSAwLjIpLAogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgU2hvdyB0aGUgcGxvdApwCgojIFNhdmUgdGhlIHBsb3QgYXMgYSBQREYgd2l0aCB0b2RheeKAmXMgZGF0ZSBhbmQgcHJvamVjdCBuYW1lCmdnc2F2ZShwYXN0ZTAoU3lzLkRhdGUoKSwgIl9saWJyYXJ5X3NpemVfIiwgZXhwLCAiXyIsIHRyZWF0bWVudCwiLnZzLiIsIGNvbnRyb2wsICIucGRmIiksIGRldmljZSA9ICJwZGYiKQpgYGAKCiMgRXhwcmVzc2lvbiBkaXN0cmlidXRpb24KCmBgYHtyIGV4cHJlc3Npb25fZGlzdHJpYnV0aW9ufQoKIyBTdGFjayByYXdjb3VudHMgaW50byBzaW5nbGUgdmVjdG9yIApkYXQgPC0gc3RhY2socmF3Y291bnRzKQoKIyBGb3JtYXQgZXhwcmVzc2lvbiBkaXN0cmlidXRpb24gcGxvdCB3aXRoIHRoZSBleHByZXNzaW9uIGxldmVsIGFuZCBkZW5zaXR5IApleHByZXNzaW9uX2Rpc3QgPC0gZ2dwbG90KGRhdCwgYWVzKHggPSBsb2cyKHZhbHVlcysxKSwgIGZpbGw9aW5kLCBsYWJlbCA9IGluZCApKSArIAogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSwgcG9zaXRpb24gPSAiaWRlbnRpdHkiKSArIAogIHlsYWIoIkRlbnNpdHkiKSArIAogIGdlb21fdGV4dGRlbnNpdHkoaGp1c3QgPSAieW1heCIsIHZqdXN0ID0gMCwKICAgICAgICAgICB0ZXh0X29ubHkgPSBUUlVFLCB0ZXh0X3Ntb290aGluZyA9IDIwKSArIAogICAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gdGV4dC5zaXplKSwKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBheGlzLnRleHQuc2l6ZSksCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHRleHQuc2l6ZSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBheGlzLnRleHQuc2l6ZSksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUobGluZXdpZHRoID0gMC4yKSwKICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDE1KSkKCmV4cHJlc3Npb25fZGlzdAoKI3NhdmUgZmlndXJlCmNhaXJvX3BkZihwYXN0ZTAoU3lzLkRhdGUoKSwgIl9leHByZXNzaW9uX2Rpc3RfIiwgZXhwLCAiXyIsIHRyZWF0bWVudCwgIi52cy4iLCBjb250cm9sLCAiLnBkZiIpKQpleHByZXNzaW9uX2Rpc3QKZGV2Lm9mZigpIAoKYGBgCgojIE5vbi16ZXJvIGdlbmVzIG9ic2VydmVkCgpgYGB7ciBub24temVyb19nZW5lc30KIyBQcmVwYXJlIGRhdGEgYnkgZ2V0dGluZyBsaWJyYXJ5IHNpemVzIGFuZCBub24temVybyBjb3VudHMKeCA8LSBjb2xTdW1zKHJhd2NvdW50cykKeSA8LSBjb2xTdW1zKHJhd2NvdW50cyAhPSAwKSAKZGYgPC0gZGF0YS5mcmFtZSh4LHkpCmRmJGluZCA8LSByb3duYW1lcyhkZikKCiMgQ2FsY3VsYXRlIGF4aXMgbGltaXRzCnhfbWluIDwtIG1pbihkZiR4KQp4X21heCA8LSBtYXgoZGYkeCkKeV9taW4gPC0gbWluKGRmJHkpCnlfbWF4IDwtIG1heChkZiR5KQoKIyBOb24temVybyBwbG90Cm5vbnplcm8gPC0gZ2dwbG90KGRhdGEgPSBkZiwgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSBpbmQsIGxhYmVsID0gaW5kKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsKICBnZW9tX3RleHQoaGp1c3QgPSAtMC4xLCB2anVzdCA9IC0wLjEsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDUpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoeV9taW4sIHlfbWF4KSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICBsaW1pdHMgPSBjKHhfbWluLTFlMywgeF9tYXgrOWU1KSwKICAgIGxhYmVscyA9IHNjYWxlczo6Y29tbWFfZm9ybWF0KHNjYWxlID0gMWUtNiwgIGFjY3VyYWN5ID0gMSkgICMgRm9ybWF0IGxhYmVscyB3aXRob3V0IGRlY2ltYWxzCiAgKSArCiAgeGxhYigiTWlsbGlvbnMgb2YgcmVhZHMiKSArIHlsYWIoIk51bWJlciBvZiBub24temVybyBnZW5lcyBvYnNlcnZlZCIpICsKICBsYWJzKGNvbG9yID0gIlNhbXBsZSIpICsgCiAgICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0LnNpemUpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGF4aXMudGV4dC5zaXplKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gdGV4dC5zaXplKSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGF4aXMudGV4dC5zaXplKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShsaW5ld2lkdGggPSAwLjIpLAogICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBjb29yZF9jYXJ0ZXNpYW4oKQoKIyBTaG93IG5vbnplcm8gcGxvdApub256ZXJvCgojIFNhdmUgcGxvdAoKY2Fpcm9fcGRmKHBhc3RlMChTeXMuRGF0ZSgpLCAiX25vbi16ZXJvXyIsIGV4cCwgIl8iLCB0cmVhdG1lbnQsICIudnMuIiwgY29udHJvbCwgIi5wZGYiKSkKbm9uemVybwpkZXYub2ZmKCkgCgpgYGAKCiMgUlBLTSBhbmQgQ1BNIHRyYW5zZm9ybWF0aW9ucwpgYGB7ciBkYXRhX3RyYW5zZm9ybWF0aW9uc30KIyBMb2FkIEdGRiBhbm5vdGF0aW9uIApnZmZfYW5ub3QgPC0gbG9hZF9nZmZfYW5ub3RhdGlvbnMoIi4uLy4uL3Jhdy1kYXRhL3BhZXJ1Z2lub3NhX3BhMTQuZ2ZmIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZF9jb2wgPSAiZ2VuZV9pZCIsIHR5cGUgPSAiZ2VuZSIpCnJvd25hbWVzKGdmZl9hbm5vdCkgPC0gZ2ZmX2Fubm90JGdlbmVfaWQKCmhlYWQoZ2ZmX2Fubm90KQpoZWFkKHJhd2NvdW50cykKZGltKGdmZl9hbm5vdCkKZGltKHJhd2NvdW50cykKCnN1bW1hcnkocm93bmFtZXMoZ2ZmX2Fubm90KSA9PSByb3duYW1lcyhyYXdjb3VudHMpKQpnZmZfYW5ub3QgPC0gZ2ZmX2Fubm90W3Jvd25hbWVzKHJhd2NvdW50cyksXQpzdW1tYXJ5KHJvd25hbWVzKGdmZl9hbm5vdCkgPT0gcm93bmFtZXMocmF3Y291bnRzKSkKCgojIENyZWF0ZSBhbiBleHByZXNzaW9uIG9iamVjdCB3aXRoIGNvdW50cywgbWV0YWRhdGEsIGFuZCBnZW5lIGluZm8KZXhwdCA8LSBjcmVhdGVfZXhwdChjb3VudF9kYXRhZnJhbWUgPSByYXdjb3VudHMsCiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEgPSBtZXRhZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgZ2VuZV9pbmZvID0gZ2ZmX2Fubm90KQoKIyBOb3JtYWxpemUgY291bnRzIGxvZzIgQ1BNCmNwbV9ub3JtYWxpemVkX2V4cCA8LSBub3JtYWxpemVfZXhwdChleHB0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gInJhdyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydCA9ICJjcG0iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd19taW4gPSAiMTAiKQoKIyMjIyMjIyBDYWxjdWxhdGUgUlBLTSAjIyMjIyMjIwoKIyBHcmFiIGdlbmUgbGVuZ3RocyBmcm9tIEdGRiAoc2hvdWxkIGJlIGluIGJhc2UgcGFpcnMpCmdlbmVfbGVuZ3RocyA8LSBnZmZfYW5ub3Qkd2lkdGggIApuYW1lcyhnZW5lX2xlbmd0aHMpIDwtIHJvd25hbWVzKGdmZl9hbm5vdCkgICMgc2V0IGdlbmUgbmFtZXMKCiMgTWFrZSBzdXJlIGdlbmVfbGVuZ3RocyBhcmUgaW4gdGhlIHNhbWUgb3JkZXIgYXMgcmF3Y291bnRzIHJvd3MKZ2VuZV9sZW5ndGhzIDwtIGdlbmVfbGVuZ3Roc1tyb3duYW1lcyhyYXdjb3VudHMpXQoKIyBNYWtlIERHRUxpc3Qgb2JqZWN0IGZvciBlZGdlUgpkZ2UgPC0gREdFTGlzdChjb3VudHMgPSByYXdjb3VudHMpCgojIENhbGN1bGF0ZSBSUEtNIChyZWFkcyBwZXIga2lsb2Jhc2UgcGVyIG1pbGxpb24pCnJwa20gPC0gcnBrbShkZ2UsIGdlbmUubGVuZ3RoID0gZ2VuZV9sZW5ndGhzKQoKIyBXcmFwIFJQS00gaW4gYW4gZXhwZXJpbWVudCBvYmplY3QgdG9vCmV4cHRfcnBrbSA8LSBjcmVhdGVfZXhwdChjb3VudF9kYXRhZnJhbWUgPSBycGttLAogICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEgPSBtZXRhZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm8gPSBnZmZfYW5ub3QpCgojIGxvZzIgdHJhbnNmb3JtIHRoZSBSUEtNIChhZ2Fpbiwgbm8gbm9ybWFsaXphdGlvbiBiZXlvbmQgbG9nKQpycGttX25vcm1hbGl6ZWRfZXhwIDwtIG5vcm1hbGl6ZV9leHB0KGV4cHRfcnBrbSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gInJhdyIpCgojIEdldCB0aGUgYWN0dWFsIGV4cHJlc3Npb24gbWF0cmljZXMgZnJvbSB0aGUgZXhwZXJpbWVudCBvYmplY3RzCnJwa20gPC0gZXhwcnMocnBrbV9ub3JtYWxpemVkX2V4cCkKY3BtIDwtIGV4cHJzKGNwbV9ub3JtYWxpemVkX2V4cCkKCiMgTWVyZ2UgQ1BNIGFuZCBSUEtNIG1hdHJpY2VzIHdpdGggZ2VuZSBhbm5vdGF0aW9uIGluZm8KY3BtX2Fubm90YXRlZCA8LSBtZXJnZShnZmZfYW5ub3QsIGNwbSwgYnkgPSAwKQpycGttX2Fubm90YXRlZCA8LSBtZXJnZShnZmZfYW5ub3QsIHJwa20sIGJ5ID0gMCkKYGBgCgojIyBIZWF0bWFwIG9mIGFsZ2luYXRlIGdlbmVzClRoaXMgZ2VuZXJhdGVzIGEgc21hbGwgaGVhdG1hcCBvZiB0aGUgYWxnaW5hdGUgZ2VuZXMgYWNyb3NzIHNhbXBsZXMgdG8gdmlzdWFsaXplIGV4cHJlc3Npb24uCgpgYGB7ciBoZWF0bWFwc30KIyBMb29wIHRocm91Z2ggQ1BNIGFuZCBSUEtNIHRvIHBsb3QgYm90aCBoZWF0bWFwcwpmb3IgKHR5cGUgaW4gYygiY3BtIiwgInJwa20iKSkgewogIAogICMgRGVmaW5lIGdlbmUgbGlzdAogIGFsZ19vcGVyb25fZ2VuZXMgPC0gYygKICAgICJhbGdBIiwgImFsZ0YiLCAiYWxnSiIsICJhbGdJIiwgImFsZ0wiLCAiYWxnWCIsICJhbGdHIiwgImFsZ0UiLAogICAgImFsZ0siLCAiYWxnNDQiLCAiYWxnOCIsICJhbGdEIiwgIm11Y0MiLCAibXVjQiIsICJhbGdVIiwgImFsZ1ciLAogICAgImFsZ1AiLCAiYWxnUSIsICJhbGdSIiwgImFsZ1oiLCAiYWxnQyIsICJhbGdCIgogICkKCiAgIyBHZXQgdGhlIHJpZ2h0IGRhdGEgcGVyIHR5cGUgb2YgdHJhbnNmb3JtYXRpb24KICBkYXRhX2Fubm90IDwtIGdldChwYXN0ZTAodHlwZSwgIl9hbm5vdGF0ZWQiKSkKICAKICAjIEZpeCByb3duYW1lcyB1c2luZyBnZW5lIG5hbWUgKG1ha2UgdW5pcXVlKQogIHJvd25hbWVzKGRhdGFfYW5ub3QpIDwtIG1ha2UubmFtZXMoZGF0YV9hbm5vdCRuYW1lLCB1bmlxdWUgPSBUUlVFKQogIAogICMgRHJvcCB1bmRlc2lyZWQgbWV0YWRhdGEgY29sdW1ucwogIGNvbHNfdG9fZXhjbHVkZSA8LSBjKCJSb3cubmFtZXMiLCJzZXFuYW1lcyIsInN0YXJ0IiwiZW5kIiwid2lkdGgiLAogICAgICAgICAgICAgICAgICAgICAgICJzdHJhbmQiLCJzb3VyY2UiLCJ0eXBlIiwic2NvcmUiLCJwaGFzZSIsCiAgICAgICAgICAgICAgICAgICAgICAgImdlbmVfaWQiLCJOYW1lIiwiRGJ4cmVmIiwiQWxpYXMiLCJuYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAiUGFyZW50IiwibG9jdXMiKQogIGtlZXAgPC0gIW5hbWVzKGRhdGFfYW5ub3QpICVpbiUgY29sc190b19leGNsdWRlCiAgZXhwcl9kYXRhIDwtIGRhdGFfYW5ub3RbLCBrZWVwXQogIAogICMgRXh0cmFjdCBtYXRyaXggZm9yIGFsZyBnZW5lcwogIGFsZ19nZW5lcyA8LSBleHByX2RhdGFbYWxnX29wZXJvbl9nZW5lcywgLCBkcm9wID0gRkFMU0VdCiAgbWF0IDwtIGFsZ19nZW5lcyAtIHJvd01lYW5zKGFsZ19nZW5lcykKICAKICAjIFB1bGwgc2FtcGxlIGFubm90YXRpb25zCiAgYW5ubyA8LSBhcy5kYXRhLmZyYW1lKG1ldGFkYXRhWywgYygiY29uZGl0aW9uIiwgImluZHVjZWQiKV0pCiAgY29sbmFtZXMoYW5ubykgPC0gYygiQ29uZGl0aW9uIiwgIkluZHVjZWQiKQogIAogICMgQ29sb3Igc2V0dGluZ3MgZm9yIGFubm90YXRpb24KICMgYW5uX2NvbG9ycyA8LSBsaXN0KAogIyAgQ29uZGl0aW9uID0gYygiTEItRE1TTyIgPSAiI0Q5NUYwMiIsICJMQi1JUFRHIiA9ICIjNjZBNjFFIiksCiAjICBJbmR1Y2VkID0gYygibm8iID0gImxpZ2h0Z3JleSIsICJ5ZXMiID0gImdyYXkyNyIpCiAjICkKICAKICAjIFNjYWxlIGRhdGEgYnkgcm93IChaLXNjb3JlIHBlciBnZW5lKQogIHNjYWxlZF9tYXQgPC0gdChzY2FsZSh0KG1hdCkpKQoKICAjIEJ1aWxkIGhlYXRtYXAKICBodCA8LSBIZWF0bWFwKAogICAgc2NhbGVkX21hdCwKICAgIG5hbWUgPSAiWi1zY29yZSIsCiAgICB0b3BfYW5ub3RhdGlvbiA9IEhlYXRtYXBBbm5vdGF0aW9uKGRmID0gYW5ubyMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjY29sID0gYW5uX2NvbG9ycwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgIGNsdXN0ZXJfY29sdW1ucyA9IFRSVUUsCiAgICByb3dfbmFtZXNfc2lkZSA9ICJsZWZ0IiwKICAgIGNvbHVtbl9uYW1lc19zaWRlID0gImJvdHRvbSIsCiAgICBjb2x1bW5fbmFtZXNfcm90ID0gNDUsCiAgICByb3dfbmFtZXNfZ3AgPSBncGFyKGZvbnRzaXplID0gMTApLAogICAgY29sdW1uX25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDEwKSwKICAgIHNob3dfcm93X2RlbmQgPSBUUlVFLAogICAgc2hvd19jb2x1bW5fZGVuZCA9IFRSVUUKICApCiAgCiAgIyBEcmF3IGFuZCBzYXZlCiAgZHJhdyhodCkKICAKICBjYWlyb19wZGYocGFzdGUwKFN5cy5EYXRlKCksICJfYWxnX2hlYXRtYXBfIiwgdHlwZSwgIl8iLCBleHAsICJfIiwgdHJlYXRtZW50LCAiLnZzLiIsIGNvbnRyb2wsICIucGRmIikpCiAgZHJhdyhodCkKICBkZXYub2ZmKCkKfQoKYGBgCgojIERFU2VxCmBgYHtyIERFU2VxfQojIENyZWF0ZSBERVNlcURhdGFTZXQKZGRzIDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoCiAgY291bnREYXRhID0gcmF3Y291bnRzLAogIGNvbERhdGEgPSBtZXRhZGF0YSwKICBkZXNpZ24gPSBkZXNpZ25fZm9ybXVsYQopCgojIENoZWNrIG51bWJlciBvZiBnZW5lcyBiZWZvcmUgZmlsdGVyaW5nCnByaW50KCJOdW1iZXIgb2YgZ2VuZXMgYmVmb3JlIGZpbHRlcmluZzoiKQpucm93KGRkcykKCiMgRmlsdGVyOiBrZWVwIGdlbmVzIHdpdGggY291bnRzID49MTAgaW4gYXQgbGVhc3QgMiBzYW1wbGVzCnByaW50KCJGaWx0ZXJpbmcgZ2VuZXMgd2l0aCBjb3VudHMgPj0xMCBpbiBhdCBsZWFzdCAyIHNhbXBsZXMiKQprZWVwIDwtIHJvd1N1bXMoY291bnRzKGRkcykgPj0gMTApID49IDIgCmRkc19maWx0ZXJlZCA8LSBkZHNba2VlcCwgXQoKIyBDaGVjayBudW1iZXIgb2YgZ2VuZXMgYWZ0ZXIgZmlsdGVyaW5nCnByaW50KCJOdW1iZXIgb2YgZ2VuZXMgYWZ0ZXIgZmlsdGVyaW5nOiIpCm5yb3coZGRzX2ZpbHRlcmVkKQoKIyBSdW4gREVTZXEgb24gdGhlIGZpbHRlcmVkIGRhdGFzZXQKZGRzX2ZpbmFsIDwtIERFU2VxKGRkc19maWx0ZXJlZCkKCiMgU2hvdyBhdmFpbGFibGUgcmVzdWx0cwpyZXN1bHRzTmFtZXMoZGRzX2ZpbmFsKQoKIyBQbG90IGRpc3BlcnNpb24gZXN0aW1hdGVzCnBsb3REaXNwRXN0cyhkZHNfZmluYWwpCmBgYAoKIyBTYXZlIERFIHRhYmxlcyAKYGBge3Igc2F2ZV90YWJsZXN9CnJlcyA8LSByZXN1bHRzKGRkc19maW5hbCwgY29udHJhc3QgPSBjKCJleHBfNiIsICJ0cmVhdG1lbnQiLCAiY29udHJvbCIpKQpyZXNkZiA8LSBhcy5kYXRhLmZyYW1lKHJlcykKcmVzZGYkZ2VuZV9pZCA8LSByb3duYW1lcyhyZXNkZikKCmNwbSA8LSBhcy5kYXRhLmZyYW1lKGNwbSkKcnBrbSA8LSBhcy5kYXRhLmZyYW1lKHJwa20pCgojIGFwcGVuZCB0eXBlIG9mIHZhbHVlIHRvIHRoZSBkYXRhZnJhbWUgICAKY29sbmFtZXMocnBrbSkgPC0gcGFzdGUwKGNvbG5hbWVzKHJwa20pLCAiX3Jwa20iKQpjb2xuYW1lcyhjcG0pIDwtIHBhc3RlMChjb2xuYW1lcyhjcG0pLCAiX2NwbSIpCnJhd2NvdW50czIgPC0gcmF3Y291bnRzCmNvbG5hbWVzKHJhd2NvdW50czIpIDwtIHBhc3RlMChjb2xuYW1lcyhyYXdjb3VudHMyKSwgIl9yYXdjb3VudHMiKQoKIyBlbnN1cmUgY29sdW1uIGdlbmVfaWQgaXMgdGhlcmUKcnBrbSRnZW5lX2lkIDwtIHJvd25hbWVzKHJwa20pCmNwbSRnZW5lX2lkIDwtIHJvd25hbWVzKGNwbSkKcmF3Y291bnRzMiRnZW5lX2lkIDwtIHJvd25hbWVzKHJhd2NvdW50czIpCgpnZmZfYW5ub3QgPC0gZ2ZmX2Fubm90W3Jvd25hbWVzKHJlc2RmKSxdCgpkaW0ocmVzZGYpCiMgbWVyZ2Ugd2l0aCBzaWdnZW5lcwpyZXNkZiA8LSBmdWxsX2pvaW4ocmVzZGYsIGdmZl9hbm5vdCwgYnkgPSAiZ2VuZV9pZCIsIGNvcHkgPSBGQUxTRSkKaGVhZChyZXNkZikKCnBhX2dvIDwtIHJlYWQuY3N2KCIuLi8uLi9yYXctZGF0YS8yMDg5NjNfbWljcm9iZXMub25saW5lLmNzdiIsIGhlYWRlciA9IFRSVUUpCmhlYWQocGFfZ28pCgpjb2xfdG9fcmVtb3ZlIDwtIGludGVyc2VjdChjb2xuYW1lcyhwYV9nbyksY29sbmFtZXMocmVzZGYpKQpjb2xfdG9fcmVtb3ZlIDwtIHNldGRpZmYoY29sX3RvX3JlbW92ZSwgIkFsaWFzIikgIyByZXR1cm5zIGFsbCBleGNlcHQgdGhlIHNlY29uZCB2ZWN0b3IKCnBhX2dvIDwtIHBhX2dvICU+JSBzZWxlY3QoLWFsbF9vZihjb2xfdG9fcmVtb3ZlKSkKCnJlc2RmIDwtIGZ1bGxfam9pbihyZXNkZiwgcnBrbSwgYnkgPSAiZ2VuZV9pZCIsIGNvcHkgPSBGQUxTRSkKcmVzZGYgPC0gZnVsbF9qb2luKHJlc2RmLCBjcG0sIGJ5ID0gImdlbmVfaWQiLCBjb3B5ID0gRkFMU0UpCnJlc2RmIDwtIGZ1bGxfam9pbihyZXNkZiwgcmF3Y291bnRzMiwgYnkgPSAiZ2VuZV9pZCIsIGNvcHkgPSBGQUxTRSkKI3Jlc2RmIDwtIGZ1bGxfam9pbihyZXNkZiwgcGFfZ28sIGJ5ID0gIkFsaWFzIiwgY29weSA9IEZBTFNFKQpyZXNkZiA8LSBtZXJnZShyZXNkZiwgcGFfZ28sIGJ5ID0gIkFsaWFzIiwgY29weSA9IEZBTFNFKQoKaGVhZChyZXNkZikKd3JpdGUuY3N2KHJlc2RmLCBwYXN0ZTAoU3lzLkRhdGUoKSAsICJfcmVzdWx0c18iLGV4cCwgIl8iLCB0cmVhdG1lbnQsIi52cy4iLCBjb250cm9sLCIuY3N2IiksIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMgU2F2ZSBERUcgbGlzdApgYGB7ciBzYXZlX2RlZ30KIyBmaWx0ZXIgZm9yIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIChMRkMgPj0gMywgcGFkaiA8IHB2YWxfY3V0b2ZmKQpkaW0ocmVzZGYpCmhlYWQocmVzZGYpCgpzdW1tYXJ5KGlzLm5hKHJlc2RmJGxvZzJGb2xkQ2hhbmdlKSkKc3VtbWFyeShpcy5uYShyZXNkZiRwYWRqKSkKCnNpZ19nZW5lcyA8LSByZXNkZlthYnMocmVzZGYkbG9nMkZvbGRDaGFuZ2UpID49IGxvZ2ZjX2N1dG9mZiAmIHJlc2RmJHBhZGogPCBwdmFsX2N1dG9mZiwgXSAgJT4lIGRyb3BfbmEobG9nMkZvbGRDaGFuZ2UpCnNpZ19nZW5lcyRkaXJlY3Rpb24gPC0gaWZlbHNlKHNpZ19nZW5lcyRsb2cyRm9sZENoYW5nZSA+IDAsICJ1cCIsICJkb3duIikKCnN1bW1hcnkoaXMubmEoc2lnX2dlbmVzJGxvZzJGb2xkQ2hhbmdlKSkKc3VtbWFyeShpcy5uYShzaWdfZ2VuZXMkcGFkaikpCgpkaW0oc2lnX2dlbmVzKQpoZWFkKHNpZ19nZW5lcykKd3JpdGUuY3N2KHNpZ19nZW5lcywgcGFzdGUwKFN5cy5EYXRlKCksIl9zaWduaWZpY2FudGdlbmVzXyIsIGV4cCwgIl8iLCB0cmVhdG1lbnQsIi52cy4iLCBjb250cm9sLCIuY3N2IiksIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMgUENBIHBsb3QgCmBgYHtyIFBDQX0KdnN0IDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnREYXRhID0gcmF3Y291bnRzLCBjb2xEYXRhID0gbWV0YWRhdGEsIGRlc2lnbiA9IH4gZXhwXzYgKyBiYXRjaCkKCiMgVmFyaWFuY2Ugc3RhYmlsaXppbmcgdHJhbnNmb3JtYXRpb25zCnZzZCA8LSB2c3QodnN0LCBibGluZCA9IFRSVUUpCgojIFBDQSBwbG90CnBjYURhdGEgPC0gcGxvdFBDQSh2c2QsIGludGdyb3VwID0gYygiZXhwXzYiLCAiYmF0Y2giLCAiY29uZGl0aW9uIiksIHJldHVybkRhdGEgPSBUUlVFKQpwZXJjZW50VmFyIDwtIHJvdW5kKDEwMCAqIGF0dHIocGNhRGF0YSwgInBlcmNlbnRWYXIiKSkKCiMgQ2FsY3VsYXRlIHRoZSBtYXhpbXVtIGFic29sdXRlIHZhbHVlIGFtb25nIFBDMSBhbmQgUEMyCm1heF9hYnNfdmFsIDwtIG1heChjKGFicyhtaW4ocGNhRGF0YSRQQzEpKSwgYWJzKG1pbihwY2FEYXRhJFBDMikpLCBhYnMobWF4KHBjYURhdGEkUEMxKSksIGFicyhtYXgocGNhRGF0YSRQQzIpKSkpCgpheGlzX3NpemUgPC0gMTAKdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoYmFzZV9mYW1pbHkgPSAiQXJpYWwiKSkKCnBjYSA8LSBnZ3Bsb3QocGNhRGF0YSwgYWVzKFBDMSwgUEMyLCBjb2xvciA9IGNvbmRpdGlvbiwgc2hhcGUgPSBjb25kaXRpb24pKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKwogIHhsYWIocGFzdGUwKCJQQzE6ICIsIHBlcmNlbnRWYXJbMV0sICIlIHZhcmlhbmNlIikpICsKICB5bGFiKHBhc3RlMCgiUEMyOiAiLCBwZXJjZW50VmFyWzJdLCAiJSB2YXJpYW5jZSIpKSArCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksIDEwLCAxMSwgMTIsIDEzLCAxNCwgMTUsIDE2KSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSwgeGxpbSA9IGMoLW1heF9hYnNfdmFsLCBtYXhfYWJzX3ZhbCksIHlsaW0gPSBjKC1tYXhfYWJzX3ZhbCwgbWF4X2Fic192YWwpKSArCiAgbGFicyhjb2xvciA9ICJjb25kaXRpb24iLCBzaGFwZSA9ICJjb25kaXRpb24iKSArCiAgZ3VpZGVzKHNoYXBlID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpLCAgIyBBZGp1c3Qgc2l6ZSBvZiBzaGFwZSBsZWdlbmQKICAgIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gYXhpc19zaXplKSwKICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUobGluZXdpZHRoID0gMC4yKSwKICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUobGluZXdpZHRoID0gMCwgY29sb3IgPSAiYmxhY2siKSwgICMgU2V0IHRoZSBheGlzIGxpbmUgbGluZXdpZHRoCiAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGxpbmV3aWR0aCA9IDAuNSksICAjIFNldCB0aGUgcGFuZWwgYm9yZGVyIGxpbmV3aWR0aAogIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gTkEpICAjIFNldCBsZWdlbmQga2V5IGJhY2tncm91bmQgdG8gd2hpdGUgYW5kIHJlbW92ZSBib3JkZXIKICApCgpwcmludChwY2EpCgpjYWlyb19wZGYocGFzdGUwKFN5cy5EYXRlKCksIl9wY2FfIixleHAsICJfIiwgdHJlYXRtZW50LCIudnMuIiwgY29udHJvbCwiLnBkZiIsIHNlcCA9ICIiKSkKcGNhCmRldi5vZmYoKQoKYGBgCgojIFZvbGNhbm8gcGxvdApgYGB7ciB2b2xjYW5vfQpzZXF1ZW5jZSA8LSBjKCJ0cmVhdG1lbnQiKQoKZm9yIChpIGluIHNlcXVlbmNlKSB7CiAgICBzZXQuc2VlZCgwKQogICAgcmVzIDwtIHJlc3VsdHMoZGRzX2ZpbmFsLCBjb250cmFzdCA9IGMoImV4cF82IiwgaSwgImNvbnRyb2wiKSkKCiAgZ3AyIDwtIHdlc19wYWxldHRlcyRaaXNzb3UxCiAga2V5IDwtIHJlYWQuY3N2KCIuLi8uLi9yYXctZGF0YS9wYTE0X2dlbmVfa2V5LmNzdiIsICBoZWFkZXIgPSBUUlVFKQoKICByb3duYW1lcyhrZXkpIDwtIGtleSRnZW5lX2lkCgogIHJlcyA8LSBtZXJnZShrZXksIGFzLmRhdGEuZnJhbWUocmVzKSwgYnk9MCkKICByZXMgPC0gYXMuZGF0YS5mcmFtZShyZXMpCiAgcmVzJEFsaWFzIDwtIHJvd25hbWVzKHJlcykKCiAjIERlZmluZSBnZW5lIGxpc3QKICBhbGdfZ2VuZXMgPC0gYygKICAgICJhbGdBIiwgImFsZ0YiLCAiYWxnSiIsICJhbGdJIiwgImFsZ0wiLCAiYWxnWCIsICJhbGdHIiwgImFsZ0UiLAogICAgImFsZ0siLCAiYWxnNDQiLCAiYWxnOCIsICJhbGdEIiwgIm11Y0MiLCAibXVjQiIsICJhbGdVIiwgImFsZ1ciLAogICAgImFsZ1AiLCAiYWxnUSIsICJhbGdSIiwgImFsZ1oiLCAiYWxnQyIsICJhbGdCIgogICkKCmxvZ2ZjX2N1dG9mZgprZXl2YWxzIDwtIGlmZWxzZSgKIHJlcyRsb2cyRm9sZENoYW5nZSA8PSAtbG9nZmNfY3V0b2ZmICYgcmVzJHBhZGogPD0gcHZhbF9jdXRvZmYsIGdwMlsxXSwKICBpZmVsc2UocmVzJGxvZzJGb2xkQ2hhbmdlID49IGxvZ2ZjX2N1dG9mZiAmIHJlcyRwYWRqIDw9IHB2YWxfY3V0b2ZmLCBncDJbNV0sCiAgICAgICAgICdsaWdodGdyZXknKSkKa2V5dmFsc1tpcy5uYShrZXl2YWxzKV0gPC0gJ2xpZ2h0Z3JleScKbmFtZXMoa2V5dmFscylba2V5dmFscyA9PSBncDJbNV1dIDwtICdVcC1yZWd1bGF0ZWQnCm5hbWVzKGtleXZhbHMpW2tleXZhbHMgPT0gJ2xpZ2h0Z3JleSddIDwtICdOUycKbmFtZXMoa2V5dmFscylba2V5dmFscyA9PSBncDJbMV1dIDwtICdEb3duLXJlZ3VsYXRlZCcKCnZvbGNhbm8gPC0gRW5oYW5jZWRWb2xjYW5vKHJlcywKICAgICAgICAgICAgICAgICAgICAgbGFiID0gcmVzW1sibmFtZSJdXSwKICAgICAgICAgICAgICAgICAgICAgc2VsZWN0TGFiID0gYWxnX2dlbmVzLAogICAgICAgICAgICAgICAgICAgICB4ID0gJ2xvZzJGb2xkQ2hhbmdlJywKICAgICAgICAgICAgICAgICAgICAgeSA9ICdwYWRqJywKICAgICAgICAgICAgICAgICAgICAgeGxhYiA9IGJxdW90ZSh+TG9nWzJdfiAnZm9sZCBjaGFuZ2UnKSwKICAgICAgICAgICAgICAgICAgICAgcEN1dG9mZiA9IHB2YWxfY3V0b2ZmLAogICAgICAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IGxvZ2ZjX2N1dG9mZiwKICAgICAgICAgICAgICAgICAgICAgY3V0b2ZmTGluZVR5cGUgPSAiZGFzaGVkIiwKICAgICAgICAgICAgICAgICAgICAgcG9pbnRTaXplID0gMSwKICAgICAgICAgICAgICAgICAgICAgbGFiU2l6ZSA9IDMuMCwKICAgICAgICAgICAgICAgICAgICAgYXhpc0xhYlNpemUgPSAxNCwKICAgICAgICAgICAgICAgICAgICAgbGFiQ29sID0gJ2JsYWNrJywKICAgICAgICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywKICAgICAgICAgICAgICAgICAgICAgI2NvbCA9IGMoJ2dyZXknLCBncDJbMl0sIGdwMlszXSwgZ3AyWzFdKSwKICAgICAgICAgICAgICAgICAgICAgY29sQ3VzdG9tID0ga2V5dmFscywKICAgICAgICAgICAgICAgICAgICAgY29sQWxwaGEgPSA1LzUsCiAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ2JvdHRvbScsCiAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZExhYlNpemUgPSAxMiwKICAgICAgICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsCiAgICAgICAgICAgICAgICAgICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgYXJyb3doZWFkcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjIsCiAgICAgICAgICAgICAgICAgICAgIGdyaWRsaW5lcy5tYWpvciA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICBib3JkZXJXaWR0aCA9IDAuMywKICAgICAgICAgICAgICAgICAgICAgZ3JpZGxpbmVzLm1pbm9yID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gcGFzdGUwKHRyZWF0bWVudCwiIHZzICIsIGNvbnRyb2wsIHNlcCA9ICIiKSwKICAgICAgICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiIiwKICAgICAgICAgICAgICAgICAgICAgI2NhcHRpb24gPSBwYXN0ZTAoInRvdGFsID0gIiwgbnJvdyh0b3B0YWJsZSksICIgdmFyaWFibGVzIiksCiAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSBwYXN0ZTAoIlZvbGNhbm8gcGxvdCB3aXRoIGxvZzIgRkMgb2YgIiwgbG9nZmNfY3V0b2ZmLCIgYW5kIFAgdmFsdWUgb2YgIixwdmFsX2N1dG9mZiwgIi4iKSwKICAgICAgICAgICAgICAgICAgICAgbWF4Lm92ZXJsYXBzID0gMzAsCiAgICAgICAgICAgICAgICAgICAgICN5bGltID0gYygwLDEwKSwKICAgICAgICAgICAgICAgICAgICAgY29sQ29ubmVjdG9ycyA9ICdibGFjaycpICsgCiAgICAgIHRoZW1lKGF4aXMudGlja3M9ZWxlbWVudF9saW5lKGxpbmV3aWR0aCA9MC4yKSkgIyArCiAjIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKC01LCAtMi41LCAwLCAyLjUsIDUpLCBsaW1pdHMgPSBjKC02LDYpKQoKcHJpbnQodm9sY2FubykKCmNhaXJvX3BkZihwYXN0ZTAoU3lzLkRhdGUoKSwiX3ZvbGNhbm9fIiwgZXhwLCAiXyIsIHRyZWF0bWVudCwiLnZzLiIsIGNvbnRyb2wsIi5wZGYiLCBzZXAgPSAiIikpCnByaW50KHZvbGNhbm8pCmRldi5vZmYoKQp9CgpgYGAKCiMgTUEgcGxvdApgYGB7ciBNQV9wbG90fQpzZXF1ZW5jZSA8LSBjKCJ0cmVhdG1lbnQiKQoKZm9yIChpIGluIHNlcXVlbmNlKSB7CiAgICBzZXQuc2VlZCgwKQoKcmVzIDwtIHJlc3VsdHMoZGRzX2ZpbmFsLCBjb250cmFzdCA9IGMoImV4cF82IiwgaSwgImNvbnRyb2wiKSkKCmdwMiA8LSB3ZXNfcGFsZXR0ZXMkWmlzc291MQoKcmVzJGdlbmVfaWQgPC0gcm93bmFtZXMocmVzKQpyZXMgPC0gYXMuZGF0YS5mcmFtZShyZXMpCmhlYWQocmVzKQpyZXMgPC0gZnVsbF9qb2luKGtleSwgYXMuZGF0YS5mcmFtZShyZXMpLCBieT0iZ2VuZV9pZCIpCnJvd25hbWVzKHJlcykgPC0gcmVzJEFsaWFzCgphbnkoaXMubmEocmVzKSkgICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBOQXMKCnJlcyA8LSByZXMgJT4lIGZpbHRlcighaXMubmEoYmFzZU1lYW4pKQoKCm1hIDwtIGdnbWFwbG90KHJlcywgCiAgICAgICAgICAgICAgIGZkciA9IHB2YWxfY3V0b2ZmLCAKICAgICAgICAgICAgICAgZmMgPSAyXihsb2dmY19jdXRvZmYpLCAKICAgICAgICAgICAgICAgc2l6ZSA9IDEsCiAgICAgICAgICAgICAgIHBhbGV0dGUgPSBjKChncDJbNV0pLCAoZ3AyWzFdKSksCiAgICAgICAgICAgICAgIHNlbGVjdC50b3AubWV0aG9kID0gImZjIiwKICAgICAgICAgICAgICMgIHlsaW0gPSBjKC0xNSwxNSksCiAgICAgICAgICAgICAgIGxlZ2VuZCA9ICJib3R0b20iLCAKICAgICAgICAgICAgICAgdGl0bGUgPSBwYXN0ZTAodHJlYXRtZW50LCIgdnMgIiwgY29udHJvbCwgc2VwID0gIiIpLAogICAgICAgICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKCJWb2xjYW5vIHBsb3Qgd2l0aCBsb2cyIEZDIG9mICIsIGxvZ2ZjX2N1dG9mZiwiIGFuZCBQIHZhbHVlIG9mICIscHZhbF9jdXRvZmYsICIuIiksCiAgICAgICAgICAgICAgIGZvbnQubGFiZWwgPSBjKCAxMiksIAogICAgICAgICAgICAgbGFiZWwucmVjdGFuZ2xlID0gRkFMU0UsCiAgICAgICAgICAgICAgZ2VuZW5hbWVzID0gcmVzJG5hbWUsCiAgICAgICAgICAgICAgZm9udC5sZWdlbmQgPSBjKDEyKSwKICAgICAgICAgICAgICAgZm9udC5tYWluID0gYygiYm9sZCIsIDE0KSwKICAgICAgICAgICAgICAgYWxwaGEgPSAxLjUsCiAgICAgICAgICAgICAgIGdndGhlbWUgPSBnZ3Bsb3QyOjp0aGVtZShwYW5lbC5ncmlkID1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSkpIApwcmludChtYSkKCmNhaXJvX3BkZihwYXN0ZTAoU3lzLkRhdGUoKSwiX21hXyIsIGV4cCwgIl8iLCB0cmVhdG1lbnQsIi52cy4iLCBjb250cm9sLCIucGRmIikpCnByaW50KG1hKQpkZXYub2ZmKCkKfQpgYGAKCg==