1 Overview

batch condition media treatment induced exp_10
SK085 1 SCFM-IPTG SCFM DMSO yes control
SK086 2 SCFM-IPTG SCFM DMSO yes control
SK087 3 SCFM-IPTG SCFM DMSO yes control
SK094 1 SCFM-EbS-IPTG SCFM EbS yes treatment
SK095 2 SCFM-EbS-IPTG SCFM EbS yes treatment
SK096 3 SCFM-EbS-IPTG SCFM EbS yes treatment

2 Project variables

##       batch     condition media treatment induced    exp_10
## SK085     1     SCFM-IPTG  SCFM      DMSO     yes   control
## SK086     2     SCFM-IPTG  SCFM      DMSO     yes   control
## SK087     3     SCFM-IPTG  SCFM      DMSO     yes   control
## SK094     1 SCFM-EbS-IPTG  SCFM       EbS     yes treatment
## SK095     2 SCFM-EbS-IPTG  SCFM       EbS     yes treatment
## SK096     3 SCFM-EbS-IPTG  SCFM       EbS     yes treatment
## [1] "The control is: SCFM-IPTG"
## [1] "The treatment is: SCFM-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_10 + 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)
##             SK085 SK086 SK087 SK094 SK095 SK096
## gene1650835  1579  1694  1158  1087  1785  1506
## gene1650837  1732  2280  1356   979  1923  1517
## gene1650839   377   454   293   358   543   350
## gene1650841  1914  2500  1745  1478  2295  1593
## gene1650843   292   389   236   169   291   237
## gene1650845   177   180   124   113   199   163
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 302 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 302 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] 5708
# 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_10_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_10", "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] 5708    7
# merge with siggenes
resdf <- full_join(resdf, gff_annot, by = "gene_id", copy = FALSE)
head(resdf)
##    baseMean log2FoldChange     lfcSE       stat    pvalue      padj     gene_id
## 1 1438.2167     0.04040474 0.1599583  0.2525955 0.8005808 0.9114746 gene1650835
## 2 1579.1039    -0.23373426 0.1622710 -1.4403946 0.1497558 0.3620803 gene1650837
## 3  386.8928     0.21568782 0.1817467  1.1867495 0.2353264 0.4830571 gene1650839
## 4 1877.8415    -0.14101687 0.1460251 -0.9657029 0.3341928 0.5906514 gene1650841
## 5  261.2426    -0.33305969 0.2062300 -1.6149912 0.1063126 0.2865999 gene1650843
## 6  155.7703     0.03420085 0.2464384  0.1387805 0.8896236 0.9555403 gene1650845
##     seqnames start  end width strand    source type score phase Name
## 1 chromosome   483 2027  1545      + PseudoCAP gene    NA     0     
## 2 chromosome  2056 3159  1104      + PseudoCAP gene    NA     0     
## 3 chromosome  3169 4278  1110      + PseudoCAP gene    NA     0     
## 4 chromosome  4275 6695  2421      + PseudoCAP gene    NA     0     
## 5 chromosome  7018 7791   774      - PseudoCAP gene    NA     0     
## 6 chromosome  7803 8339   537      - PseudoCAP gene    NA     0     
##           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      padj
## 1 PA14_00010 1438.2167     0.04040474 0.1599583  0.2525955 0.8005808 0.9114746
## 2 PA14_00020 1579.1039    -0.23373426 0.1622710 -1.4403946 0.1497558 0.3620803
## 3 PA14_00030  386.8928     0.21568782 0.1817467  1.1867495 0.2353264 0.4830571
## 4 PA14_00050 1877.8415    -0.14101687 0.1460251 -0.9657029 0.3341928 0.5906514
## 5 PA14_00060  261.2426    -0.33305969 0.2062300 -1.6149912 0.1063126 0.2865999
## 6 PA14_00070  155.7703     0.03420085 0.2464384  0.1387805 0.8896236 0.9555403
##       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       name Parent locus SK085_rpkm SK086_rpkm SK087_rpkm
## 1      GeneID:4384099       dnaA         <NA>   7.989449   7.833958   7.830711
## 2      GeneID:4384100       dnaN         <NA>   8.605764   8.744455   8.540827
## 3      GeneID:4384101       recF         <NA>   6.411482   6.421924   6.336705
## 4      GeneID:4384102       gyrB         <NA>   7.620694   7.747847   7.774559
## 5      GeneID:4385186 PA14_00060         <NA>   6.561349   6.716019   6.542347
## 6      GeneID:4385187 PA14_00070         <NA>   6.368749   6.138494   6.146263
##   SK094_rpkm SK095_rpkm SK096_rpkm SK085_cpm SK086_cpm SK087_cpm SK094_cpm
## 1   7.632174   7.811126   7.997391  8.615052  8.459333  8.456080  8.257213
## 2   7.964566   8.401262   8.491115  8.748155  8.886879  8.683202  8.106762
## 3   6.515466   6.579994   6.380902  6.560362  6.570815  6.485495  6.664462
## 4   7.428580   7.527104   7.433135  8.891988  9.019505  9.046289  8.699259
## 5   5.960189   6.204749   6.339104  6.196208  6.350426  6.177265  5.597344
## 6   5.907771   6.184195   6.326657  5.486717  5.259038  5.266713  5.031337
##   SK095_cpm SK096_cpm SK085_rawcounts SK086_rawcounts SK087_rawcounts
## 1  8.436465  8.623005            1579            1694            1158
## 2  8.543601  8.633478            1732            2280            1356
## 3  6.729058  6.529746             377             454             293
## 4  8.798109  8.703830            1914            2500            1745
## 5  5.840855  5.974703             292             389             236
## 6  5.304194  5.445066             177             180             124
##   SK094_rawcounts SK095_rawcounts SK096_rawcounts locusId   accession        GI
## 1            1087            1785            1506 2194572 YP_788156.1 116053721
## 2             979            1923            1517 2194573 YP_788157.1 116053722
## 3             358             543             350 2194574 YP_788158.1 116053723
## 4            1478            2295            1593 2194575 YP_788159.1 116053724
## 5             169             291             237 2194576 YP_788160.1 116053725
## 6             113             199             163 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] 5701   54
head(resdf)
##        Alias  baseMean log2FoldChange     lfcSE       stat    pvalue      padj
## 1 PA14_00010 1438.2167     0.04040474 0.1599583  0.2525955 0.8005808 0.9114746
## 2 PA14_00020 1579.1039    -0.23373426 0.1622710 -1.4403946 0.1497558 0.3620803
## 3 PA14_00030  386.8928     0.21568782 0.1817467  1.1867495 0.2353264 0.4830571
## 4 PA14_00050 1877.8415    -0.14101687 0.1460251 -0.9657029 0.3341928 0.5906514
## 5 PA14_00060  261.2426    -0.33305969 0.2062300 -1.6149912 0.1063126 0.2865999
## 6 PA14_00070  155.7703     0.03420085 0.2464384  0.1387805 0.8896236 0.9555403
##       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       name Parent locus SK085_rpkm SK086_rpkm SK087_rpkm
## 1      GeneID:4384099       dnaA         <NA>   7.989449   7.833958   7.830711
## 2      GeneID:4384100       dnaN         <NA>   8.605764   8.744455   8.540827
## 3      GeneID:4384101       recF         <NA>   6.411482   6.421924   6.336705
## 4      GeneID:4384102       gyrB         <NA>   7.620694   7.747847   7.774559
## 5      GeneID:4385186 PA14_00060         <NA>   6.561349   6.716019   6.542347
## 6      GeneID:4385187 PA14_00070         <NA>   6.368749   6.138494   6.146263
##   SK094_rpkm SK095_rpkm SK096_rpkm SK085_cpm SK086_cpm SK087_cpm SK094_cpm
## 1   7.632174   7.811126   7.997391  8.615052  8.459333  8.456080  8.257213
## 2   7.964566   8.401262   8.491115  8.748155  8.886879  8.683202  8.106762
## 3   6.515466   6.579994   6.380902  6.560362  6.570815  6.485495  6.664462
## 4   7.428580   7.527104   7.433135  8.891988  9.019505  9.046289  8.699259
## 5   5.960189   6.204749   6.339104  6.196208  6.350426  6.177265  5.597344
## 6   5.907771   6.184195   6.326657  5.486717  5.259038  5.266713  5.031337
##   SK095_cpm SK096_cpm SK085_rawcounts SK086_rawcounts SK087_rawcounts
## 1  8.436465  8.623005            1579            1694            1158
## 2  8.543601  8.633478            1732            2280            1356
## 3  6.729058  6.529746             377             454             293
## 4  8.798109  8.703830            1914            2500            1745
## 5  5.840855  5.974703             292             389             236
## 6  5.304194  5.445066             177             180             124
##   SK094_rawcounts SK095_rawcounts SK096_rawcounts locusId   accession        GI
## 1            1087            1785            1506 2194572 YP_788156.1 116053721
## 2             979            1923            1517 2194573 YP_788157.1 116053722
## 3             358             543             350 2194574 YP_788158.1 116053723
## 4            1478            2295            1593 2194575 YP_788159.1 116053724
## 5             169             291             237 2194576 YP_788160.1 116053725
## 6             113             199             163 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    5701
summary(is.na(resdf$padj))
##    Mode   FALSE    TRUE 
## logical    5480     221
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      38
summary(is.na(sig_genes$padj))
##    Mode   FALSE 
## logical      38
dim(sig_genes)
## [1] 38 55
head(sig_genes)
##          Alias  baseMean log2FoldChange     lfcSE       stat       pvalue
## 290 PA14_03700  175.6311      -2.111993 0.2644127  -7.987490 1.377144e-15
## 291 PA14_03710  136.0235      -2.786479 0.6146952  -4.533106 5.812252e-06
## 327 PA14_04180  185.6246       2.254576 0.6168978   3.654700 2.574831e-04
## 735 PA14_09280 6237.5139      -2.391004 0.1800259 -13.281443 2.966234e-40
## 736 PA14_09290  946.6688      -2.371135 0.1623443 -14.605599 2.586986e-48
## 737 PA14_09300  911.5013      -3.052185 0.1988762 -15.347156 3.700592e-53
##             padj     gene_id   seqnames  start    end width strand    source
## 290 1.642393e-13 gene1651429 chromosome 330946 331944   999      - PseudoCAP
## 291 8.981975e-05 gene1651431 chromosome 332121 332303   183      - PseudoCAP
## 327 2.418754e-03 gene1651505 chromosome 374152 374502   351      + PseudoCAP
## 735 2.712127e-37 gene1652335 chromosome 790021 795450  5430      + PseudoCAP
## 736 4.730734e-45 gene1652337 chromosome 795447 796496  1050      + PseudoCAP
## 737 1.015072e-49 gene1652339 chromosome 796493 798205  1713      + PseudoCAP
##     type score phase Name         Dbxref       name Parent locus SK085_rpkm
## 290 gene    NA     0      GeneID:4383688        sbp         <NA>   6.259635
## 291 gene    NA     0      GeneID:4383689 PA14_03710         <NA>   8.533314
## 327 gene    NA     0      GeneID:4383725 PA14_04180         <NA>   5.181207
## 735 gene    NA     0      GeneID:4385699       pchF         <NA>   8.856222
## 736 gene    NA     0      GeneID:4385698       pchG         <NA>   8.493838
## 737 gene    NA     0      GeneID:4385697 PA14_09300         <NA>   7.833852
##     SK086_rpkm SK087_rpkm SK094_rpkm SK095_rpkm SK096_rpkm SK085_cpm SK086_cpm
## 290   5.919397   6.432344   3.645500   4.306746   4.148038  6.258210  5.917977
## 291   8.004901   8.509954   5.052885   6.419552   4.952596  6.100510  5.579675
## 327   5.462390   5.570573   8.532461   7.329947   6.736631  3.742459  4.011200
## 735   8.971514   9.016292   5.918131   6.565791   6.889719 11.294633 11.410119
## 736   8.578279   8.729162   5.869055   6.124063   6.406162  8.564037  8.648489
## 737   7.860328   8.086422   4.119188   4.967030   5.295074  8.607743  8.634266
##     SK087_cpm SK094_cpm SK095_cpm SK096_cpm SK085_rawcounts SK086_rawcounts
## 290  6.430917  3.644172  4.305376  4.146676             305             287
## 291  6.077430  2.784849  4.042814  2.696820             273             226
## 327  4.115182  7.029191  5.835975  5.250974              50              73
## 735 11.454970  8.339487  8.994265  9.320712           10138           13130
## 736  8.799389  5.938268  6.193467  6.475741            1524            1932
## 737  8.860736  4.860738  5.724227  6.056224            1571            1913
##     SK087_rawcounts SK094_rawcounts SK095_rawcounts SK096_rawcounts locusId
## 290             282              41              97              64 2194868
## 291             220              21              80              21 2194869
## 327              54             462             290             142 2194906
## 735            9280            1151            2630            2445 2195310
## 736            1470             215             373             337 2195311
## 737            1534             100             268             251 2195312
##       accession        GI scaffoldId   stop
## 290 YP_788452.1 116054010       4582 330946
## 291 YP_788453.1 116054011       4582 332121
## 327 YP_788490.1 116054047       4582 374502
## 735 YP_788894.1 116052262       4582 795450
## 736 YP_788895.1 116052261       4582 796496
## 737 YP_788896.1 116052260       4582 798205
##                                                         desc     COG COGFun
## 290                 sulfate-binding protein precursor (NCBI) COG1613      P
## 291                              hypothetical protein (NCBI) COG5583      S
## 327                              hypothetical protein (NCBI) COG3111      S
## 735                         pyochelin synthetase PchF (NCBI) COG1020      Q
## 736               pyochelin biosynthetic protein PchG (NCBI) COG4693      Q
## 737 putative ATP-binding component of ABC transporter (NCBI) COG1132      V
##                                                                 COGDesc
## 290            ABC-type sulfate transport system, periplasmic component
## 291                                       Uncharacterized small protein
## 327                                   Uncharacterized conserved protein
## 735       Non-ribosomal peptide synthetase modules and related proteins
## 736  Oxidoreductase (NAD-binding), involved in siderophore biosynthesis
## 737 ABC-type multidrug transport system, ATPase and permease components
##                                                        TIGRFam
## 290 TIGR00971 sulfate ABC transporter, sulfate-binding protein
## 291                                                           
## 327                                                           
## 735                    TIGR01733 amino acid adenylation domain
## 736                      TIGR01761 thiazolinyl imide reductase
## 737                                                           
##                                 TIGRRoles
## 290 Transport and binding proteins:Anions
## 291                                      
## 327                                      
## 735                                      
## 736                                      
## 737                                      
##                                                         GO EC ECDesc direction
## 290            GO:0008272,GO:0030288,GO:0008271,GO:0015419                down
## 291                                                                       down
## 327                                                                         up
## 735 GO:0009058,GO:0031177,GO:0016874,GO:0016788,GO:0048037                down
## 736            GO:0006810,GO:0016020,GO:0016491,GO:0005215                down
## 737            GO:0006810,GO:0016021,GO:0005524,GO:0042626                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_10 + 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_10", "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_10", 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_10", 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()
}

LS0tCnRpdGxlOiAiMjAyNV9leHBfMTBfYWxnaW5hdGVfREVHIgphdXRob3I6ICJOb3VyIEVsIEh1c3NlaW5pIgpkYXRlOiAiMjAyNSIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICB0b2NfY29sbGFwc2VkOiBmYWxzZSAgIyBFbnN1cmVzIFRPQyBpcyBleHBhbmRlZCBieSBkZWZhdWx0CiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBoaWdobGlnaHQ6IGthdGUKICAgIHRoZW1lOgogICAgICBib290c3dhdGNoOiB6ZXBoeXIKICAgIGNzczogc3R5bGUuY3NzICAjIExpbmsgdG8geW91ciBjdXN0b20gQ1NTIGZpbGUKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCiAgbWFya2Rvd246IAogICAgd3JhcDogNzIKLS0tCgoKYGBge3IgbG9hZF9saWJyYXJpZXMsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoIkRFU2VxMiIpCmxpYnJhcnkoImdncGxvdDIiKQpsaWJyYXJ5KCJrYWJsZUV4dHJhIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJnZ2ZvcmNlIikKbGlicmFyeSgiUkNvbG9yQnJld2VyIikKbGlicmFyeSgicGhlYXRtYXAiKQpsaWJyYXJ5KCJ3ZXNhbmRlcnNvbiIpCmxpYnJhcnkoIkVuaGFuY2VkVm9sY2FubyIpCmxpYnJhcnkoImdncHViciIpCmxpYnJhcnkoImhwZ2x0b29scyIpCmxpYnJhcnkoImRwbHlyIikKbGlicmFyeSgidGliYmxlIikgCmxpYnJhcnkoImVkZ2VSIikKbGlicmFyeSgiZ2VuZWZpbHRlciIpCmxpYnJhcnkoInBoZWF0bWFwIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJ0aWR5dmVyc2UiKQpsaWJyYXJ5KCJERVNlcTIiKQpsaWJyYXJ5KCJDb21wbGV4SGVhdG1hcCIpCmxpYnJhcnkoImdvc2VxIikKbGlicmFyeSgicGx5ciIpCmxpYnJhcnkoImdlb210ZXh0cGF0aCIpCmBgYAoKIyBPdmVydmlldwoKYGBge3Igc2FtcGxlX3RhYmxlLCBlY2hvPUZBTFNFfQojIExvYWQgbWV0YWRhdGEgQ1NWIGZpbGUgaW50byBhIGRhdGFmcmFtZSwgdXNpbmcgdGhlIGZpcnN0IGNvbHVtbiBhcyByb3cgbmFtZXMKbWV0YWRhdGEgPC0gcmVhZC5jc3YoIi4uLy4uL3Jhdy1kYXRhL21ldGFkYXRhX2FsZ2luYXRlX3Z0bC5jc3YiLCByb3cubmFtZXMgPSAxLCBoZWFkZXIgPSBUUlVFKQoKIyBGaWx0ZXIgdGhlIGRhdGEgdG8gaW5jbHVkZSBvbmx5IHJvd3Mgd2hlcmUgZXhwXzEwIGlzIGVpdGhlciAiY29udHJvbCIgb3IgInRyZWF0bWVudCIKIyBUaGVuIHJlbW92ZSBvdGhlciBleHBlcmltZW50cyAoZXhwXzIgdG8gZXhwXzYpCm1ldGFkYXRhIDwtIGZpbHRlcihtZXRhZGF0YSwgZXhwXzEwICVpbiUgYygiY29udHJvbCIsICJ0cmVhdG1lbnQiKSkgJT4lCiAgICBzZWxlY3QoYmF0Y2gsIGNvbmRpdGlvbiwgbWVkaWEsIHRyZWF0bWVudCwgaW5kdWNlZCwgZXhwXzEwKSAKCiMgRGlzcGxheSB0aGUgY2xlYW5lZCBtZXRhZGF0YSB0YWJsZSB1c2luZyBrbml0cjo6a2FibGUgYW5kIGthYmxlRXh0cmEgc3R5bGluZwptZXRhZGF0YSAlPiUKICBrYmwoKSAlPiUgICMgQ3JlYXRlIGEgYmFzaWMgdGFibGUKICBrYWJsZV9jbGFzc2ljKGZ1bGxfd2lkdGggPSBUUlVFKSAgIyBBcHBseSBhIGNsYXNzaWMgdGFibGUgc3R5bGUgd2l0aCBmdWxsIHdpZHRoCmBgYCAKCiMgUHJvamVjdCB2YXJpYWJsZXMKYGBge3IgcHJvamVjdF9wYXJhbWV0ZXJzLCBlY2hvPUZBTFNFfQojIERlZmluZSB0aGUgbGFiZWxzIGZvciBjb250cm9sIGFuZCB0cmVhdG1lbnQgZ3JvdXBzIHVzZWQgaW4gdGhlIGV4cGVyaW1lbnQKaGVhZChtZXRhZGF0YSkKIyBFeHRyYWN0IGNvbnRyb2wgYW5kIHRyZWF0bWVudCBjb25kaXRpb25zIGJhc2VkIG9uIGBleHBfMTBgIGxhYmVscwpjb250cm9sIDwtIG1ldGFkYXRhW21ldGFkYXRhJGV4cF8xMCA9PSAiY29udHJvbCIsIF0KdHJlYXRtZW50IDwtIG1ldGFkYXRhW21ldGFkYXRhJGV4cF8xMCA9PSAidHJlYXRtZW50IiwgXQoKY29udHJvbCA8LSB1bmlxdWUoY29udHJvbCRjb25kaXRpb24pCnRyZWF0bWVudCA8LSB1bmlxdWUodHJlYXRtZW50JGNvbmRpdGlvbikKCnByaW50KHBhc3RlMCgiVGhlIGNvbnRyb2wgaXM6ICIsIGNvbnRyb2wpKQpwcmludChwYXN0ZTAoIlRoZSB0cmVhdG1lbnQgaXM6ICIsIHRyZWF0bWVudCkpCgojIFNldCBkZWZhdWx0IHRleHQgc2l6ZXMgZm9yIHBsb3RzCnRleHQuc2l6ZSA8LSAxMiAgICAKYXhpcy50ZXh0LnNpemUgPC0gMTQKCmxvZ2ZjX2N1dG9mZiA8LSAyCnB2YWxfY3V0b2ZmIDwtIDAuMDEKCiMgU2V0IHZhcmlhYmxlcyBmb3IgdGhlIHByb2plY3QgdXNlZCBpbiBmaWxlbmFtZXMgYW5kIHBsb3QgdGl0bGVzCnByb2plY3QgPC0gIm9ybl9hbGdpbmF0ZV9ybmFzZXEiCmV4cCA8LSAiZXhwXzEwIiAgICAgICAgICAgICAgICAgICAgCmBgYAoKYGBge3IgcmF3ZGF0YX0KIyBMb2FkIHJhdyBjb3VudCBkYXRhCnJhd2NvdW50cyA8LSByZWFkLmNzdigiLi4vLi4vcmF3LWRhdGEvaHRzZXFfU0tfdW5maWx0ZXJlZF9yZXZlcnNlX3N0cmFuZF9jb3VudC5jc3YiLCAKICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9IDEsIGhlYWRlciA9IFRSVUUpCgojIEFwcGVuZCBhIHByZWZpeCB0byB0aGUgYmF0Y2ggYW5kIHJ1biBjb2x1bW5zIHRvIHR1cm4gdG8gY2hhcmFjdGVyIGNsYXNzCm1ldGFkYXRhW1siYmF0Y2giXV0gPC0gcGFzdGUwKCJiIiwgbWV0YWRhdGFbWyJiYXRjaCJdXSkKbWV0YWRhdGFbWyJydW4iXV0gPC0gcGFzdGUwKCJyIiwgbWV0YWRhdGFbWyJydW4iXV0pCgojIFN1YnNldCB0aGUgcmF3Y291bnRzIGRhdGFmcmFtZSB0byBvbmx5IGluY2x1ZGUgc2FtcGxlcyB0aGF0IGFyZSBwcmVzZW50IGluIGV4cGVyaW1lbnQKc2FtcGxlcyA8LSByb3duYW1lcyhtZXRhZGF0YSkKcmF3Y291bnRzIDwtIHNlbGVjdChyYXdjb3VudHMsIGFsbF9vZihzYW1wbGVzKSkKCiMgRW5zdXJlIHRoYXQgdGhlIG9yZGVyIG9mIHNhbXBsZXMgaW4gbWV0YWRhdGEgbWF0Y2hlcyB0aGUgb3JkZXIgb2YgY29sdW1ucyBpbiByYXdjb3VudHMKYWxsKHJvd25hbWVzKG1ldGFkYXRhKSA9PSBjb2xuYW1lcyhyYXdjb3VudHMpKSAgIyBTaG91bGQgcmV0dXJuIFRSVUUgaWYgb3JkZXIgaXMgY29ycmVjdAoKIyBEZWZpbmUgdGhlIGRlc2lnbiBmb3JtdWxhIGZvciBERVNlcTIsIGluY2x1ZGluZyBtYWluIGNvbmRpdGlvbiBhbmQgYmF0Y2ggZWZmZWN0CmRlc2lnbl9mb3JtdWxhIDwtIH4gZXhwXzEwICsgYmF0Y2gKCiMgQ3JlYXRlIERFU2VxMiBkYXRhc2V0IG9iamVjdCBmcm9tIHRoZSBmaWx0ZXJlZCBjb3VudCBtYXRyaXggYW5kIG1ldGFkYXRhCmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KAogIGNvdW50RGF0YSA9IHJhd2NvdW50cywKICBjb2xEYXRhID0gbWV0YWRhdGEsCiAgZGVzaWduID0gZGVzaWduX2Zvcm11bGEKKQpgYGAKCgojIExpYnJhcnkgc2l6ZSBwZXIgc2FtcGxlCmBgYHtyIGxpYnJhcnlfc2l6ZX0KIyBTdW0gdXAgdGhlIGNvdW50cyBmb3IgZWFjaCBzYW1wbGUKcmF3Y291bnRzX3N1bXMgPC0gY29sU3VtcyhyYXdjb3VudHMpCgojIFR1cm4gaXQgaW50byBhIGRhdGEgZnJhbWUKZGF0YSA8LSBkYXRhLmZyYW1lKAogIENhdGVnb3J5ID0gbmFtZXMocmF3Y291bnRzX3N1bXMpLAogIENvdW50ID0gYXMubnVtZXJpYyhyYXdjb3VudHNfc3VtcykKKQoKIyBNYWtlIHN1cmUgc2FtcGxlIG9yZGVyIGlzIGNvbnNpc3RlbnQKZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZShDYXRlZ29yeSA9IGZhY3RvcihDYXRlZ29yeSwgbGV2ZWxzID0gc29ydCh1bmlxdWUoQ2F0ZWdvcnkpKSkpCgojIFBsb3QgYmFyIGNoYXJ0IG9mIGxpYnJhcnkgc2l6ZXMKcCA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHggPSBDYXRlZ29yeSwgeSA9IENvdW50LCBmaWxsID0gQ2F0ZWdvcnkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAjIGNvb3JkX2ZsaXAoKSAjIGZsaXAgaWYgdG9vIG1hbnkgc2FtcGxlcyB0byByZWFkIGxhYmVscyBlYXNpbHkKICBsYWJzKHkgPSAiTGlicmFyeSBzaXplIChNKSIsIHggPSBOVUxMKSArICAjIHJlbW92ZSB4IGxhYmVsLCByZW5hbWUgeSBheGlzCiAgIyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKyAgIyBvcHRpb25hbCBjb2xvciBwYWxldHRlCiAgc2NhbGVfeV9jb250aW51b3VzKAogICAgbGFiZWxzID0gc2NhbGVzOjpsYWJlbF9udW1iZXIoc2NhbGUgPSAxZS02KSwgICMgc2hvdyBjb3VudHMgaW4gbWlsbGlvbnMKICAgIGxpbWl0cyA9IGMoMCwgKG1heChkYXRhJENvdW50KSArIDFlNikpICAgICAgICAjIGFkZCBhIGJpdCBvZiBzcGFjZSBvbiB0b3AKICApICsKICB0aGVtZSgKICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0LnNpemUsIGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksICAjIHNsYW50IGxhYmVscwogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYXhpcy50ZXh0LnNpemUpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHRleHQuc2l6ZSksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGF4aXMudGV4dC5zaXplKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAgIyBubyBsZWdlbmQgbmVlZGVkIHNpbmNlIGVhY2ggYmFyIGlzIGEgZGlmZmVyZW50IHNhbXBsZQogICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShsaW5ld2lkdGggPSAwLjIpLAogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgU2hvdyB0aGUgcGxvdApwCgojIFNhdmUgdGhlIHBsb3QgYXMgYSBQREYgd2l0aCB0b2RheeKAmXMgZGF0ZSBhbmQgcHJvamVjdCBuYW1lCmdnc2F2ZShwYXN0ZTAoU3lzLkRhdGUoKSwgIl9saWJyYXJ5X3NpemVfIiwgZXhwLCAiXyIsIHRyZWF0bWVudCwiLnZzLiIsIGNvbnRyb2wsICIucGRmIiksIGRldmljZSA9ICJwZGYiKQpgYGAKCiMgRXhwcmVzc2lvbiBkaXN0cmlidXRpb24KCmBgYHtyIGV4cHJlc3Npb25fZGlzdHJpYnV0aW9ufQoKIyBTdGFjayByYXdjb3VudHMgaW50byBzaW5nbGUgdmVjdG9yIApkYXQgPC0gc3RhY2socmF3Y291bnRzKQoKIyBGb3JtYXQgZXhwcmVzc2lvbiBkaXN0cmlidXRpb24gcGxvdCB3aXRoIHRoZSBleHByZXNzaW9uIGxldmVsIGFuZCBkZW5zaXR5IApleHByZXNzaW9uX2Rpc3QgPC0gZ2dwbG90KGRhdCwgYWVzKHggPSBsb2cyKHZhbHVlcysxKSwgIGZpbGw9aW5kLCBsYWJlbCA9IGluZCApKSArIAogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSwgcG9zaXRpb24gPSAiaWRlbnRpdHkiKSArIAogIHlsYWIoIkRlbnNpdHkiKSArIAogIGdlb21fdGV4dGRlbnNpdHkoaGp1c3QgPSAieW1heCIsIHZqdXN0ID0gMCwKICAgICAgICAgICB0ZXh0X29ubHkgPSBUUlVFLCB0ZXh0X3Ntb290aGluZyA9IDIwKSArIAogICAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gdGV4dC5zaXplKSwKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBheGlzLnRleHQuc2l6ZSksCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHRleHQuc2l6ZSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBheGlzLnRleHQuc2l6ZSksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUobGluZXdpZHRoID0gMC4yKSwKICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDE1KSkKCmV4cHJlc3Npb25fZGlzdAoKI3NhdmUgZmlndXJlCmNhaXJvX3BkZihwYXN0ZTAoU3lzLkRhdGUoKSwgIl9leHByZXNzaW9uX2Rpc3RfIiwgZXhwLCAiXyIsIHRyZWF0bWVudCwgIi52cy4iLCBjb250cm9sLCAiLnBkZiIpKQpleHByZXNzaW9uX2Rpc3QKZGV2Lm9mZigpIAoKYGBgCgojIE5vbi16ZXJvIGdlbmVzIG9ic2VydmVkCgpgYGB7ciBub24temVyb19nZW5lc30KIyBQcmVwYXJlIGRhdGEgYnkgZ2V0dGluZyBsaWJyYXJ5IHNpemVzIGFuZCBub24temVybyBjb3VudHMKeCA8LSBjb2xTdW1zKHJhd2NvdW50cykKeSA8LSBjb2xTdW1zKHJhd2NvdW50cyAhPSAwKSAKZGYgPC0gZGF0YS5mcmFtZSh4LHkpCmRmJGluZCA8LSByb3duYW1lcyhkZikKCiMgQ2FsY3VsYXRlIGF4aXMgbGltaXRzCnhfbWluIDwtIG1pbihkZiR4KQp4X21heCA8LSBtYXgoZGYkeCkKeV9taW4gPC0gbWluKGRmJHkpCnlfbWF4IDwtIG1heChkZiR5KQoKIyBOb24temVybyBwbG90Cm5vbnplcm8gPC0gZ2dwbG90KGRhdGEgPSBkZiwgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSBpbmQsIGxhYmVsID0gaW5kKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsKICBnZW9tX3RleHQoaGp1c3QgPSAtMC4xLCB2anVzdCA9IC0wLjEsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDUpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoeV9taW4sIHlfbWF4KSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICBsaW1pdHMgPSBjKHhfbWluLTFlMywgeF9tYXgrOWU1KSwKICAgIGxhYmVscyA9IHNjYWxlczo6Y29tbWFfZm9ybWF0KHNjYWxlID0gMWUtNiwgIGFjY3VyYWN5ID0gMSkgICMgRm9ybWF0IGxhYmVscyB3aXRob3V0IGRlY2ltYWxzCiAgKSArCiAgeGxhYigiTWlsbGlvbnMgb2YgcmVhZHMiKSArIHlsYWIoIk51bWJlciBvZiBub24temVybyBnZW5lcyBvYnNlcnZlZCIpICsKICBsYWJzKGNvbG9yID0gIlNhbXBsZSIpICsgCiAgICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0LnNpemUpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGF4aXMudGV4dC5zaXplKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gdGV4dC5zaXplKSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGF4aXMudGV4dC5zaXplKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShsaW5ld2lkdGggPSAwLjIpLAogICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBjb29yZF9jYXJ0ZXNpYW4oKQoKIyBTaG93IG5vbnplcm8gcGxvdApub256ZXJvCgojIFNhdmUgcGxvdAoKY2Fpcm9fcGRmKHBhc3RlMChTeXMuRGF0ZSgpLCAiX25vbi16ZXJvXyIsIGV4cCwgIl8iLCB0cmVhdG1lbnQsICIudnMuIiwgY29udHJvbCwgIi5wZGYiKSkKbm9uemVybwpkZXYub2ZmKCkgCgpgYGAKCiMgUlBLTSBhbmQgQ1BNIHRyYW5zZm9ybWF0aW9ucwpgYGB7ciBkYXRhX3RyYW5zZm9ybWF0aW9uc30KIyBMb2FkIEdGRiBhbm5vdGF0aW9uIApnZmZfYW5ub3QgPC0gbG9hZF9nZmZfYW5ub3RhdGlvbnMoIi4uLy4uL3Jhdy1kYXRhL3BhZXJ1Z2lub3NhX3BhMTQuZ2ZmIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZF9jb2wgPSAiZ2VuZV9pZCIsIHR5cGUgPSAiZ2VuZSIpCnJvd25hbWVzKGdmZl9hbm5vdCkgPC0gZ2ZmX2Fubm90JGdlbmVfaWQKCmhlYWQoZ2ZmX2Fubm90KQpoZWFkKHJhd2NvdW50cykKZGltKGdmZl9hbm5vdCkKZGltKHJhd2NvdW50cykKCnN1bW1hcnkocm93bmFtZXMoZ2ZmX2Fubm90KSA9PSByb3duYW1lcyhyYXdjb3VudHMpKQpnZmZfYW5ub3QgPC0gZ2ZmX2Fubm90W3Jvd25hbWVzKHJhd2NvdW50cyksXQpzdW1tYXJ5KHJvd25hbWVzKGdmZl9hbm5vdCkgPT0gcm93bmFtZXMocmF3Y291bnRzKSkKCgojIENyZWF0ZSBhbiBleHByZXNzaW9uIG9iamVjdCB3aXRoIGNvdW50cywgbWV0YWRhdGEsIGFuZCBnZW5lIGluZm8KZXhwdCA8LSBjcmVhdGVfZXhwdChjb3VudF9kYXRhZnJhbWUgPSByYXdjb3VudHMsCiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEgPSBtZXRhZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgZ2VuZV9pbmZvID0gZ2ZmX2Fubm90KQoKIyBOb3JtYWxpemUgY291bnRzIGxvZzIgQ1BNCmNwbV9ub3JtYWxpemVkX2V4cCA8LSBub3JtYWxpemVfZXhwdChleHB0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gInJhdyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydCA9ICJjcG0iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd19taW4gPSAiMTAiKQoKIyMjIyMjIyBDYWxjdWxhdGUgUlBLTSAjIyMjIyMjIwoKIyBHcmFiIGdlbmUgbGVuZ3RocyBmcm9tIEdGRiAoc2hvdWxkIGJlIGluIGJhc2UgcGFpcnMpCmdlbmVfbGVuZ3RocyA8LSBnZmZfYW5ub3Qkd2lkdGggIApuYW1lcyhnZW5lX2xlbmd0aHMpIDwtIHJvd25hbWVzKGdmZl9hbm5vdCkgICMgc2V0IGdlbmUgbmFtZXMKCiMgTWFrZSBzdXJlIGdlbmVfbGVuZ3RocyBhcmUgaW4gdGhlIHNhbWUgb3JkZXIgYXMgcmF3Y291bnRzIHJvd3MKZ2VuZV9sZW5ndGhzIDwtIGdlbmVfbGVuZ3Roc1tyb3duYW1lcyhyYXdjb3VudHMpXQoKIyBNYWtlIERHRUxpc3Qgb2JqZWN0IGZvciBlZGdlUgpkZ2UgPC0gREdFTGlzdChjb3VudHMgPSByYXdjb3VudHMpCgojIENhbGN1bGF0ZSBSUEtNIChyZWFkcyBwZXIga2lsb2Jhc2UgcGVyIG1pbGxpb24pCnJwa20gPC0gcnBrbShkZ2UsIGdlbmUubGVuZ3RoID0gZ2VuZV9sZW5ndGhzKQoKIyBXcmFwIFJQS00gaW4gYW4gZXhwZXJpbWVudCBvYmplY3QgdG9vCmV4cHRfcnBrbSA8LSBjcmVhdGVfZXhwdChjb3VudF9kYXRhZnJhbWUgPSBycGttLAogICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEgPSBtZXRhZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm8gPSBnZmZfYW5ub3QpCgojIGxvZzIgdHJhbnNmb3JtIHRoZSBSUEtNIChhZ2Fpbiwgbm8gbm9ybWFsaXphdGlvbiBiZXlvbmQgbG9nKQpycGttX25vcm1hbGl6ZWRfZXhwIDwtIG5vcm1hbGl6ZV9leHB0KGV4cHRfcnBrbSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gInJhdyIpCgojIEdldCB0aGUgYWN0dWFsIGV4cHJlc3Npb24gbWF0cmljZXMgZnJvbSB0aGUgZXhwZXJpbWVudCBvYmplY3RzCnJwa20gPC0gZXhwcnMocnBrbV9ub3JtYWxpemVkX2V4cCkKY3BtIDwtIGV4cHJzKGNwbV9ub3JtYWxpemVkX2V4cCkKCiMgTWVyZ2UgQ1BNIGFuZCBSUEtNIG1hdHJpY2VzIHdpdGggZ2VuZSBhbm5vdGF0aW9uIGluZm8KY3BtX2Fubm90YXRlZCA8LSBtZXJnZShnZmZfYW5ub3QsIGNwbSwgYnkgPSAwKQpycGttX2Fubm90YXRlZCA8LSBtZXJnZShnZmZfYW5ub3QsIHJwa20sIGJ5ID0gMCkKYGBgCgojIyBIZWF0bWFwIG9mIGFsZ2luYXRlIGdlbmVzClRoaXMgZ2VuZXJhdGVzIGEgc21hbGwgaGVhdG1hcCBvZiB0aGUgYWxnaW5hdGUgZ2VuZXMgYWNyb3NzIHNhbXBsZXMgdG8gdmlzdWFsaXplIGV4cHJlc3Npb24uCgpgYGB7ciBoZWF0bWFwc30KIyBMb29wIHRocm91Z2ggQ1BNIGFuZCBSUEtNIHRvIHBsb3QgYm90aCBoZWF0bWFwcwpmb3IgKHR5cGUgaW4gYygiY3BtIiwgInJwa20iKSkgewogIAogICMgRGVmaW5lIGdlbmUgbGlzdAogIGFsZ19vcGVyb25fZ2VuZXMgPC0gYygKICAgICJhbGdBIiwgImFsZ0YiLCAiYWxnSiIsICJhbGdJIiwgImFsZ0wiLCAiYWxnWCIsICJhbGdHIiwgImFsZ0UiLAogICAgImFsZ0siLCAiYWxnNDQiLCAiYWxnOCIsICJhbGdEIiwgIm11Y0MiLCAibXVjQiIsICJhbGdVIiwgImFsZ1ciLAogICAgImFsZ1AiLCAiYWxnUSIsICJhbGdSIiwgImFsZ1oiLCAiYWxnQyIsICJhbGdCIgogICkKCiAgIyBHZXQgdGhlIHJpZ2h0IGRhdGEgcGVyIHR5cGUgb2YgdHJhbnNmb3JtYXRpb24KICBkYXRhX2Fubm90IDwtIGdldChwYXN0ZTAodHlwZSwgIl9hbm5vdGF0ZWQiKSkKICAKICAjIEZpeCByb3duYW1lcyB1c2luZyBnZW5lIG5hbWUgKG1ha2UgdW5pcXVlKQogIHJvd25hbWVzKGRhdGFfYW5ub3QpIDwtIG1ha2UubmFtZXMoZGF0YV9hbm5vdCRuYW1lLCB1bmlxdWUgPSBUUlVFKQogIAogICMgRHJvcCB1bmRlc2lyZWQgbWV0YWRhdGEgY29sdW1ucwogIGNvbHNfdG9fZXhjbHVkZSA8LSBjKCJSb3cubmFtZXMiLCJzZXFuYW1lcyIsInN0YXJ0IiwiZW5kIiwid2lkdGgiLAogICAgICAgICAgICAgICAgICAgICAgICJzdHJhbmQiLCJzb3VyY2UiLCJ0eXBlIiwic2NvcmUiLCJwaGFzZSIsCiAgICAgICAgICAgICAgICAgICAgICAgImdlbmVfaWQiLCJOYW1lIiwiRGJ4cmVmIiwiQWxpYXMiLCJuYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAiUGFyZW50IiwibG9jdXMiKQogIGtlZXAgPC0gIW5hbWVzKGRhdGFfYW5ub3QpICVpbiUgY29sc190b19leGNsdWRlCiAgZXhwcl9kYXRhIDwtIGRhdGFfYW5ub3RbLCBrZWVwXQogIAogICMgRXh0cmFjdCBtYXRyaXggZm9yIGFsZyBnZW5lcwogIGFsZ19nZW5lcyA8LSBleHByX2RhdGFbYWxnX29wZXJvbl9nZW5lcywgLCBkcm9wID0gRkFMU0VdCiAgbWF0IDwtIGFsZ19nZW5lcyAtIHJvd01lYW5zKGFsZ19nZW5lcykKICAKICAjIFB1bGwgc2FtcGxlIGFubm90YXRpb25zCiAgYW5ubyA8LSBhcy5kYXRhLmZyYW1lKG1ldGFkYXRhWywgYygiY29uZGl0aW9uIiwgImluZHVjZWQiKV0pCiAgY29sbmFtZXMoYW5ubykgPC0gYygiQ29uZGl0aW9uIiwgIkluZHVjZWQiKQogIAogICMgQ29sb3Igc2V0dGluZ3MgZm9yIGFubm90YXRpb24KICMgYW5uX2NvbG9ycyA8LSBsaXN0KAogIyAgQ29uZGl0aW9uID0gYygiTEItRE1TTyIgPSAiI0Q5NUYwMiIsICJMQi1JUFRHIiA9ICIjNjZBNjFFIiksCiAjICBJbmR1Y2VkID0gYygibm8iID0gImxpZ2h0Z3JleSIsICJ5ZXMiID0gImdyYXkyNyIpCiAjICkKICAKICAjIFNjYWxlIGRhdGEgYnkgcm93IChaLXNjb3JlIHBlciBnZW5lKQogIHNjYWxlZF9tYXQgPC0gdChzY2FsZSh0KG1hdCkpKQoKICAjIEJ1aWxkIGhlYXRtYXAKICBodCA8LSBIZWF0bWFwKAogICAgc2NhbGVkX21hdCwKICAgIG5hbWUgPSAiWi1zY29yZSIsCiAgICB0b3BfYW5ub3RhdGlvbiA9IEhlYXRtYXBBbm5vdGF0aW9uKGRmID0gYW5ubyMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjY29sID0gYW5uX2NvbG9ycwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgIGNsdXN0ZXJfY29sdW1ucyA9IFRSVUUsCiAgICByb3dfbmFtZXNfc2lkZSA9ICJsZWZ0IiwKICAgIGNvbHVtbl9uYW1lc19zaWRlID0gImJvdHRvbSIsCiAgICBjb2x1bW5fbmFtZXNfcm90ID0gNDUsCiAgICByb3dfbmFtZXNfZ3AgPSBncGFyKGZvbnRzaXplID0gMTApLAogICAgY29sdW1uX25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDEwKSwKICAgIHNob3dfcm93X2RlbmQgPSBUUlVFLAogICAgc2hvd19jb2x1bW5fZGVuZCA9IFRSVUUKICApCiAgCiAgIyBEcmF3IGFuZCBzYXZlCiAgZHJhdyhodCkKICAKICBjYWlyb19wZGYocGFzdGUwKFN5cy5EYXRlKCksICJfYWxnX2hlYXRtYXBfIiwgdHlwZSwgIl8iLCBleHAsICJfIiwgdHJlYXRtZW50LCAiLnZzLiIsIGNvbnRyb2wsICIucGRmIikpCiAgZHJhdyhodCkKICBkZXYub2ZmKCkKfQoKYGBgCgojIERFU2VxCmBgYHtyIERFU2VxfQojIENyZWF0ZSBERVNlcURhdGFTZXQKZGRzIDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoCiAgY291bnREYXRhID0gcmF3Y291bnRzLAogIGNvbERhdGEgPSBtZXRhZGF0YSwKICBkZXNpZ24gPSBkZXNpZ25fZm9ybXVsYQopCgojIENoZWNrIG51bWJlciBvZiBnZW5lcyBiZWZvcmUgZmlsdGVyaW5nCnByaW50KCJOdW1iZXIgb2YgZ2VuZXMgYmVmb3JlIGZpbHRlcmluZzoiKQpucm93KGRkcykKCiMgRmlsdGVyOiBrZWVwIGdlbmVzIHdpdGggY291bnRzID49MTAgaW4gYXQgbGVhc3QgMiBzYW1wbGVzCnByaW50KCJGaWx0ZXJpbmcgZ2VuZXMgd2l0aCBjb3VudHMgPj0xMCBpbiBhdCBsZWFzdCAyIHNhbXBsZXMiKQprZWVwIDwtIHJvd1N1bXMoY291bnRzKGRkcykgPj0gMTApID49IDIgCmRkc19maWx0ZXJlZCA8LSBkZHNba2VlcCwgXQoKIyBDaGVjayBudW1iZXIgb2YgZ2VuZXMgYWZ0ZXIgZmlsdGVyaW5nCnByaW50KCJOdW1iZXIgb2YgZ2VuZXMgYWZ0ZXIgZmlsdGVyaW5nOiIpCm5yb3coZGRzX2ZpbHRlcmVkKQoKIyBSdW4gREVTZXEgb24gdGhlIGZpbHRlcmVkIGRhdGFzZXQKZGRzX2ZpbmFsIDwtIERFU2VxKGRkc19maWx0ZXJlZCkKCiMgU2hvdyBhdmFpbGFibGUgcmVzdWx0cwpyZXN1bHRzTmFtZXMoZGRzX2ZpbmFsKQoKIyBQbG90IGRpc3BlcnNpb24gZXN0aW1hdGVzCnBsb3REaXNwRXN0cyhkZHNfZmluYWwpCmBgYAoKIyBTYXZlIERFIHRhYmxlcyAKYGBge3Igc2F2ZV90YWJsZXN9CnJlcyA8LSByZXN1bHRzKGRkc19maW5hbCwgY29udHJhc3QgPSBjKCJleHBfMTAiLCAidHJlYXRtZW50IiwgImNvbnRyb2wiKSkKcmVzZGYgPC0gYXMuZGF0YS5mcmFtZShyZXMpCnJlc2RmJGdlbmVfaWQgPC0gcm93bmFtZXMocmVzZGYpCgpjcG0gPC0gYXMuZGF0YS5mcmFtZShjcG0pCnJwa20gPC0gYXMuZGF0YS5mcmFtZShycGttKQoKIyBhcHBlbmQgdHlwZSBvZiB2YWx1ZSB0byB0aGUgZGF0YWZyYW1lICAgCmNvbG5hbWVzKHJwa20pIDwtIHBhc3RlMChjb2xuYW1lcyhycGttKSwgIl9ycGttIikKY29sbmFtZXMoY3BtKSA8LSBwYXN0ZTAoY29sbmFtZXMoY3BtKSwgIl9jcG0iKQpyYXdjb3VudHMyIDwtIHJhd2NvdW50cwpjb2xuYW1lcyhyYXdjb3VudHMyKSA8LSBwYXN0ZTAoY29sbmFtZXMocmF3Y291bnRzMiksICJfcmF3Y291bnRzIikKCiMgZW5zdXJlIGNvbHVtbiBnZW5lX2lkIGlzIHRoZXJlCnJwa20kZ2VuZV9pZCA8LSByb3duYW1lcyhycGttKQpjcG0kZ2VuZV9pZCA8LSByb3duYW1lcyhjcG0pCnJhd2NvdW50czIkZ2VuZV9pZCA8LSByb3duYW1lcyhyYXdjb3VudHMyKQoKZ2ZmX2Fubm90IDwtIGdmZl9hbm5vdFtyb3duYW1lcyhyZXNkZiksXQoKZGltKHJlc2RmKQojIG1lcmdlIHdpdGggc2lnZ2VuZXMKcmVzZGYgPC0gZnVsbF9qb2luKHJlc2RmLCBnZmZfYW5ub3QsIGJ5ID0gImdlbmVfaWQiLCBjb3B5ID0gRkFMU0UpCmhlYWQocmVzZGYpCgpwYV9nbyA8LSByZWFkLmNzdigiLi4vLi4vcmF3LWRhdGEvMjA4OTYzX21pY3JvYmVzLm9ubGluZS5jc3YiLCBoZWFkZXIgPSBUUlVFKQpoZWFkKHBhX2dvKQoKY29sX3RvX3JlbW92ZSA8LSBpbnRlcnNlY3QoY29sbmFtZXMocGFfZ28pLGNvbG5hbWVzKHJlc2RmKSkKY29sX3RvX3JlbW92ZSA8LSBzZXRkaWZmKGNvbF90b19yZW1vdmUsICJBbGlhcyIpICMgcmV0dXJucyBhbGwgZXhjZXB0IHRoZSBzZWNvbmQgdmVjdG9yCgpwYV9nbyA8LSBwYV9nbyAlPiUgc2VsZWN0KC1hbGxfb2YoY29sX3RvX3JlbW92ZSkpCgpyZXNkZiA8LSBmdWxsX2pvaW4ocmVzZGYsIHJwa20sIGJ5ID0gImdlbmVfaWQiLCBjb3B5ID0gRkFMU0UpCnJlc2RmIDwtIGZ1bGxfam9pbihyZXNkZiwgY3BtLCBieSA9ICJnZW5lX2lkIiwgY29weSA9IEZBTFNFKQpyZXNkZiA8LSBmdWxsX2pvaW4ocmVzZGYsIHJhd2NvdW50czIsIGJ5ID0gImdlbmVfaWQiLCBjb3B5ID0gRkFMU0UpCiNyZXNkZiA8LSBmdWxsX2pvaW4ocmVzZGYsIHBhX2dvLCBieSA9ICJBbGlhcyIsIGNvcHkgPSBGQUxTRSkKcmVzZGYgPC0gbWVyZ2UocmVzZGYsIHBhX2dvLCBieSA9ICJBbGlhcyIsIGNvcHkgPSBGQUxTRSkKCmhlYWQocmVzZGYpCndyaXRlLmNzdihyZXNkZiwgcGFzdGUwKFN5cy5EYXRlKCkgLCAiX3Jlc3VsdHNfIixleHAsICJfIiwgdHJlYXRtZW50LCIudnMuIiwgY29udHJvbCwiLmNzdiIpLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIFNhdmUgREVHIGxpc3QKYGBge3Igc2F2ZV9kZWd9CiMgZmlsdGVyIGZvciBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyAoTEZDID49IDMsIHBhZGogPCBwdmFsX2N1dG9mZikKZGltKHJlc2RmKQpoZWFkKHJlc2RmKQoKc3VtbWFyeShpcy5uYShyZXNkZiRsb2cyRm9sZENoYW5nZSkpCnN1bW1hcnkoaXMubmEocmVzZGYkcGFkaikpCgpzaWdfZ2VuZXMgPC0gcmVzZGZbYWJzKHJlc2RmJGxvZzJGb2xkQ2hhbmdlKSA+PSBsb2dmY19jdXRvZmYgJiByZXNkZiRwYWRqIDwgcHZhbF9jdXRvZmYsIF0gICU+JSBkcm9wX25hKGxvZzJGb2xkQ2hhbmdlKQpzaWdfZ2VuZXMkZGlyZWN0aW9uIDwtIGlmZWxzZShzaWdfZ2VuZXMkbG9nMkZvbGRDaGFuZ2UgPiAwLCAidXAiLCAiZG93biIpCgpzdW1tYXJ5KGlzLm5hKHNpZ19nZW5lcyRsb2cyRm9sZENoYW5nZSkpCnN1bW1hcnkoaXMubmEoc2lnX2dlbmVzJHBhZGopKQoKZGltKHNpZ19nZW5lcykKaGVhZChzaWdfZ2VuZXMpCndyaXRlLmNzdihzaWdfZ2VuZXMsIHBhc3RlMChTeXMuRGF0ZSgpLCJfc2lnbmlmaWNhbnRnZW5lc18iLCBleHAsICJfIiwgdHJlYXRtZW50LCIudnMuIiwgY29udHJvbCwiLmNzdiIpLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIFBDQSBwbG90IApgYGB7ciBQQ0F9CnZzdCA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IHJhd2NvdW50cywgY29sRGF0YSA9IG1ldGFkYXRhLCBkZXNpZ24gPSB+IGV4cF8xMCArIGJhdGNoKQoKIyBWYXJpYW5jZSBzdGFiaWxpemluZyB0cmFuc2Zvcm1hdGlvbnMKdnNkIDwtIHZzdCh2c3QsIGJsaW5kID0gVFJVRSkKCiMgUENBIHBsb3QKcGNhRGF0YSA8LSBwbG90UENBKHZzZCwgaW50Z3JvdXAgPSBjKCJleHBfMTAiLCAiYmF0Y2giLCAiY29uZGl0aW9uIiksIHJldHVybkRhdGEgPSBUUlVFKQpwZXJjZW50VmFyIDwtIHJvdW5kKDEwMCAqIGF0dHIocGNhRGF0YSwgInBlcmNlbnRWYXIiKSkKCiMgQ2FsY3VsYXRlIHRoZSBtYXhpbXVtIGFic29sdXRlIHZhbHVlIGFtb25nIFBDMSBhbmQgUEMyCm1heF9hYnNfdmFsIDwtIG1heChjKGFicyhtaW4ocGNhRGF0YSRQQzEpKSwgYWJzKG1pbihwY2FEYXRhJFBDMikpLCBhYnMobWF4KHBjYURhdGEkUEMxKSksIGFicyhtYXgocGNhRGF0YSRQQzIpKSkpCgpheGlzX3NpemUgPC0gMTAKdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoYmFzZV9mYW1pbHkgPSAiQXJpYWwiKSkKCnBjYSA8LSBnZ3Bsb3QocGNhRGF0YSwgYWVzKFBDMSwgUEMyLCBjb2xvciA9IGNvbmRpdGlvbiwgc2hhcGUgPSBjb25kaXRpb24pKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKwogIHhsYWIocGFzdGUwKCJQQzE6ICIsIHBlcmNlbnRWYXJbMV0sICIlIHZhcmlhbmNlIikpICsKICB5bGFiKHBhc3RlMCgiUEMyOiAiLCBwZXJjZW50VmFyWzJdLCAiJSB2YXJpYW5jZSIpKSArCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksIDEwLCAxMSwgMTIsIDEzLCAxNCwgMTUsIDE2KSkgKwogIGNvb3JkX2ZpeGVkKHJhdGlvID0gMSwgeGxpbSA9IGMoLW1heF9hYnNfdmFsLCBtYXhfYWJzX3ZhbCksIHlsaW0gPSBjKC1tYXhfYWJzX3ZhbCwgbWF4X2Fic192YWwpKSArCiAgbGFicyhjb2xvciA9ICJjb25kaXRpb24iLCBzaGFwZSA9ICJjb25kaXRpb24iKSArCiAgZ3VpZGVzKHNoYXBlID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpLCAgIyBBZGp1c3Qgc2l6ZSBvZiBzaGFwZSBsZWdlbmQKICAgIGNvbG9yID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkNvbmRpdGlvbiIpKSArCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gYXhpc19zaXplKSwKICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUobGluZXdpZHRoID0gMC4yKSwKICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUobGluZXdpZHRoID0gMCwgY29sb3IgPSAiYmxhY2siKSwgICMgU2V0IHRoZSBheGlzIGxpbmUgbGluZXdpZHRoCiAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEsIGxpbmV3aWR0aCA9IDAuNSksICAjIFNldCB0aGUgcGFuZWwgYm9yZGVyIGxpbmV3aWR0aAogIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gTkEpICAjIFNldCBsZWdlbmQga2V5IGJhY2tncm91bmQgdG8gd2hpdGUgYW5kIHJlbW92ZSBib3JkZXIKICApCgpwcmludChwY2EpCgpjYWlyb19wZGYocGFzdGUwKFN5cy5EYXRlKCksIl9wY2FfIixleHAsICJfIiwgdHJlYXRtZW50LCIudnMuIiwgY29udHJvbCwiLnBkZiIsIHNlcCA9ICIiKSkKcGNhCmRldi5vZmYoKQoKYGBgCgojIFZvbGNhbm8gcGxvdApgYGB7ciB2b2xjYW5vfQpzZXF1ZW5jZSA8LSBjKCJ0cmVhdG1lbnQiKQoKZm9yIChpIGluIHNlcXVlbmNlKSB7CiAgICBzZXQuc2VlZCgwKQogICAgcmVzIDwtIHJlc3VsdHMoZGRzX2ZpbmFsLCBjb250cmFzdCA9IGMoImV4cF8xMCIsIGksICJjb250cm9sIikpCgogIGdwMiA8LSB3ZXNfcGFsZXR0ZXMkWmlzc291MQogIGtleSA8LSByZWFkLmNzdigiLi4vLi4vcmF3LWRhdGEvcGExNF9nZW5lX2tleS5jc3YiLCAgaGVhZGVyID0gVFJVRSkKCiAgcm93bmFtZXMoa2V5KSA8LSBrZXkkZ2VuZV9pZAoKICByZXMgPC0gbWVyZ2Uoa2V5LCBhcy5kYXRhLmZyYW1lKHJlcyksIGJ5PTApCiAgcmVzIDwtIGFzLmRhdGEuZnJhbWUocmVzKQogIHJlcyRBbGlhcyA8LSByb3duYW1lcyhyZXMpCgogIyBEZWZpbmUgZ2VuZSBsaXN0CiAgYWxnX2dlbmVzIDwtIGMoCiAgICAiYWxnQSIsICJhbGdGIiwgImFsZ0oiLCAiYWxnSSIsICJhbGdMIiwgImFsZ1giLCAiYWxnRyIsICJhbGdFIiwKICAgICJhbGdLIiwgImFsZzQ0IiwgImFsZzgiLCAiYWxnRCIsICJtdWNDIiwgIm11Y0IiLCAiYWxnVSIsICJhbGdXIiwKICAgICJhbGdQIiwgImFsZ1EiLCAiYWxnUiIsICJhbGdaIiwgImFsZ0MiLCAiYWxnQiIKICApCgpsb2dmY19jdXRvZmYKa2V5dmFscyA8LSBpZmVsc2UoCiByZXMkbG9nMkZvbGRDaGFuZ2UgPD0gLWxvZ2ZjX2N1dG9mZiAmIHJlcyRwYWRqIDw9IHB2YWxfY3V0b2ZmLCBncDJbMV0sCiAgaWZlbHNlKHJlcyRsb2cyRm9sZENoYW5nZSA+PSBsb2dmY19jdXRvZmYgJiByZXMkcGFkaiA8PSBwdmFsX2N1dG9mZiwgZ3AyWzVdLAogICAgICAgICAnbGlnaHRncmV5JykpCmtleXZhbHNbaXMubmEoa2V5dmFscyldIDwtICdsaWdodGdyZXknCm5hbWVzKGtleXZhbHMpW2tleXZhbHMgPT0gZ3AyWzVdXSA8LSAnVXAtcmVndWxhdGVkJwpuYW1lcyhrZXl2YWxzKVtrZXl2YWxzID09ICdsaWdodGdyZXknXSA8LSAnTlMnCm5hbWVzKGtleXZhbHMpW2tleXZhbHMgPT0gZ3AyWzFdXSA8LSAnRG93bi1yZWd1bGF0ZWQnCgp2b2xjYW5vIDwtIEVuaGFuY2VkVm9sY2FubyhyZXMsCiAgICAgICAgICAgICAgICAgICAgIGxhYiA9IHJlc1tbIm5hbWUiXV0sCiAgICAgICAgICAgICAgICAgICAgIHNlbGVjdExhYiA9IGFsZ19nZW5lcywKICAgICAgICAgICAgICAgICAgICAgeCA9ICdsb2cyRm9sZENoYW5nZScsCiAgICAgICAgICAgICAgICAgICAgIHkgPSAncGFkaicsCiAgICAgICAgICAgICAgICAgICAgIHhsYWIgPSBicXVvdGUofkxvZ1syXX4gJ2ZvbGQgY2hhbmdlJyksCiAgICAgICAgICAgICAgICAgICAgIHBDdXRvZmYgPSBwdmFsX2N1dG9mZiwKICAgICAgICAgICAgICAgICAgICAgRkNjdXRvZmYgPSBsb2dmY19jdXRvZmYsCiAgICAgICAgICAgICAgICAgICAgIGN1dG9mZkxpbmVUeXBlID0gImRhc2hlZCIsCiAgICAgICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDEsCiAgICAgICAgICAgICAgICAgICAgIGxhYlNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICAgICAgIGF4aXNMYWJTaXplID0gMTQsCiAgICAgICAgICAgICAgICAgICAgIGxhYkNvbCA9ICdibGFjaycsCiAgICAgICAgICAgICAgICAgICAgIGxhYkZhY2UgPSAnYm9sZCcsCiAgICAgICAgICAgICAgICAgICAgICNjb2wgPSBjKCdncmV5JywgZ3AyWzJdLCBncDJbM10sIGdwMlsxXSksCiAgICAgICAgICAgICAgICAgICAgIGNvbEN1c3RvbSA9IGtleXZhbHMsCiAgICAgICAgICAgICAgICAgICAgIGNvbEFscGhhID0gNS81LAogICAgICAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdib3R0b20nLAogICAgICAgICAgICAgICAgICAgICBsZWdlbmRMYWJTaXplID0gMTIsCiAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZEljb25TaXplID0gNC4wLAogICAgICAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgIGFycm93aGVhZHMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgd2lkdGhDb25uZWN0b3JzID0gMC4yLAogICAgICAgICAgICAgICAgICAgICBncmlkbGluZXMubWFqb3IgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgYm9yZGVyV2lkdGggPSAwLjMsCiAgICAgICAgICAgICAgICAgICAgIGdyaWRsaW5lcy5taW5vciA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICB0aXRsZSA9IHBhc3RlMCh0cmVhdG1lbnQsIiB2cyAiLCBjb250cm9sLCBzZXAgPSAiIiksCiAgICAgICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIiIsCiAgICAgICAgICAgICAgICAgICAgICNjYXB0aW9uID0gcGFzdGUwKCJ0b3RhbCA9ICIsIG5yb3codG9wdGFibGUpLCAiIHZhcmlhYmxlcyIpLAogICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gcGFzdGUwKCJWb2xjYW5vIHBsb3Qgd2l0aCBsb2cyIEZDIG9mICIsIGxvZ2ZjX2N1dG9mZiwiIGFuZCBQIHZhbHVlIG9mICIscHZhbF9jdXRvZmYsICIuIiksCiAgICAgICAgICAgICAgICAgICAgIG1heC5vdmVybGFwcyA9IDMwLAogICAgICAgICAgICAgICAgICAgICAjeWxpbSA9IGMoMCwxMCksCiAgICAgICAgICAgICAgICAgICAgIGNvbENvbm5lY3RvcnMgPSAnYmxhY2snKSArIAogICAgICB0aGVtZShheGlzLnRpY2tzPWVsZW1lbnRfbGluZShsaW5ld2lkdGggPTAuMikpICMgKwogIyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygtNSwgLTIuNSwgMCwgMi41LCA1KSwgbGltaXRzID0gYygtNiw2KSkKCnByaW50KHZvbGNhbm8pCgpjYWlyb19wZGYocGFzdGUwKFN5cy5EYXRlKCksIl92b2xjYW5vXyIsIGV4cCwgIl8iLCB0cmVhdG1lbnQsIi52cy4iLCBjb250cm9sLCIucGRmIiwgc2VwID0gIiIpKQpwcmludCh2b2xjYW5vKQpkZXYub2ZmKCkKfQoKYGBgCgojIE1BIHBsb3QKYGBge3IgTUFfcGxvdH0Kc2VxdWVuY2UgPC0gYygidHJlYXRtZW50IikKCmZvciAoaSBpbiBzZXF1ZW5jZSkgewogICAgc2V0LnNlZWQoMCkKCnJlcyA8LSByZXN1bHRzKGRkc19maW5hbCwgY29udHJhc3QgPSBjKCJleHBfMTAiLCBpLCAiY29udHJvbCIpKQoKZ3AyIDwtIHdlc19wYWxldHRlcyRaaXNzb3UxCgpyZXMkZ2VuZV9pZCA8LSByb3duYW1lcyhyZXMpCnJlcyA8LSBhcy5kYXRhLmZyYW1lKHJlcykKaGVhZChyZXMpCnJlcyA8LSBmdWxsX2pvaW4oa2V5LCBhcy5kYXRhLmZyYW1lKHJlcyksIGJ5PSJnZW5lX2lkIikKcm93bmFtZXMocmVzKSA8LSByZXMkQWxpYXMKCmFueShpcy5uYShyZXMpKSAgIyBDaGVjayBpZiB0aGVyZSBhcmUgYW55IE5BcwoKcmVzIDwtIHJlcyAlPiUgZmlsdGVyKCFpcy5uYShiYXNlTWVhbikpCgoKbWEgPC0gZ2dtYXBsb3QocmVzLCAKICAgICAgICAgICAgICAgZmRyID0gcHZhbF9jdXRvZmYsIAogICAgICAgICAgICAgICBmYyA9IDJeKGxvZ2ZjX2N1dG9mZiksIAogICAgICAgICAgICAgICBzaXplID0gMSwKICAgICAgICAgICAgICAgcGFsZXR0ZSA9IGMoKGdwMls1XSksIChncDJbMV0pKSwKICAgICAgICAgICAgICAgc2VsZWN0LnRvcC5tZXRob2QgPSAiZmMiLAogICAgICAgICAgICAgIyAgeWxpbSA9IGMoLTE1LDE1KSwKICAgICAgICAgICAgICAgbGVnZW5kID0gImJvdHRvbSIsIAogICAgICAgICAgICAgICB0aXRsZSA9IHBhc3RlMCh0cmVhdG1lbnQsIiB2cyAiLCBjb250cm9sLCBzZXAgPSAiIiksCiAgICAgICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoIlZvbGNhbm8gcGxvdCB3aXRoIGxvZzIgRkMgb2YgIiwgbG9nZmNfY3V0b2ZmLCIgYW5kIFAgdmFsdWUgb2YgIixwdmFsX2N1dG9mZiwgIi4iKSwKICAgICAgICAgICAgICAgZm9udC5sYWJlbCA9IGMoIDEyKSwgCiAgICAgICAgICAgICBsYWJlbC5yZWN0YW5nbGUgPSBGQUxTRSwKICAgICAgICAgICAgICBnZW5lbmFtZXMgPSByZXMkbmFtZSwKICAgICAgICAgICAgICBmb250LmxlZ2VuZCA9IGMoMTIpLAogICAgICAgICAgICAgICBmb250Lm1haW4gPSBjKCJib2xkIiwgMTQpLAogICAgICAgICAgICAgICBhbHBoYSA9IDEuNSwKICAgICAgICAgICAgICAgZ2d0aGVtZSA9IGdncGxvdDI6OnRoZW1lKHBhbmVsLmdyaWQgPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpKSkgCnByaW50KG1hKQoKY2Fpcm9fcGRmKHBhc3RlMChTeXMuRGF0ZSgpLCJfbWFfIiwgZXhwLCAiXyIsIHRyZWF0bWVudCwiLnZzLiIsIGNvbnRyb2wsIi5wZGYiKSkKcHJpbnQobWEpCmRldi5vZmYoKQp9CmBgYAoK