Differential gene expression analysis for Pacific cod RNAseq data.

  • Raw reads found here
  • Reads aligned to genome downloaded from NCBI
  • NOTE this analysis is for the featureCounts exons (see 06.2-cod-RNAseq-alignment-genome)

0.0.1 Install and load packages

## clear
rm(list=ls())

## Install Rtools directly from (https://cran.r-project.org/bin/windows/Rtools/), then install these on first run:
# install.packages("BiocManager")
# BiocManager::install("DESeq2")
# BiocManager::install("vsn")
# BiocManager::install("tidybulk")
# BiocManager::install("goseq")
# BiocManager::install("affycoretools")
# BiocManager::install("EnhancedVolcano")
# BiocManager::install("pcaExplorer")
# BiocManager::install("apeglm")
# BiocManager::install("PCAtools")


# List of packages we want to install (run every time)
load.lib<-c("DESeq2","edgeR","goseq","dplyr","GenomicFeatures","data.table","calibrate","affycoretools","data.table","vsn","tidybulk","ggplot2","cowplot","pheatmap","gplots","RColorBrewer","EnhancedVolcano","pcaExplorer","readxl","apeglm","ashr","tibble","plotly","sqldf","PCAtools","ggpubr","beepr","genefilter","ComplexHeatmap","circlize","scales", "tidyverse", "gridextra'")

# Select only the packages that aren't currently installed (run every time)
# install.lib <- load.lib[!load.lib %in% installed.packages()]

# And finally we install the missing packages, including their dependency.
# for(lib in install.lib) install.packages(lib,dependencies=TRUE)
# After the installation process completes, we load all packages.
sapply(load.lib,require,character=TRUE)
         DESeq2           edgeR           goseq           dplyr GenomicFeatures 
           TRUE            TRUE            TRUE            TRUE            TRUE 
     data.table       calibrate   affycoretools      data.table             vsn 
           TRUE            TRUE            TRUE            TRUE            TRUE 
       tidybulk         ggplot2         cowplot        pheatmap          gplots 
           TRUE            TRUE            TRUE            TRUE            TRUE 
   RColorBrewer EnhancedVolcano     pcaExplorer          readxl          apeglm 
           TRUE            TRUE            TRUE            TRUE            TRUE 
           ashr          tibble          plotly           sqldf        PCAtools 
           TRUE            TRUE            TRUE            TRUE            TRUE 
         ggpubr           beepr      genefilter  ComplexHeatmap        circlize 
           TRUE            TRUE            TRUE           FALSE            TRUE 
         scales       tidyverse      gridextra' 
           TRUE            TRUE           FALSE 

I found the DESeq2 vignette and the HBC DGE training workshop super helpful in figuring out how to use the DESeq2 package!

1 Load data

1.1 Load count data

Load in the count matrix we generated after alignment using the featureCounts. We also need to slightly reformat the count matrix to make all of the estimated counts integers, as required for DESeq2.

# Read in counts data. This is a gene-level counts matrix generated from hisat2 and summarized using featureCounts
cod_counts_data_OG <- read_delim("../output/06.2-cod-RNAseq-alignment-genome/featureCounts-exon/featureCounts_exon_matrix_noheader.txt", delim="\t") 
head(cod_counts_data_OG)
# A tibble: 6 × 86
  Geneid       Chr              Start End   Strand Length ../output/06.2-cod-R…¹
  <chr>        <chr>            <chr> <chr> <chr>   <dbl>                  <dbl>
1 LOC132464423 NC_082382.1;NC_… 7826… 8896… +;+      1618                      6
2 rereb        NC_082382.1;NC_… 4475… 4490… +;+;+…   5887                    236
3 LOC132464476 NC_082382.1;NC_… 6269… 6305… -;-      1468                      2
4 LOC132464448 NC_082382.1;NC_… 7316… 7404… -;-;-…   5017                      0
5 c1h1orf159   NC_082382.1;NC_… 8431… 8452… -;-;-…   1093                      0
6 LOC132464512 NC_082382.1;NC_… 8922… 8959… +;+;+…   1720                      0
# ℹ abbreviated name:
#   ¹​`../output/06.2-cod-RNAseq-alignment-genome/hisat2/100.sorted.bam`
# ℹ 79 more variables:
#   `../output/06.2-cod-RNAseq-alignment-genome/hisat2/107.sorted.bam` <dbl>,
#   `../output/06.2-cod-RNAseq-alignment-genome/hisat2/108.sorted.bam` <dbl>,
#   `../output/06.2-cod-RNAseq-alignment-genome/hisat2/109.sorted.bam` <dbl>,
#   `../output/06.2-cod-RNAseq-alignment-genome/hisat2/10.sorted.bam` <dbl>, …

1.2 Count data munging

# # We need to modify this data frame so that the row names are actually row names, instead of comprising the first column
cod_counts_data <- cod_counts_data_OG %>% 
  column_to_rownames(var = "Geneid")

# Additional formatting
# Remove unnecessary columns 
cod_counts_data <- subset(cod_counts_data, select = -c(Chr, Start, End, Strand, Length))

# Remove the directory path and file type portions of the column names, to leave just the sample names
colnames(cod_counts_data) <- sub("../output/06.2-cod-RNAseq-alignment-genome/hisat2/", "sample_", colnames(cod_counts_data))
colnames(cod_counts_data) <- sub(".sorted.bam", "", colnames(cod_counts_data))

# Reorder the coumns into alphabetical order (to make it easier to create an associated metadata spreadsheet)
cod_counts_data <- cod_counts_data[, order(colnames(cod_counts_data))]

cod_sample_names <- names(cod_counts_data)

write.table(cod_counts_data, file = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/Gmac_genome_exon_counts_formatted.tab", sep = "\t",
            row.names = TRUE, col.names = NA)

head(cod_counts_data)
             sample_1 sample_10 sample_100 sample_107 sample_108 sample_109
LOC132464423        1         5          6          3         20          0
rereb             465       547        236        121        415        168
LOC132464476        1         1          2          0          5          1
LOC132464448        6         3          0          0          4          0
c1h1orf159          1         8          0          3          3          0
LOC132464512        0         7          0          2          0          1
             sample_11 sample_110 sample_117 sample_118 sample_119 sample_12
LOC132464423         0          4          3          0          0         3
rereb              342        204        335        267        179       395
LOC132464476         0          0          0          0          0         0
LOC132464448         2          0          2          0          1         2
c1h1orf159           2         10          3          9          8         3
LOC132464512         0          1          0          0          2         0
             sample_120 sample_121 sample_127 sample_128 sample_129 sample_13
LOC132464423          1         26          2          2          9         0
rereb               393        224        317        111         17       445
LOC132464476          0          0          0          0          0         3
LOC132464448          2          3          2          0          0         4
c1h1orf159            8          2          5          1          0         6
LOC132464512          1          0          1          0          3         2
             sample_131 sample_137 sample_138 sample_139 sample_140 sample_147
LOC132464423          7          0          0          0          2          2
rereb               150         75         45         72         78         94
LOC132464476          1          0          0          0          0          2
LOC132464448          3          0          0          1          0          1
c1h1orf159            1          2          0          2          1          0
LOC132464512          0          0          1          1          0          0
             sample_148 sample_149 sample_150 sample_18 sample_19 sample_19-G
LOC132464423         13         37         21         4        20          25
rereb               352        778        261       353       210         663
LOC132464476          2          0          2         2         2           6
LOC132464448          5         25          2         1         5          30
c1h1orf159            5         69          4         3         0          29
LOC132464512          0          1          1         2         2          11
             sample_19-S sample_2 sample_20 sample_20-G sample_20-S sample_21
LOC132464423          48        2         1          18          65         2
rereb                984      305       231         722         820       337
LOC132464476           6        0         1           3           4         1
LOC132464448          38        2         2          26          37         3
c1h1orf159            54        9         1          68          14         2
LOC132464512          19        1         0           4          22         7
             sample_28 sample_29 sample_3 sample_30 sample_31 sample_37
LOC132464423         0         1        2         2         0         3
rereb              274       353      301       486       241       124
LOC132464476         1         1        4         0         1         2
LOC132464448         5         3        8         6         5         2
c1h1orf159           3         0       10         4         2         0
LOC132464512         0         1        2         4         0         1
             sample_38 sample_39 sample_4 sample_40 sample_41 sample_47
LOC132464423         1         1        1         3        24        11
rereb              132       117      418        70       192       127
LOC132464476         0         0        0         4        15         7
LOC132464448         2         4        2         1         1         0
c1h1orf159           0         4        0         2         0         3
LOC132464512         0         0        0         0         2         0
             sample_48 sample_49 sample_5 sample_50 sample_57 sample_57-G
LOC132464423         8         6        6         3         1           7
rereb              115       267      270       241       223         836
LOC132464476         0         5        0         2         0           3
LOC132464448         3         1        8         0         1          38
c1h1orf159           3         4        4         8         5          52
LOC132464512         0         3        0         0         0           1
             sample_57-S sample_58 sample_58-G sample_58-S sample_59 sample_60
LOC132464423          33         6           9          31         6        10
rereb                 62       213        1065         390       149       289
LOC132464476          19         5           6          30         4         0
LOC132464448           0         2          35           4         0         5
c1h1orf159             0         0          42           0         0         0
LOC132464512           0         0           2           3         0         0
             sample_67 sample_68 sample_69 sample_70 sample_78 sample_79
LOC132464423         0         1         1        10        13         2
rereb              337       293       210       122       154       156
LOC132464476         1         1         0         2         0         0
LOC132464448         3         1         1         2         5         1
c1h1orf159           7         7         2         0         1         4
LOC132464512         0         0         3         0         0         0
             sample_80 sample_83 sample_88 sample_90 sample_91 sample_92
LOC132464423         1         0        22         3         1         0
rereb              224       158       174       155       396       215
LOC132464476         0         1         0         1         0         0
LOC132464448         1         2         4         0         2         4
c1h1orf159           0         0         1         1         9         5
LOC132464512         1         0         0         0         1         1
             sample_97 sample_98 sample_99 sample_RESUB-116 sample_RESUB-156
LOC132464423         2        52         5                3                2
rereb              137        81       193              380              249
LOC132464476         1        13         3                1                1
LOC132464448         0         6         0                4                5
c1h1orf159           0         0         3                5                4
LOC132464512         2         0         0                1                0
             sample_RESUB-36 sample_RESUB-76 sample_RESUB-94
LOC132464423               6               1               0
rereb                    114             165             463
LOC132464476               0               1               0
LOC132464448               2               1               1
c1h1orf159                 4               0               3
LOC132464512               1               0               1
cod_sample_names
 [1] "sample_1"         "sample_10"        "sample_100"       "sample_107"      
 [5] "sample_108"       "sample_109"       "sample_11"        "sample_110"      
 [9] "sample_117"       "sample_118"       "sample_119"       "sample_12"       
[13] "sample_120"       "sample_121"       "sample_127"       "sample_128"      
[17] "sample_129"       "sample_13"        "sample_131"       "sample_137"      
[21] "sample_138"       "sample_139"       "sample_140"       "sample_147"      
[25] "sample_148"       "sample_149"       "sample_150"       "sample_18"       
[29] "sample_19"        "sample_19-G"      "sample_19-S"      "sample_2"        
[33] "sample_20"        "sample_20-G"      "sample_20-S"      "sample_21"       
[37] "sample_28"        "sample_29"        "sample_3"         "sample_30"       
[41] "sample_31"        "sample_37"        "sample_38"        "sample_39"       
[45] "sample_4"         "sample_40"        "sample_41"        "sample_47"       
[49] "sample_48"        "sample_49"        "sample_5"         "sample_50"       
[53] "sample_57"        "sample_57-G"      "sample_57-S"      "sample_58"       
[57] "sample_58-G"      "sample_58-S"      "sample_59"        "sample_60"       
[61] "sample_67"        "sample_68"        "sample_69"        "sample_70"       
[65] "sample_78"        "sample_79"        "sample_80"        "sample_83"       
[69] "sample_88"        "sample_90"        "sample_91"        "sample_92"       
[73] "sample_97"        "sample_98"        "sample_99"        "sample_RESUB-116"
[77] "sample_RESUB-156" "sample_RESUB-36"  "sample_RESUB-76"  "sample_RESUB-94" 

1.3 Import sample metadata sheets

# Read in the csv file as a data frame
cod_sample_info_OG <- read.csv("~/project-cod-temperature/data/DESeq2_Sample_Information.csv")
cod_experiment_alldata_OG <- read.csv("~/project-cod-temperature/data/temp-experiment.csv")
head(cod_sample_info_OG)
  sample_name sample_number tank temp_treatment tissue_type
1    sample_1             1    1             16       Liver
2   sample_10            10    2             16       Liver
3  sample_100           100   15              9       Liver
4  sample_107           107   16              9       Liver
5  sample_108           108   16              9       Liver
6  sample_109           109   16              9       Liver
head(cod_experiment_alldata_OG)
  Microchip.ID SL_11212022 WWT_11212022 Tank Temperature SL_12272022
1          620          93         8.53    1          16         101
2         1164          88         7.06    1          16          96
3         1476         102        10.70    1          16         108
4         9387          87         7.83    1          16          95
5         9407         100        11.51    1          16         117
6         9415          92         8.68    1          16         100
  WWT_12272022 MortDate DissectionDate SL_mm WholeBodyWW_g TOTAL_Liver_WW_mg
1        11.12                  2/8/23   119         16.15            0.4945
2         8.64                  2/8/23   105         10.89            0.1997
3        12.25                  2/8/23   110         12.97            0.1715
4        10.16                  2/8/23   116         15.40            0.3625
5        14.98                  2/8/23   127         17.98            0.3482
6        10.96                  2/8/23   114         14.02            0.2343
  LiverforLipids_WW_mg MuscleWWforLipids_mg GeneticSamplingCount
1               0.1546               0.3495                    8
2               0.1091               0.3328                    5
3               0.1107               0.3834                    4
4               0.1681               0.3262                    6
5               0.1210               0.3434                    2
6               0.1342               0.2776                    9
  DissectionComments
1                   
2                   
3                   
4                   
5                   
6                   
# Rename the "GeneticSamplingCount" column of the experimental data to "sample_number"
cod_experiment_alldata <- cod_experiment_alldata_OG
names(cod_experiment_alldata)[names(cod_experiment_alldata) == "GeneticSamplingCount"] <- "sample_number"

# Calculate length difference and weight difference (end-beginning)
cod_experiment_alldata$SL_diff_mm <- cod_experiment_alldata$SL_mm - cod_experiment_alldata$SL_11212022
cod_experiment_alldata$WWT_diff_g <- cod_experiment_alldata$WholeBodyWW_g - cod_experiment_alldata$WWT_11212022

# Merge the two data frames to get experimental data for all of our RNAseq'd samples.
# This should include all rows from cod_sample_info_OG and matching rows from cod_experiment_alldata based on the shared sample_number column. Sample number duplicates (e.g. from different tissue types) should be retained.
cod_sample_info <- merge(cod_sample_info_OG, cod_experiment_alldata, by = "sample_number", all.x = TRUE)

# Reorder the data frame into alphabetical order by the sample names, so that the rows are in the same order as our count matrix columns
cod_sample_info <- cod_sample_info[order(cod_sample_info$sample_name), ]

# Again, we need to reformat so that the data in the first column becomes the row names
rownames(cod_sample_info) <- cod_sample_info$sample_name

# Remove duplicate columns (artifact of merging data frames with multiple shared columns and of maing sample_name the rownames instead of a variable)
cod_sample_info <- subset(cod_sample_info, select=-Temperature)
cod_sample_info <- subset(cod_sample_info, select=-Tank)
#cod_sample_info <- subset(cod_sample_info, select=-sample_name)


head(cod_sample_info)
           sample_number sample_name tank temp_treatment tissue_type
sample_1               1    sample_1    1             16       Liver
sample_10             10   sample_10    2             16       Liver
sample_100           100  sample_100   15              9       Liver
sample_107           107  sample_107   16              9       Liver
sample_108           108  sample_108   16              9       Liver
sample_109           109  sample_109   16              9       Liver
           Microchip.ID SL_11212022 WWT_11212022 SL_12272022 WWT_12272022
sample_1           9443          99        10.54         108        12.94
sample_10          9518          95         9.45         105        12.67
sample_100         9483          70         4.54          78         5.23
sample_107         4236          94         9.15         104        11.44
sample_108         9416          81         6.26          91         7.87
sample_109         9481          89         7.77          95         9.49
           MortDate DissectionDate SL_mm WholeBodyWW_g TOTAL_Liver_WW_mg
sample_1                    2/8/23   114         14.39            0.0896
sample_10                   2/8/23   120         16.22            0.3854
sample_100                  2/9/23    93          8.33            0.2558
sample_107                  2/9/23   119         16.41            0.5612
sample_108                  2/9/23   106         11.67            0.3650
sample_109                  2/9/23   116         11.45            0.3088
           LiverforLipids_WW_mg MuscleWWforLipids_mg DissectionComments
sample_1                 0.0704               0.3899      lipid inserts
sample_10                0.1285               0.2967                   
sample_100               0.1143               0.3483                   
sample_107               0.1503               0.3322                   
sample_108               0.1125               0.3612                   
sample_109               0.1090               0.3062                   
           SL_diff_mm WWT_diff_g
sample_1           15       3.85
sample_10          25       6.77
sample_100         23       3.79
sample_107         25       7.26
sample_108         25       5.41
sample_109         27       3.68

1.4 Sample metadata munging

# Factor variables
cod_sample_info$temp_treatment <- factor(cod_sample_info$temp_treatment)
cod_sample_info$tank <- factor(cod_sample_info$tank)
cod_sample_info$tissue_type <- factor(cod_sample_info$tissue_type)

# Remove bad/missing samples
# MuliQC report: 149, 129
# PCA outliers: 31, 41 (per Laura)
cod_sample_info <- cod_sample_info[!(row.names(cod_sample_info) %in% c("sample_149", "sample_129", "sample_31", "sample_41")),]
cod_counts_data <- as.matrix(subset(cod_counts_data, select=-c(sample_149, sample_129, sample_31, sample_41)))

# Check that the column names of our count data match the row names of our sample info sheet
ncol(cod_counts_data)
[1] 76
nrow(cod_sample_info)
[1] 76
all(colnames(cod_counts_data) %in% rownames(cod_sample_info))
[1] TRUE
all(colnames(cod_counts_data) == rownames(cod_sample_info))
[1] TRUE

Combine counts data and sample metadata for later analyses

# Melt cod_counts_data to long format
cod_counts_data_long <- as.data.frame(cod_counts_data)
cod_counts_data_long$gene <- rownames(cod_counts_data_long)
cod_counts_data_long <- cod_counts_data_long %>% 
  pivot_longer(cols = starts_with("sample"), 
               names_to = "sample_name", 
               values_to = "count")

colnames(cod_counts_data_long)
[1] "gene"        "sample_name" "count"      
colnames(cod_sample_info)
 [1] "sample_number"        "sample_name"          "tank"                
 [4] "temp_treatment"       "tissue_type"          "Microchip.ID"        
 [7] "SL_11212022"          "WWT_11212022"         "SL_12272022"         
[10] "WWT_12272022"         "MortDate"             "DissectionDate"      
[13] "SL_mm"                "WholeBodyWW_g"        "TOTAL_Liver_WW_mg"   
[16] "LiverforLipids_WW_mg" "MuscleWWforLipids_mg" "DissectionComments"  
[19] "SL_diff_mm"           "WWT_diff_g"          
# Merge cod_counts_data_long with df_C to get treatment info
cod_countsdata_plus_sampleinfo <- left_join(cod_counts_data_long, cod_sample_info, by = "sample_name")

2 Preliminary PCA visualization (liver tissue)

2.1 DESeq object

# Filter data
infosub_L <- cod_sample_info %>% filter(tissue_type == "Liver")
countsub_L <- subset(cod_counts_data, select=row.names(infosub_L))

# Calculate DESeq object
dds_L <- DESeqDataSetFromMatrix(countData = countsub_L,
                              colData = infosub_L,
                              design = ~ temp_treatment) 

# Run differential expression analysis 
# (Note that this DESeq() function runs all necessary steps, including data normalization, 
# estimating size factors, estimating dispersions, gene-wise dispersion estimates, mean-dispersion 
# relationship, final dispersion estimates, fitting model, and testing)
dds_L <- DESeq(dds_L)
resultsNames(dds_L) # lists the coefficients
[1] "Intercept"              "temp_treatment_5_vs_0"  "temp_treatment_9_vs_0" 
[4] "temp_treatment_16_vs_0"
plotDispEsts(dds_L)

2.2 PCA visualization

# Generate PCAs
# top 500 most variable genes
pca_L_500<- plotPCA(vst(dds_L), intgroup = c("temp_treatment"), returnData=TRUE)
percentVar_L_500 <- round(100*attr(pca_L_500, "percentVar"))
# merge with metadata sheet so we can plot using other features
pca_L_500 <- subset(pca_L_500, select=-temp_treatment) #remove the temp_treatment column, which will be a duplicate post-merge
pca_L_500 <- merge(pca_L_500, cod_sample_info, by.x = "name", by.y = "row.names")

# top 1000 most variable genes
pca_L_1000 <- plotPCA(vst(dds_L), intgroup = c("temp_treatment"), returnData=TRUE, ntop=1000)
percentVar_L_1000 <- round(100*attr(pca_L_1000, "percentVar"))
# merge with metadata sheet so we can plot using other features
pca_L_1000 <- subset(pca_L_1000, select=-temp_treatment) #remove the temp_treatment column, which will be a duplicate post-merge
pca_L_1000 <- merge(pca_L_1000, cod_sample_info, by.x = "name", by.y = "row.names")

# all genes
pca_L_all <- plotPCA(vst(dds_L), intgroup = c("temp_treatment"), returnData=TRUE, ntop=nrow(assay(vst(dds_L))))
percentVar_L_all <- round(100*attr(pca_L_all, "percentVar"))
# merge with metadata sheet so we can plot using other features
pca_L_all <- subset(pca_L_all, select=-temp_treatment) #remove the temp_treatment column, which will be a duplicate post-merge
pca_L_all <- merge(pca_L_all, cod_sample_info, by.x = "name", by.y = "row.names")

# Assign specific colors to each temperature treatment level
temp_colors <- c(
  "0" = "darkblue",
  "5" = "royalblue1",
  "9" = "green",
  "16" = "orangered") 

# Plot PCAs
p.L.500 <- ggplot(pca_L_500, aes(PC1, PC2, color=temp_treatment)) + 
  geom_point(size=4, alpha = 5/10) +
  ggtitle("Liver, top 500 most variable genes") +
  xlab(paste0("PC1: ",percentVar_L_500[1],"% variance")) +
  ylab(paste0("PC2: ",percentVar_L_500[2],"% variance")) + 
  coord_fixed() +
  scale_color_manual(values=temp_colors)+
  stat_ellipse()

p.L.500.SLdiff <- ggplot(pca_L_500, aes(PC1, PC2, color=temp_treatment, size=SL_diff_mm)) + 
  geom_point(alpha = 0.5) +
  ggtitle("Liver, top 500 most variable genes") +
  xlab(paste0("PC1: ", percentVar_L_500[1], "% variance")) +
  ylab(paste0("PC2: ", percentVar_L_500[2], "% variance")) + 
  coord_fixed() +
  scale_color_manual(values = temp_colors) +
  scale_size_continuous() +  # Add this line to control the size of points
  stat_ellipse()

p.L.500.WWTdiff <- ggplot(pca_L_500, aes(PC1, PC2, color=temp_treatment, size=WWT_diff_g)) + 
  geom_point(alpha = 0.5) +
  ggtitle("Liver, top 500 most variable genes") +
  xlab(paste0("PC1: ", percentVar_L_500[1], "% variance")) +
  ylab(paste0("PC2: ", percentVar_L_500[2], "% variance")) + 
  coord_fixed() +
  scale_color_manual(values = temp_colors) +
  scale_size_continuous() +  # Add this line to control the size of points
  stat_ellipse()

p.L.1000 <- ggplot(pca_L_1000, aes(PC1, PC2, color=temp_treatment)) + 
  geom_point(size=4, alpha = 5/10) +
  ggtitle("Liver, top 1000 most variable genes") +
  xlab(paste0("PC1: ",percentVar_L_1000[1],"% variance")) +
  ylab(paste0("PC2: ",percentVar_L_1000[2],"% variance")) + 
  coord_fixed() +
  scale_color_manual(values=temp_colors)+
  stat_ellipse()

p.L.1000.SLdiff <- ggplot(pca_L_1000, aes(PC1, PC2, color=temp_treatment, size=SL_diff_mm)) + 
  geom_point(alpha = 0.5) +
  ggtitle("Liver, top 1000 most variable genes") +
  xlab(paste0("PC1: ", percentVar_L_500[1], "% variance")) +
  ylab(paste0("PC2: ", percentVar_L_500[2], "% variance")) + 
  coord_fixed() +
  scale_color_manual(values = temp_colors) +
  scale_size_continuous() +  # Add this line to control the size of points
  stat_ellipse()

p.L.1000.WWTdiff <- ggplot(pca_L_1000, aes(PC1, PC2, color=temp_treatment, size=WWT_diff_g)) + 
  geom_point(alpha = 0.5) +
  ggtitle("Liver, top 1000 most variable genes") +
  xlab(paste0("PC1: ", percentVar_L_500[1], "% variance")) +
  ylab(paste0("PC2: ", percentVar_L_500[2], "% variance")) + 
  coord_fixed() +
  scale_color_manual(values = temp_colors) +
  scale_size_continuous() +  # Add this line to control the size of points
  stat_ellipse()

p.L.all <- ggplot(pca_L_all, aes(PC1, PC2, color=temp_treatment)) + 
  geom_point(size=4, alpha = 5/10) +
  ggtitle("Liver, all genes") +
  xlab(paste0("PC1: ",percentVar_L_all[1],"% variance")) +
  ylab(paste0("PC2: ",percentVar_L_all[2],"% variance")) + 
  coord_fixed() +
  scale_color_manual(values=temp_colors)+
  stat_ellipse()

p.L.all.SLdiff <- ggplot(pca_L_all, aes(PC1, PC2, color=temp_treatment, size=SL_diff_mm)) + 
  geom_point(alpha = 0.5) +
  ggtitle("Liver, all genes") +
  xlab(paste0("PC1: ", percentVar_L_500[1], "% variance")) +
  ylab(paste0("PC2: ", percentVar_L_500[2], "% variance")) + 
  coord_fixed() +
  scale_color_manual(values = temp_colors) +
  scale_size_continuous() +  # Add this line to control the size of points
  stat_ellipse()

p.L.all.WWTdiff <- ggplot(pca_L_all, aes(PC1, PC2, color=temp_treatment, size=WWT_diff_g)) + 
  geom_point(alpha = 0.5) +
  ggtitle("Liver, all genes") +
  xlab(paste0("PC1: ", percentVar_L_500[1], "% variance")) +
  ylab(paste0("PC2: ", percentVar_L_500[2], "% variance")) + 
  coord_fixed() +
  scale_color_manual(values = temp_colors) +
  scale_size_continuous() +  # Add this line to control the size of points
  stat_ellipse()

# View PCAs
p.L.500

p.L.500.SLdiff

p.L.500.WWTdiff

p.L.1000

p.L.1000.SLdiff

p.L.1000.WWTdiff

p.L.all

p.L.all.SLdiff

p.L.all.WWTdiff

# Export PCAs as pngs
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-PCA_L_500.png", plot = p.L.500, res = 600, width = 6000, height = 4000)

ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-PCA_L_1000.png", plot = p.L.1000, res = 600, width = 6000, height = 4000)

ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-PCA_L_all.png", plot = p.L.all, res = 600, width = 6000, height = 4000)

3 Liver tissue, 9C v. 16C

The 9*C temperature treatment is effectively our “control,” as it represents the ambient temperature that wild juvenile Pacific cod would experience.

# liver tissue, temperatures 9 vs. 16 

# Filter data
infosub_L.9.16 <- cod_sample_info %>% filter(tissue_type == "Liver" & (temp_treatment == "9" | temp_treatment == "16"))
countsub_L.9.16 <- subset(cod_counts_data, select=row.names(infosub_L.9.16))

# Calculate DESeq object
dds_L.9.16 <- DESeqDataSetFromMatrix(countData = countsub_L.9.16,
                              colData = infosub_L.9.16,
                              design = ~ temp_treatment)

dds_L.9.16 <- DESeq(dds_L.9.16)
resultsNames(dds_L.9.16) # lists the coefficients
[1] "Intercept"              "temp_treatment_16_vs_9"
plotDispEsts(dds_L.9.16)

# Filtering: keep genes that have at least 10 counts across 1/3 of the samples - https://support.bioconductor.org/p/110307/
keep <- rowSums(DESeq2::counts(dds_L.9.16) >= 10) >= ncol(countsub_L.9.16)/3
dds_L.9.16<- dds_L.9.16[keep,]

# Generate Contrasts
contrast_list_L.9.16        <- c("temp_treatment", "16", "9") # order is important: factor, treatment group, control
res_table_L.9.16_noshrink <- results(dds_L.9.16, contrast=contrast_list_L.9.16, alpha = 0.05)

res_table_L.9.16_norm     <- lfcShrink(dds_L.9.16,
                                       coef=2,
                                       type="normal") # lfcThreshold = 0.585)  # a lfc threshold of 1 = 2-fold change, 0.585 = 1.5-fold change
res_table_L.9.16_apeglm   <- lfcShrink(dds_L.9.16,
                                       coef=2, 
                                       type="apeglm") # lfcThreshold = 0.585)  # a lfc threshold of 1 = 2-fold change, 0.585 = 1.5-fold change
res_table_L.9.16_ashr     <- lfcShrink(dds_L.9.16,
                                       coef=2, 
                                       type="ashr")
# Generate MA plots
par(mfrow=c(2,2), mar=c(4,4,2,1))
xlim <- c(1,1e5); ylim <- c(-4,4)
DESeq2::plotMA(res_table_L.9.16_noshrink, xlim=xlim, ylim=ylim, main="no shrink")
DESeq2::plotMA(res_table_L.9.16_norm, xlim=xlim, ylim=ylim, main="normal")
DESeq2::plotMA(res_table_L.9.16_apeglm, xlim=xlim, ylim=ylim, main="apeglm")
DESeq2::plotMA(res_table_L.9.16_ashr, xlim=xlim, ylim=ylim, main="ashr")

# Examine results formatting
res_table_L.9.16_norm %>% data.frame() %>% head()
              baseMean log2FoldChange     lfcSE       stat       pvalue
rereb        262.72405     0.44093999 0.1274573  3.4590881 0.0005420075
p4htmb        73.90676     0.61162744 0.2143905  2.8511799 0.0043557321
LOC132464555 521.80884     0.05089259 0.0933051  0.5454549 0.5854406870
abhd14a       89.12868     0.12150643 0.1194928  1.0168713 0.3092146703
LOC132464547  65.32804    -0.48357310 0.1942092 -2.4915335 0.0127192973
tusc2b       139.10778    -0.37679681 0.1693066 -2.2261841 0.0260018556
                    padj
rereb        0.003178632
p4htmb       0.016670447
LOC132464555 0.699748497
abhd14a      0.445645789
LOC132464547 0.039057208
tusc2b       0.067900354

Note that the metric we want to use to identify significantly expressed genes is the padj values, NOT the pvalue. padj are p-values corrected for multiple testing (default method is the Benjamini and Hochberg method).

summary(res_table_L.9.16_noshrink)

out of 14245 with nonzero total read count
adjusted p-value < 0.05
LFC > 0 (up)       : 2174, 15%
LFC < 0 (down)     : 2841, 20%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 6)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.16_norm)

out of 14245 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 2701, 19%
LFC < 0 (down)     : 3425, 24%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 6)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.16_apeglm)

out of 14245 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 2701, 19%
LFC < 0 (down)     : 3425, 24%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 6)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.16_ashr)

out of 14245 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 2701, 19%
LFC < 0 (down)     : 3425, 24%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 6)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results

4 Extracting significantly expressed genes

padj.cutoff <- 0.05
lfc.cutoff <- 0.58

# Convert results table into tibble
res_table_L.9.16_norm_tb <- res_table_L.9.16_norm %>%
  data.frame() %>%
  rownames_to_column(var="gene") %>%
  as_tibble()

# subset that table to only keep the significant genes using our pre-defined thresholds:
sig_L.9.16_norm_noLFCcutoff <- res_table_L.9.16_norm_tb %>%
  filter(padj < padj.cutoff)

sig_L.9.16_norm <- sig_L.9.16_norm_noLFCcutoff %>% 
  filter(abs(log2FoldChange) > lfc.cutoff)

head(sig_L.9.16_norm_noLFCcutoff)
# A tibble: 6 × 7
  gene         baseMean log2FoldChange lfcSE  stat    pvalue     padj
  <chr>           <dbl>          <dbl> <dbl> <dbl>     <dbl>    <dbl>
1 rereb           263.           0.441 0.127  3.46 0.000542  0.00318 
2 p4htmb           73.9          0.612 0.214  2.85 0.00436   0.0167  
3 LOC132464547     65.3         -0.484 0.194 -2.49 0.0127    0.0391  
4 zbtb40           22.4          0.584 0.193  3.03 0.00244   0.0107  
5 zc3h11a         826.           0.660 0.165  4.01 0.0000608 0.000531
6 LOC132465594    308.           0.454 0.165  2.75 0.00591   0.0214  
paste("Number of significant DEGs for 9C v 16C:", nrow(sig_L.9.16_norm_noLFCcutoff), "(padj<", padj.cutoff, ")")
[1] "Number of significant DEGs for 9C v 16C: 5015 (padj< 0.05 )"
head(sig_L.9.16_norm)
# A tibble: 6 × 7
  gene         baseMean log2FoldChange lfcSE  stat    pvalue     padj
  <chr>           <dbl>          <dbl> <dbl> <dbl>     <dbl>    <dbl>
1 p4htmb          73.9           0.612 0.214  2.85 0.00436   0.0167  
2 zbtb40          22.4           0.584 0.193  3.03 0.00244   0.0107  
3 zc3h11a        826.            0.660 0.165  4.01 0.0000608 0.000531
4 LOC132465678     9.49          0.943 0.257  3.65 0.000257  0.00175 
5 LOC132465686   144.            0.676 0.161  4.21 0.0000260 0.000267
6 ppil1          137.           -0.589 0.157 -3.75 0.000179  0.00129 
paste("Number of significant DEGs for 9C v 16C:", nrow(sig_L.9.16_norm), "(padj<", padj.cutoff, ", log-fold change >", lfc.cutoff, ")")
[1] "Number of significant DEGs for 9C v 16C: 2616 (padj< 0.05 , log-fold change > 0.58 )"
write.table(sig_L.9.16_norm_noLFCcutoff, file = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/Gmac_DEGs_sig_L.9.16_norm_noLFCcutoff.tab", sep = "\t",
            row.names = TRUE, col.names = NA)

write.table(sig_L.9.16_norm, file = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/Gmac_DEGs_sig_L.9.16_norm.tab", sep = "\t",
            row.names = TRUE, col.names = NA)

4.1 Heatmap

# Retrieve normalized counts matrix
dds_L.9.16_norm_counts <- counts(dds_L.9.16, normalized=TRUE)

# Extract normalized expression for significant genes
norm_sig_L.9.16 <- dds_L.9.16_norm_counts %>% 
  data.frame() %>%
  filter(row.names(dds_L.9.16_norm_counts) %in% sig_L.9.16_norm$gene)

head(norm_sig_L.9.16)
               sample_1   sample_10 sample_100 sample_107 sample_108 sample_109
p4htmb         31.52731  150.321085  58.888643  85.951815  54.578301  48.530523
zbtb40         37.83277   23.621885   3.925910  10.197673  29.563247  17.128420
zc3h11a      1049.07126 1371.500943 724.330310 413.734161 973.881566 383.486288
LOC132465678   22.06912    5.726518   7.851819   8.740863   1.137048   2.854737
LOC132465686  302.66218  178.237857  83.425578 135.483370  50.598634 100.867361
ppil1         130.05016   89.476836  92.258874 217.064753  98.354647 217.911563
              sample_11 sample_110   sample_12  sample_13  sample_18 sample_19
p4htmb         86.63664  53.470058  117.325051   91.98737   66.64435  65.93788
zbtb40         38.50517  23.170358   36.557806   31.74785   33.32218  17.58343
zc3h11a      1065.89321 405.481273 1120.539255 1038.72459 1081.01057 668.17049
LOC132465678   13.12676   2.673503    2.550545   21.16523   10.78070  15.38550
LOC132465686  181.14934  90.007931  124.126503  144.90045  216.59414 124.18300
ppil1         108.51458 182.689365   84.167971   91.17332  125.44819 139.56851
              sample_2  sample_20   sample_21  sample_28  sample_29   sample_3
p4htmb        94.52159   79.88478  111.555274   79.65069  154.16603   67.30977
zbtb40        14.38372   16.41468   25.814443   31.67925   20.23429   22.14137
zc3h11a      734.59715 1228.91245 1087.894404 1057.18193 1276.68745 1048.61542
LOC132465678  14.38372   19.69762    7.375555   29.86901   26.97906    1.77131
LOC132465686 200.34468  128.03451  192.686382  113.14019  184.03570  104.50728
ppil1        120.20681   99.58240  115.243051   94.13264   90.57254  114.24948
              sample_30    sample_4   sample_5  sample_78  sample_79  sample_80
p4htmb        144.13336   37.876705  91.085365  33.471387  68.808378  55.243808
zbtb40         25.60745   41.571994  32.096748  14.036388   8.215926  11.915331
zc3h11a      1045.51562 1308.132067 883.094297 521.505810 611.059472 912.064437
LOC132465678   16.09611    8.314399   6.939837   4.318889   6.161944   3.249636
LOC132465686  127.30561  258.670183 379.088613  89.616941 121.184904 125.652583
ppil1          59.99460  134.878024  70.265853 227.821379 143.778699 152.732881
             sample_83 sample_88 sample_90 sample_91 sample_92  sample_97
p4htmb        24.49252  29.32661  36.21465  64.62824  85.06382   7.628027
zbtb40        10.31264  26.77647   7.24293  10.12250  12.64462  42.716953
zc3h11a      537.54634 446.27456 514.24803 967.08770 664.41737 234.943242
LOC132465678   6.44540   2.55014   2.41431  12.45846  17.24267   3.051211
LOC132465686  69.61032 160.65884 115.88688  72.41478  88.51235 176.970234
ppil1        166.29132 234.61291 208.83782 122.24861  68.97066 254.776113
              sample_98 sample_99 sample_RESUB.116 sample_RESUB.36
p4htmb         3.939351  87.29378         70.58924       114.45319
zbtb40        14.444288  16.16551         27.35333        22.01023
zc3h11a      157.574048 806.12033        922.95431       570.79860
LOC132465678   3.939351   0.00000         11.47075        11.73879
LOC132465686 147.069112  71.12826        103.23676       115.92054
ppil1        286.259521 155.18894         79.41290       136.46342
             sample_RESUB.94
p4htmb            133.601103
zbtb40             27.247593
zc3h11a          1074.961508
LOC132465678        1.757909
LOC132465686      153.817060
ppil1              78.226962
# Annotate heatmap
annotation <- infosub_L.9.16 %>% 
    dplyr::select(temp_treatment)

# Set a color palette
heat_colors <- rev(brewer.pal(12, "RdYlBu"))

# Run pheatmap
h.L.9.16 <- pheatmap(norm_sig_L.9.16, 
                     color = heat_colors, 
                     cluster_rows = T, 
                     show_rownames = F,
                     annotation = annotation, 
                     border_color = NA, 
                     fontsize = 10,
                     scale = "row", 
                     fontsize_row = 10, 
                     height = 30,
                     main = "Normalized Significant Expression, Liver, 9*C and 16*C")

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-heatmap_L.9.16_norm_sig.png",
         plot   = h.L.9.16,
         res    = 600,
         width  = 5000,
         height = 5000)

Note the argument scale="row" was included, so the values plotted in the heat map are Z-scores, rather thn the normalized count value. This vastly improves the color visualization.

For DEGs based on adjusted p-value only

# Extract normalized expression for significant genes
norm_sig_L.9.16_noLFCcutoff <- dds_L.9.16_norm_counts %>% 
  data.frame() %>%
  filter(row.names(dds_L.9.16_norm_counts) %in% sig_L.9.16_norm_noLFCcutoff$gene)

head(norm_sig_L.9.16_noLFCcutoff)
               sample_1  sample_10 sample_100 sample_107 sample_108 sample_109
rereb         366.50499  391.55063  231.62866  176.27406  235.93745  159.86525
p4htmb         31.52731  150.32108   58.88864   85.95182   54.57830   48.53052
LOC132464547   54.38461   36.50655   46.12944  100.51992   42.07077   78.02947
zbtb40         37.83277   23.62188    3.92591   10.19767   29.56325   17.12842
zc3h11a      1049.07126 1371.50094  724.33031  413.73416  973.88157  383.48629
LOC132465594  554.88067  549.74568  227.70275  205.41027  468.46375  206.49262
              sample_11 sample_110  sample_12  sample_13  sample_18 sample_19
rereb         299.29021  181.79820  335.82170  362.25113  345.96259 230.78257
p4htmb         86.63664   53.47006  117.32505   91.98737   66.64435  65.93788
LOC132464547   39.38029   66.83757   34.85744   44.77261   53.90352  67.03684
zbtb40         38.50517   23.17036   36.55781   31.74785   33.32218  17.58343
zc3h11a      1065.89321  405.48127 1120.53925 1038.72459 1081.01057 668.17049
LOC132465594  500.56725  251.30927  334.97152  380.97422  471.41078 304.41320
              sample_2  sample_20  sample_21  sample_28  sample_29   sample_3
rereb        313.35963  252.78609  310.69527  248.00329  340.12881  266.58213
p4htmb        94.52159   79.88478  111.55527   79.65069  154.16603   67.30977
LOC132464547  72.94601   65.65872   33.19000   42.54071   40.46858   43.39709
zbtb40        14.38372   16.41468   25.81444   31.67925   20.23429   22.14137
zc3h11a      734.59715 1228.91245 1087.89440 1057.18193 1276.68745 1048.61542
LOC132465594 248.63288  537.30722  405.65554  262.48524  247.62919  204.58629
              sample_30   sample_4  sample_5 sample_78  sample_79 sample_80
rereb         355.57774  386.15763 234.21951 166.27721 160.210551 242.63947
p4htmb        144.13336   37.87671  91.08536  33.47139  68.808378  55.24381
LOC132464547   43.89849   44.34346  68.53089  82.05889  71.889350  38.99563
zbtb40         25.60745   41.57199  32.09675  14.03639   8.215926  11.91533
zc3h11a      1045.51562 1308.13207 883.09430 521.50581 611.059472 912.06444
LOC132465594  377.52698  316.87097 324.43739 252.65499 182.804346 269.71977
             sample_83 sample_88 sample_90 sample_91 sample_92  sample_97
rereb        203.67463 221.86221 187.10903 308.34680 247.14487 209.007949
p4htmb        24.49252  29.32661  36.21465  64.62824  85.06382   7.628027
LOC132464547 110.86088 127.50702  91.74378  49.83383  41.38240 201.379921
zbtb40        10.31264  26.77647   7.24293  10.12250  12.64462  42.716953
zc3h11a      537.54634 446.27456 514.24803 967.08770 664.41737 234.943242
LOC132465594 171.44763 131.33223 137.61567 376.86832 209.21101 172.393418
              sample_98 sample_99 sample_RESUB.116 sample_RESUB.36
rereb        106.362483 207.99629        335.29889       167.27774
p4htmb         3.939351  87.29378         70.58924       114.45319
LOC132464547 148.382229  26.94252         35.29462       105.64910
zbtb40        14.444288  16.16551         27.35333        22.01023
zc3h11a      157.574048 806.12033        922.95431       570.79860
LOC132465594 261.310297 536.69508        336.18126       154.07160
             sample_RESUB.94
rereb              406.95599
p4htmb             133.60110
LOC132464547        35.15819
zbtb40              27.24759
zc3h11a           1074.96151
LOC132465594       220.61761
# Annotate heatmap
annotation <- infosub_L.9.16 %>% 
    dplyr::select(temp_treatment)

# Set a color palette
heat_colors <- rev(brewer.pal(12, "RdYlBu"))

# Run pheatmap
h.L.9.16 <- pheatmap(norm_sig_L.9.16_noLFCcutoff, 
                     color = heat_colors, 
                     cluster_rows = T, 
                     show_rownames = F,
                     annotation = annotation, 
                     border_color = NA, 
                     fontsize = 10,
                     scale = "row", 
                     fontsize_row = 10, 
                     height = 30,
                     main = "Normalized Significant Expression (no LFC cutoff), Liver, 9*C and 16*C")

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-heatmap_L.9.16_norm_sig.png",
         plot   = h.L.9.16,
         res    = 600,
         width  = 5000,
         height = 5000)

4.2 Volcano plot

# Generate plot
v.L.9.16 <- 
  ggplot(res_table_L.9.16_norm_tb) +
  # Plot all
  geom_point(aes(x=log2FoldChange, y=-log10(padj),color="unchanged"),
             size=.5) +
  # Overlay all significantly upregulated in red
  geom_point(data = sig_L.9.16_norm[sig_L.9.16_norm$log2FoldChange > 0, ], 
             aes(x=log2FoldChange, y=-log10(padj), color="upregulated"), 
             size=.5) +
  # Overlay all significantly downregulated in blue
  geom_point(data = sig_L.9.16_norm[sig_L.9.16_norm$log2FoldChange < 0, ], 
             aes(x=log2FoldChange, y=-log10(padj), color="downregulated"), 
             size=.5) +
  ggtitle("Liver, 9*C and 16*C") +
  xlab("log2 fold change") + 
  ylab("-log10 adjusted p-value") +
  scale_x_continuous(limits = c(-4,4)) +
  scale_y_continuous(limits = c(0,30)) +
  scale_color_manual(values = c("unchanged" = "darkgrey", "upregulated" = "red", "downregulated" = "blue"),
                     labels = c("unchanged" = "Unchanged", "upregulated" = "Upregulated", "downregulated" = "Downregulated"),
                     name = NULL) +
  theme(legend.position = "top",
        plot.title = element_text(size = rel(1.5), hjust = 0.5),
        axis.title = element_text(size = rel(1.25)))

v.L.9.16

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-volcano_L.9.16.png",
         plot   = v.L.9.16,
         res    = 600,
         width  = 6000,
         height = 4000)

4.3 Plot expression of top DEGs across treatments

top15DEGs_L.9.16 <- sig_L.9.16_norm_noLFCcutoff %>%
  arrange(padj) %>%
  slice_head(n=15)

plot_gene_data <- function(geneName) {
  gene_data <- cod_countsdata_plus_sampleinfo %>%
    filter(gene == geneName)
  
  ggplot(data = gene_data, 
         aes(x = temp_treatment, y = count, color = factor(temp_treatment))) +
    geom_boxplot() +
    geom_point(position = position_jitter(width = 0.1), size = 2) +
    labs(title = geneName, x = "Sample", y = "Count", color = "Treatment") +
  scale_color_manual(values = temp_colors) +
    theme_minimal()
}


L.9.16_DEG1 <- plot_gene_data(top15DEGs_L.9.16[1, ]$gene)
L.9.16_DEG1

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG1.",top15DEGs_L.9.16[1, ]$gene,".png"), plot = L.9.16_DEG1, res = 600, width = 5000, height = 5000)

L.9.16_DEG2 <- plot_gene_data(top15DEGs_L.9.16[2, ]$gene)
L.9.16_DEG2

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG2.",top15DEGs_L.9.16[2, ]$gene,".png"), plot = L.9.16_DEG2, res = 600, width = 5000, height = 5000)

L.9.16_DEG3 <- plot_gene_data(top15DEGs_L.9.16[3, ]$gene)
L.9.16_DEG3

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG3.",top15DEGs_L.9.16[3, ]$gene,".png"), plot = L.9.16_DEG3, res = 600, width = 5000, height = 5000)

L.9.16_DEG4 <- plot_gene_data(top15DEGs_L.9.16[4, ]$gene)
L.9.16_DEG4

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG4.",top15DEGs_L.9.16[4, ]$gene,".png"), plot = L.9.16_DEG4, res = 600, width = 5000, height = 5000)

L.9.16_DEG5 <- plot_gene_data(top15DEGs_L.9.16[5, ]$gene)
L.9.16_DEG5

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG5.",top15DEGs_L.9.16[5, ]$gene,".png"), plot = L.9.16_DEG5, res = 600, width = 5000, height = 5000)

L.9.16_DEG6 <- plot_gene_data(top15DEGs_L.9.16[6, ]$gene)
L.9.16_DEG6

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG6.",top15DEGs_L.9.16[6, ]$gene,".png"), plot = L.9.16_DEG6, res = 600, width = 5000, height = 5000)

L.9.16_DEG7 <- plot_gene_data(top15DEGs_L.9.16[7, ]$gene)
L.9.16_DEG7

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG7.",top15DEGs_L.9.16[7, ]$gene,".png"), plot = L.9.16_DEG7, res = 600, width = 5000, height = 5000)

L.9.16_DEG8 <- plot_gene_data(top15DEGs_L.9.16[8, ]$gene)
L.9.16_DEG8

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG8.",top15DEGs_L.9.16[8, ]$gene,".png"), plot = L.9.16_DEG8, res = 600, width = 5000, height = 5000)

L.9.16_DEG9 <- plot_gene_data(top15DEGs_L.9.16[9, ]$gene)
L.9.16_DEG9

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG9.",top15DEGs_L.9.16[9, ]$gene,".png"), plot = L.9.16_DEG9, res = 600, width = 5000, height = 5000)

L.9.16_DEG10 <- plot_gene_data(top15DEGs_L.9.16[10, ]$gene)
L.9.16_DEG10

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG10.",top15DEGs_L.9.16[10, ]$gene,".png"), plot = L.9.16_DEG10, res = 600, width = 5000, height = 5000)

L.9.16_DEG11 <- plot_gene_data(top15DEGs_L.9.16[11, ]$gene)
L.9.16_DEG11

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG11.",top15DEGs_L.9.16[11, ]$gene,".png"), plot = L.9.16_DEG11, res = 600, width = 5000, height = 5000)

L.9.16_DEG12 <- plot_gene_data(top15DEGs_L.9.16[12, ]$gene)
L.9.16_DEG12

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG12.",top15DEGs_L.9.16[12, ]$gene,".png"), plot = L.9.16_DEG12, res = 600, width = 5000, height = 5000)

L.9.16_DEG13 <- plot_gene_data(top15DEGs_L.9.16[13, ]$gene)
L.9.16_DEG13

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG13.",top15DEGs_L.9.16[13, ]$gene,".png"), plot = L.9.16_DEG13, res = 600, width = 5000, height = 5000)

L.9.16_DEG14 <- plot_gene_data(top15DEGs_L.9.16[14, ]$gene)
L.9.16_DEG14

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG14.",top15DEGs_L.9.16[14, ]$gene,".png"), plot = L.9.16_DEG14, res = 600, width = 5000, height = 5000)

L.9.16_DEG15 <- plot_gene_data(top15DEGs_L.9.16[15, ]$gene)
L.9.16_DEG15

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.16_DEG15.",top15DEGs_L.9.16[15, ]$gene,".png"), plot = L.9.16_DEG15, res = 600, width = 5000, height = 5000)

5 Liver tissue, 9C v. 0C

The 9*C temperature treatment is effectively our “control,” as it represents the ambient temperature that wild juvenile Pacific cod would experience.

# liver tissue, temperatures 9 vs. 0 

# Filter data
infosub_L.9.0 <- cod_sample_info %>% filter(tissue_type == "Liver" & (temp_treatment == "9" | temp_treatment == "0"))
countsub_L.9.0 <- subset(cod_counts_data, select=row.names(infosub_L.9.0))

# Calculate DESeq object
dds_L.9.0 <- DESeqDataSetFromMatrix(countData = countsub_L.9.0,
                              colData = infosub_L.9.0,
                              design = ~ temp_treatment)

dds_L.9.0 <- DESeq(dds_L.9.0)
resultsNames(dds_L.9.0) # lists the coefficients
[1] "Intercept"             "temp_treatment_9_vs_0"
plotDispEsts(dds_L.9.0)

# Filtering: keep genes that have at least 10 counts across 1/3 of the samples - https://support.bioconductor.org/p/110307/
keep <- rowSums(DESeq2::counts(dds_L.9.0) >= 10) >= ncol(countsub_L.9.0)/3
dds_L.9.0<- dds_L.9.0[keep,]

# Generate Contrasts
contrast_list_L.9.0        <- c("temp_treatment", "0", "9") # order is important: factor, treatment group, control
res_table_L.9.0_noshrink <- results(dds_L.9.0, contrast=contrast_list_L.9.0, alpha = 0.05)

res_table_L.9.0_norm     <- lfcShrink(dds_L.9.0,
                                       coef=2,
                                       type="normal") # lfcThreshold = 0.585)  # a lfc threshold of 1 = 2-fold change, 0.585 = 1.5-fold change
res_table_L.9.0_apeglm   <- lfcShrink(dds_L.9.0,
                                       coef=2, 
                                       type="apeglm") # lfcThreshold = 0.585)  # a lfc threshold of 1 = 2-fold change, 0.585 = 1.5-fold change
res_table_L.9.0_ashr     <- lfcShrink(dds_L.9.0,
                                       coef=2, 
                                       type="ashr")
# Generate MA plots
par(mfrow=c(2,2), mar=c(4,4,2,1))
xlim <- c(1,1e5); ylim <- c(-4,4)
DESeq2::plotMA(res_table_L.9.0_noshrink, xlim=xlim, ylim=ylim, main="no shrink")
DESeq2::plotMA(res_table_L.9.0_norm, xlim=xlim, ylim=ylim, main="normal")
DESeq2::plotMA(res_table_L.9.0_apeglm, xlim=xlim, ylim=ylim, main="apeglm")
DESeq2::plotMA(res_table_L.9.0_ashr, xlim=xlim, ylim=ylim, main="ashr")

# Examine results formatting
res_table_L.9.0_norm %>% data.frame() %>% head()
              baseMean log2FoldChange     lfcSE       stat       pvalue
rereb        195.72261      0.5997946 0.1356807  4.4202373 9.859257e-06
p4htmb        40.33790      1.3560309 0.2433347  5.5661856 2.603759e-08
LOC132464555 568.80555     -0.1183840 0.1147838 -1.0313817 3.023619e-01
abhd14a       85.91394      0.1683689 0.1344005  1.2528336 2.102663e-01
LOC132464547  77.66220      0.1626846 0.2298079  0.7082412 4.787955e-01
tusc2b       160.57348      0.1349880 0.2000022  0.6750591 4.996382e-01
                     padj
rereb        5.571974e-05
p4htmb       2.448409e-07
LOC132464555 4.154587e-01
abhd14a      3.132713e-01
LOC132464547 5.909948e-01
tusc2b       6.092403e-01

Note that the metric we want to use to identify significantly expressed genes is the padj values, NOT the pvalue. padj are p-values corrected for multiple testing (default method is the Benjamini and Hochberg method).

summary(res_table_L.9.0_noshrink)

out of 14547 with nonzero total read count
adjusted p-value < 0.05
LFC > 0 (up)       : 3114, 21%
LFC < 0 (down)     : 3352, 23%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 6)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.0_norm)

out of 14547 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 3894, 27%
LFC < 0 (down)     : 3528, 24%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 6)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.0_apeglm)

out of 14547 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 3894, 27%
LFC < 0 (down)     : 3528, 24%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 6)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.0_ashr)

out of 14547 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 3891, 27%
LFC < 0 (down)     : 3531, 24%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 6)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results

5.1 Extracting significantly expressed genes

padj.cutoff <- 0.05
lfc.cutoff <- 0.58

# Convert results table into tibble
res_table_L.9.0_norm_tb <- res_table_L.9.0_norm %>%
  data.frame() %>%
  rownames_to_column(var="gene") %>%
  as_tibble()

# subset that table to only keep the significant genes using our pre-defined thresholds:
sig_L.9.0_norm_noLFCcutoff <- res_table_L.9.0_norm_tb %>%
  filter(padj < padj.cutoff)

sig_L.9.0_norm <- sig_L.9.0_norm_noLFCcutoff %>% 
  filter(abs(log2FoldChange) > lfc.cutoff)

head(sig_L.9.0_norm_noLFCcutoff)
# A tibble: 6 × 7
  gene         baseMean log2FoldChange lfcSE  stat        pvalue         padj
  <chr>           <dbl>          <dbl> <dbl> <dbl>         <dbl>        <dbl>
1 rereb           196.           0.600 0.136  4.42 0.00000986    0.0000557   
2 p4htmb           40.3          1.36  0.243  5.57 0.0000000260  0.000000245 
3 LOC132464874     14.3         -1.20  0.291 -4.13 0.0000366     0.000182    
4 usp48           267.           0.710 0.117  6.07 0.00000000129 0.0000000154
5 zbtb40           23.9         -0.614 0.230 -2.67 0.00755       0.0199      
6 atxn7l2a         36.4         -0.948 0.249 -3.80 0.000143      0.000615    
paste("Number of significant DEGs for 9C v 0C:", nrow(sig_L.9.0_norm_noLFCcutoff), "(padj<", padj.cutoff, ")")
[1] "Number of significant DEGs for 9C v 0C: 6466 (padj< 0.05 )"
head(sig_L.9.0_norm)
# A tibble: 6 × 7
  gene         baseMean log2FoldChange lfcSE  stat        pvalue         padj
  <chr>           <dbl>          <dbl> <dbl> <dbl>         <dbl>        <dbl>
1 rereb           196.           0.600 0.136  4.42 0.00000986    0.0000557   
2 p4htmb           40.3          1.36  0.243  5.57 0.0000000260  0.000000245 
3 LOC132464874     14.3         -1.20  0.291 -4.13 0.0000366     0.000182    
4 usp48           267.           0.710 0.117  6.07 0.00000000129 0.0000000154
5 zbtb40           23.9         -0.614 0.230 -2.67 0.00755       0.0199      
6 atxn7l2a         36.4         -0.948 0.249 -3.80 0.000143      0.000615    
paste("Number of significant DEGs for 9C v 0C:", nrow(sig_L.9.0_norm), "(padj<", padj.cutoff, ", log-fold change >", lfc.cutoff, ")")
[1] "Number of significant DEGs for 9C v 0C: 4405 (padj< 0.05 , log-fold change > 0.58 )"
write.table(sig_L.9.0_norm_noLFCcutoff, file = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/Gmac_DEGs_sig_L.9.0_norm_noLFCcutoff.tab", sep = "\t",
            row.names = TRUE, col.names = NA)

write.table(sig_L.9.0_norm, file = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/Gmac_DEGs_sig_L.9.0_norm.tab", sep = "\t",
            row.names = TRUE, col.names = NA)

5.2 Heatmap

# Retrieve normalized counts matrix
dds_L.9.0_norm_counts <- counts(dds_L.9.0, normalized=TRUE)

# Extract normalized expression for significant genes
norm_sig_L.9.0 <- dds_L.9.0_norm_counts %>% 
  data.frame() %>%
  filter(row.names(dds_L.9.0_norm_counts) %in% sig_L.9.0_norm$gene)

head(norm_sig_L.9.0)
             sample_100 sample_107 sample_108 sample_109 sample_110 sample_37
rereb        247.999034 185.564799 244.818042 169.749800 195.275681 125.08035
p4htmb        63.050602  90.482010  56.632607  51.531189  57.434024  11.09584
LOC132464874   8.406747  13.802340   4.129461  10.104155   3.828935  17.14811
usp48        270.066745 440.141301 168.128053 315.249628 269.939912 174.50727
zbtb40         4.203373  10.735154  30.675996  18.187479  24.888077  16.13940
atxn7l2a      29.423614   6.134374  39.524841   8.083324  22.016376  28.24395
             sample_38 sample_39 sample_40 sample_47 sample_48 sample_49
rereb        114.34618 120.39379  83.94794 114.62611 140.38311 177.26531
p4htmb        13.86014   9.26106  19.18810  10.83081  18.31084  21.90920
LOC132464874  30.31906  32.92821  41.97397  16.24622  53.71180  26.55660
usp48        218.29725 230.49750 223.06166 163.36477 207.52286 204.48582
zbtb40        18.19144  14.40609  17.98884  30.68730  14.64867  47.80188
atxn7l2a      24.25525  27.78318  21.58661  43.32325  17.09012  80.99763
              sample_50  sample_57  sample_58 sample_59  sample_60  sample_67
rereb        175.924054 166.979073 172.660638 157.54476 189.221992 206.775700
p4htmb        13.139556  17.222057  12.969813  19.03225  33.392116  20.248066
LOC132464874   7.299753   8.985421   8.916747  48.63798   4.583232   3.681466
usp48        152.564844 205.915897 179.956158 271.73828 165.651086 219.047255
zbtb40        35.768791  48.671030  30.803306  10.57347  43.213327  18.407332
atxn7l2a      69.347656  59.902806  68.091519  17.97491  77.260190  60.130619
              sample_68  sample_69 sample_70  sample_78  sample_79  sample_80
rereb        192.508523 162.176007 127.04274 175.828245 171.240293 256.683441
p4htmb        24.309950  49.425069  28.11602  35.393997  73.545510  58.441319
LOC132464874   7.227282   7.722667  26.03335   5.708709   6.586165   4.583633
usp48        199.078780 193.838942 249.92014 375.633069 353.457528 272.726156
zbtb40        55.190157  33.979735  28.11602  14.842644   8.781553  12.604990
atxn7l2a      72.929850  64.098136  47.90136  21.693095  19.758495  32.085430
              sample_83  sample_88  sample_90  sample_91  sample_92  sample_97
rereb        217.774925 237.916095 198.234831 329.456976 263.355034 221.642448
p4htmb        26.188124  31.448679  38.368032  69.052851  90.643128   8.089140
LOC132464874   5.513289  19.142674  12.789344   2.495886   4.899629   6.471312
usp48        250.854661 393.792158 377.285645 301.170266 327.050205 564.622003
zbtb40        11.026578  28.714012   7.673606  10.815507  13.473978  45.299186
atxn7l2a      28.944769   9.571337   8.952541  43.262027  24.498143   1.617828
              sample_98  sample_99 sample_RESUB.116 sample_RESUB.76
rereb        113.373933 217.551880        358.02267       178.76269
p4htmb         4.199035  91.304157         75.37319        23.83503
LOC132464874  20.995173   3.381635          3.76866        18.41797
usp48        401.707639 240.096117        279.82299       126.75900
zbtb40        15.396460  16.908177         29.20711        37.91936
atxn7l2a       9.797747  28.180295         27.32278        70.42166
             sample_RESUB.94
rereb             440.164201
p4htmb            144.503150
LOC132464874        1.901357
usp48             347.948375
zbtb40             29.471037
atxn7l2a           60.843432
# Annotate heatmap
annotation <- infosub_L.9.0 %>% 
    dplyr::select(temp_treatment)

# Set a color palette
heat_colors <- rev(brewer.pal(12, "RdYlBu"))

# Run pheatmap
h.L.9.0 <- pheatmap(norm_sig_L.9.0, 
                     color = heat_colors, 
                     cluster_rows = T, 
                     show_rownames = F,
                     annotation = annotation, 
                     border_color = NA, 
                     fontsize = 10,
                     scale = "row", 
                     fontsize_row = 10, 
                     height = 30,
                     main = "Normalized Significant Expression, Liver, 9*C and 0*C")

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-heatmap_L.9.0_norm_sig.png",
         plot   = h.L.9.0,
         res    = 600,
         width  = 5000,
         height = 5000)

Note the argument scale="row" was included, so the values plotted in the heat map are Z-scores, rather thn the normalized count value. This vastly improves the color visualization.

For DEGs based on adjusted p-value only

# Extract normalized expression for significant genes
norm_sig_L.9.0_noLFCcutoff <- dds_L.9.0_norm_counts %>% 
  data.frame() %>%
  filter(row.names(dds_L.9.0_norm_counts) %in% sig_L.9.0_norm_noLFCcutoff$gene)

head(norm_sig_L.9.0_noLFCcutoff)
             sample_100 sample_107 sample_108 sample_109 sample_110 sample_37
rereb        247.999034 185.564799 244.818042 169.749800 195.275681 125.08035
p4htmb        63.050602  90.482010  56.632607  51.531189  57.434024  11.09584
LOC132464874   8.406747  13.802340   4.129461  10.104155   3.828935  17.14811
usp48        270.066745 440.141301 168.128053 315.249628 269.939912 174.50727
zbtb40         4.203373  10.735154  30.675996  18.187479  24.888077  16.13940
atxn7l2a      29.423614   6.134374  39.524841   8.083324  22.016376  28.24395
             sample_38 sample_39 sample_40 sample_47 sample_48 sample_49
rereb        114.34618 120.39379  83.94794 114.62611 140.38311 177.26531
p4htmb        13.86014   9.26106  19.18810  10.83081  18.31084  21.90920
LOC132464874  30.31906  32.92821  41.97397  16.24622  53.71180  26.55660
usp48        218.29725 230.49750 223.06166 163.36477 207.52286 204.48582
zbtb40        18.19144  14.40609  17.98884  30.68730  14.64867  47.80188
atxn7l2a      24.25525  27.78318  21.58661  43.32325  17.09012  80.99763
              sample_50  sample_57  sample_58 sample_59  sample_60  sample_67
rereb        175.924054 166.979073 172.660638 157.54476 189.221992 206.775700
p4htmb        13.139556  17.222057  12.969813  19.03225  33.392116  20.248066
LOC132464874   7.299753   8.985421   8.916747  48.63798   4.583232   3.681466
usp48        152.564844 205.915897 179.956158 271.73828 165.651086 219.047255
zbtb40        35.768791  48.671030  30.803306  10.57347  43.213327  18.407332
atxn7l2a      69.347656  59.902806  68.091519  17.97491  77.260190  60.130619
              sample_68  sample_69 sample_70  sample_78  sample_79  sample_80
rereb        192.508523 162.176007 127.04274 175.828245 171.240293 256.683441
p4htmb        24.309950  49.425069  28.11602  35.393997  73.545510  58.441319
LOC132464874   7.227282   7.722667  26.03335   5.708709   6.586165   4.583633
usp48        199.078780 193.838942 249.92014 375.633069 353.457528 272.726156
zbtb40        55.190157  33.979735  28.11602  14.842644   8.781553  12.604990
atxn7l2a      72.929850  64.098136  47.90136  21.693095  19.758495  32.085430
              sample_83  sample_88  sample_90  sample_91  sample_92  sample_97
rereb        217.774925 237.916095 198.234831 329.456976 263.355034 221.642448
p4htmb        26.188124  31.448679  38.368032  69.052851  90.643128   8.089140
LOC132464874   5.513289  19.142674  12.789344   2.495886   4.899629   6.471312
usp48        250.854661 393.792158 377.285645 301.170266 327.050205 564.622003
zbtb40        11.026578  28.714012   7.673606  10.815507  13.473978  45.299186
atxn7l2a      28.944769   9.571337   8.952541  43.262027  24.498143   1.617828
              sample_98  sample_99 sample_RESUB.116 sample_RESUB.76
rereb        113.373933 217.551880        358.02267       178.76269
p4htmb         4.199035  91.304157         75.37319        23.83503
LOC132464874  20.995173   3.381635          3.76866        18.41797
usp48        401.707639 240.096117        279.82299       126.75900
zbtb40        15.396460  16.908177         29.20711        37.91936
atxn7l2a       9.797747  28.180295         27.32278        70.42166
             sample_RESUB.94
rereb             440.164201
p4htmb            144.503150
LOC132464874        1.901357
usp48             347.948375
zbtb40             29.471037
atxn7l2a           60.843432
# Annotate heatmap
annotation <- infosub_L.9.0 %>% 
    dplyr::select(temp_treatment)

# Set a color palette
heat_colors <- rev(brewer.pal(12, "RdYlBu"))

# Run pheatmap
h.L.9.0 <- pheatmap(norm_sig_L.9.0_noLFCcutoff, 
                     color = heat_colors, 
                     cluster_rows = T, 
                     show_rownames = F,
                     annotation = annotation, 
                     border_color = NA, 
                     fontsize = 10,
                     scale = "row", 
                     fontsize_row = 10, 
                     height = 30,
                     main = "Normalized Significant Expression (no LFC cutoff), Liver, 9*C and 0*C")

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/heatmap_L.9.0_norm_sig_noLFCcutoff.png",
         plot   = h.L.9.0,
         res    = 600,
         width  = 5000,
         height = 5000)

5.3 Volcano plot

# Generate plot
v.L.9.0 <- 
  ggplot(res_table_L.9.0_norm_tb) +
  # Plot all
  geom_point(aes(x=log2FoldChange, y=-log10(padj),color="unchanged"),
             size=.5) +
  # Overlay all significantly upregulated in red
  geom_point(data = sig_L.9.0_norm[sig_L.9.0_norm$log2FoldChange > 0, ], 
             aes(x=log2FoldChange, y=-log10(padj), color="upregulated"), 
             size=.5) +
  # Overlay all significantly downregulated in blue
  geom_point(data = sig_L.9.0_norm[sig_L.9.0_norm$log2FoldChange < 0, ], 
             aes(x=log2FoldChange, y=-log10(padj), color="downregulated"), 
             size=.5) +
  ggtitle("Liver, 9*C and 0*C") +
  xlab("log2 fold change") + 
  ylab("-log10 adjusted p-value") +
  scale_x_continuous(limits = c(-4,4)) +
  scale_y_continuous(limits = c(0,30)) +
  scale_color_manual(values = c("unchanged" = "darkgrey", "upregulated" = "red", "downregulated" = "blue"),
                     labels = c("unchanged" = "Unchanged", "upregulated" = "Upregulated", "downregulated" = "Downregulated"),
                     name = NULL) +
  theme(legend.position = "top",
        plot.title = element_text(size = rel(1.5), hjust = 0.5),
        axis.title = element_text(size = rel(1.25)))

v.L.9.0

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-volcano_L.9.0.png",
         plot   = v.L.9.0,
         res    = 600,
         width  = 6000,
         height = 4000)

5.4 Plot expression of top DEGs across treatments

top15DEGs_L.9.0 <- sig_L.9.0_norm_noLFCcutoff %>%
  arrange(padj) %>%
  slice_head(n=15)

L.9.0_DEG1 <- plot_gene_data(top15DEGs_L.9.0[1, ]$gene)
L.9.0_DEG1

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG1.",top15DEGs_L.9.0[1, ]$gene,".png"), plot = L.9.0_DEG1, res = 600, width = 5000, height = 5000)

L.9.0_DEG2 <- plot_gene_data(top15DEGs_L.9.0[2, ]$gene)
L.9.0_DEG2

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG2.",top15DEGs_L.9.0[2, ]$gene,".png"), plot = L.9.0_DEG2, res = 600, width = 5000, height = 5000)

L.9.0_DEG3 <- plot_gene_data(top15DEGs_L.9.0[3, ]$gene)
L.9.0_DEG3

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG3.",top15DEGs_L.9.0[3, ]$gene,".png"), plot = L.9.0_DEG3, res = 600, width = 5000, height = 5000)

L.9.0_DEG4 <- plot_gene_data(top15DEGs_L.9.0[4, ]$gene)
L.9.0_DEG4

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG4.",top15DEGs_L.9.0[4, ]$gene,".png"), plot = L.9.0_DEG4, res = 600, width = 5000, height = 5000)

L.9.0_DEG5 <- plot_gene_data(top15DEGs_L.9.0[5, ]$gene)
L.9.0_DEG5

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG5.",top15DEGs_L.9.0[5, ]$gene,".png"), plot = L.9.0_DEG5, res = 600, width = 5000, height = 5000)

L.9.0_DEG6 <- plot_gene_data(top15DEGs_L.9.0[6, ]$gene)
L.9.0_DEG6

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG6.",top15DEGs_L.9.0[6, ]$gene,".png"), plot = L.9.0_DEG6, res = 600, width = 5000, height = 5000)

L.9.0_DEG7 <- plot_gene_data(top15DEGs_L.9.0[7, ]$gene)
L.9.0_DEG7

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG7.",top15DEGs_L.9.0[7, ]$gene,".png"), plot = L.9.0_DEG7, res = 600, width = 5000, height = 5000)

L.9.0_DEG8 <- plot_gene_data(top15DEGs_L.9.0[8, ]$gene)
L.9.0_DEG8

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG8.",top15DEGs_L.9.0[8, ]$gene,".png"), plot = L.9.0_DEG8, res = 600, width = 5000, height = 5000)

L.9.0_DEG9 <- plot_gene_data(top15DEGs_L.9.0[9, ]$gene)
L.9.0_DEG9

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG9.",top15DEGs_L.9.0[9, ]$gene,".png"), plot = L.9.0_DEG9, res = 600, width = 5000, height = 5000)

L.9.0_DEG10 <- plot_gene_data(top15DEGs_L.9.0[10, ]$gene)
L.9.0_DEG10

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG10.",top15DEGs_L.9.0[10, ]$gene,".png"), plot = L.9.0_DEG10, res = 600, width = 5000, height = 5000)

L.9.0_DEG11 <- plot_gene_data(top15DEGs_L.9.0[11, ]$gene)
L.9.0_DEG11

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG11.",top15DEGs_L.9.0[11, ]$gene,".png"), plot = L.9.0_DEG11, res = 600, width = 5000, height = 5000)

L.9.0_DEG12 <- plot_gene_data(top15DEGs_L.9.0[12, ]$gene)
L.9.0_DEG12

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG12.",top15DEGs_L.9.0[12, ]$gene,".png"), plot = L.9.0_DEG12, res = 600, width = 5000, height = 5000)

L.9.0_DEG13 <- plot_gene_data(top15DEGs_L.9.0[13, ]$gene)
L.9.0_DEG13

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG13.",top15DEGs_L.9.0[13, ]$gene,".png"), plot = L.9.0_DEG13, res = 600, width = 5000, height = 5000)

L.9.0_DEG14 <- plot_gene_data(top15DEGs_L.9.0[14, ]$gene)
L.9.0_DEG14

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG14.",top15DEGs_L.9.0[14, ]$gene,".png"), plot = L.9.0_DEG14, res = 600, width = 5000, height = 5000)

L.9.0_DEG15 <- plot_gene_data(top15DEGs_L.9.0[15, ]$gene)
L.9.0_DEG15

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.0_DEG15.",top15DEGs_L.9.0[15, ]$gene,".png"), plot = L.9.0_DEG15, res = 600, width = 5000, height = 5000)

6 Liver tissue, 9C v. 5C

The 9*C temperature treatment is effectively our “control,” as it represents the ambient temperature that wild juvenile Pacific cod would experience.

# liver tissue, temperatures 9 vs. 5 

# Filter data
infosub_L.9.5 <- cod_sample_info %>% filter(tissue_type == "Liver" & (temp_treatment == "9" | temp_treatment == "5"))
countsub_L.9.5 <- subset(cod_counts_data, select=row.names(infosub_L.9.5))

# Calculate DESeq object
dds_L.9.5 <- DESeqDataSetFromMatrix(countData = countsub_L.9.5,
                              colData = infosub_L.9.5,
                              design = ~ temp_treatment)

dds_L.9.5 <- DESeq(dds_L.9.5)
resultsNames(dds_L.9.5) # lists the coefficients
[1] "Intercept"             "temp_treatment_9_vs_5"
plotDispEsts(dds_L.9.5)

# Filtering: keep genes that have at least 10 counts across 1/3 of the samples - https://support.bioconductor.org/p/110307/
keep <- rowSums(DESeq2::counts(dds_L.9.5) >= 10) >= ncol(countsub_L.9.5)/3
dds_L.9.5<- dds_L.9.5[keep,]

# Generate Contrasts
contrast_list_L.9.5        <- c("temp_treatment", "5", "9") # order is important: factor, treatment group, control
res_table_L.9.5_noshrink <- results(dds_L.9.5, contrast=contrast_list_L.9.5, alpha = 0.05)

res_table_L.9.5_norm     <- lfcShrink(dds_L.9.5,
                                       coef=2,
                                       type="normal") # lfcThreshold = 0.585)  # a lfc threshold of 1 = 2-fold change, 0.585 = 1.5-fold change
res_table_L.9.5_apeglm   <- lfcShrink(dds_L.9.5,
                                       coef=2, 
                                       type="apeglm") # lfcThreshold = 0.585)  # a lfc threshold of 1 = 2-fold change, 0.585 = 1.5-fold change
res_table_L.9.5_ashr     <- lfcShrink(dds_L.9.5,
                                       coef=2, 
                                       type="ashr")
# Generate MA plots
par(mfrow=c(2,2), mar=c(4,4,2,1))
xlim <- c(1,1e5); ylim <- c(-4,4)
DESeq2::plotMA(res_table_L.9.5_noshrink, xlim=xlim, ylim=ylim, main="no shrink")
DESeq2::plotMA(res_table_L.9.5_norm, xlim=xlim, ylim=ylim, main="normal")
DESeq2::plotMA(res_table_L.9.5_apeglm, xlim=xlim, ylim=ylim, main="apeglm")
DESeq2::plotMA(res_table_L.9.5_ashr, xlim=xlim, ylim=ylim, main="ashr")

# Examine results formatting
res_table_L.9.5_norm %>% data.frame() %>% head()
              baseMean log2FoldChange     lfcSE       stat      pvalue
rereb        187.79714      0.2045636 0.1285921  1.5904247 0.111739109
p4htmb        39.63125      0.5986769 0.2003332  2.9873841 0.002813759
LOC132464555 491.53128     -0.1406288 0.1029234 -1.3664738 0.171790296
abhd14a       82.85574     -0.1635148 0.1236476 -1.3229814 0.185841567
LOC132464547  61.72158      0.3457015 0.1867980  1.8553627 0.063544453
tusc2b       155.64889     -0.1649801 0.1783700 -0.9258003 0.354549763
                   padj
rereb        0.32066032
p4htmb       0.02992357
LOC132464555 0.41125645
abhd14a      0.42787081
LOC132464547 0.23023829
tusc2b       0.61074721

Note that the metric we want to use to identify significantly expressed genes is the padj values, NOT the pvalue. padj are p-values corrected for multiple testing (default method is the Benjamini and Hochberg method).

summary(res_table_L.9.5_noshrink)

out of 14208 with nonzero total read count
adjusted p-value < 0.05
LFC > 0 (up)       : 876, 6.2%
LFC < 0 (down)     : 824, 5.8%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 5)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.5_norm)

out of 14208 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 1220, 8.6%
LFC < 0 (down)     : 1172, 8.2%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 5)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.5_apeglm)

out of 14208 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 1220, 8.6%
LFC < 0 (down)     : 1172, 8.2%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 5)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
summary(res_table_L.9.5_ashr)

out of 14208 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 1223, 8.6%
LFC < 0 (down)     : 1169, 8.2%
outliers [1]       : 0, 0%
low counts [2]     : 0, 0%
(mean count < 5)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results

6.1 Extracting significantly expressed genes

padj.cutoff <- 0.05
lfc.cutoff <- 0.58

# Convert results table into tibble
res_table_L.9.5_norm_tb <- res_table_L.9.5_norm %>%
  data.frame() %>%
  rownames_to_column(var="gene") %>%
  as_tibble()

# subset that table to only keep the significant genes using our pre-defined thresholds:
sig_L.9.5_norm_noLFCcutoff <- res_table_L.9.5_norm_tb %>%
  filter(padj < padj.cutoff)

sig_L.9.5_norm <- sig_L.9.5_norm_noLFCcutoff %>% 
  filter(abs(log2FoldChange) > lfc.cutoff)

head(sig_L.9.5_norm)
# A tibble: 6 × 7
  gene         baseMean log2FoldChange lfcSE  stat      pvalue      padj
  <chr>           <dbl>          <dbl> <dbl> <dbl>       <dbl>     <dbl>
1 p4htmb           39.6          0.599 0.200  2.99 0.00281     0.0299   
2 fkbp5           401.          -0.916 0.191 -4.80 0.00000156  0.000102 
3 fbxo2            12.2         -0.680 0.214 -3.17 0.00152     0.0193   
4 LOC132466537    354.           0.682 0.146  4.66 0.00000322  0.000184 
5 LOC132466614    136.           0.723 0.141  5.12 0.000000304 0.0000261
6 ccdc3b           41.2          0.838 0.196  4.29 0.0000181   0.000736 
paste("Number of significant DEGs for 9C v 5C:", nrow(sig_L.9.5_norm_noLFCcutoff), "(padj<", padj.cutoff, ")")
[1] "Number of significant DEGs for 9C v 5C: 1700 (padj< 0.05 )"
head(sig_L.9.5_norm)
# A tibble: 6 × 7
  gene         baseMean log2FoldChange lfcSE  stat      pvalue      padj
  <chr>           <dbl>          <dbl> <dbl> <dbl>       <dbl>     <dbl>
1 p4htmb           39.6          0.599 0.200  2.99 0.00281     0.0299   
2 fkbp5           401.          -0.916 0.191 -4.80 0.00000156  0.000102 
3 fbxo2            12.2         -0.680 0.214 -3.17 0.00152     0.0193   
4 LOC132466537    354.           0.682 0.146  4.66 0.00000322  0.000184 
5 LOC132466614    136.           0.723 0.141  5.12 0.000000304 0.0000261
6 ccdc3b           41.2          0.838 0.196  4.29 0.0000181   0.000736 
paste("Number of significant DEGs for 9C v 5C:", nrow(sig_L.9.5_norm), "(padj<", padj.cutoff, ", log-fold change >", lfc.cutoff, ")")
[1] "Number of significant DEGs for 9C v 5C: 840 (padj< 0.05 , log-fold change > 0.58 )"
write.table(sig_L.9.5_norm_noLFCcutoff, file = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/Gmac_DEGs_sig_L.9.5_norm_noLFCcutoff.tab", sep = "\t",
            row.names = TRUE, col.names = NA)

write.table(sig_L.9.5_norm, file = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/Gmac_DEGs_sig_L.9.5_norm.tab", sep = "\t",
            row.names = TRUE, col.names = NA)

6.2 Heatmap

# Retrieve normalized counts matrix
dds_L.9.5_norm_counts <- counts(dds_L.9.5, normalized=TRUE)

# Extract normalized expression for significant genes
norm_sig_L.9.5 <- dds_L.9.5_norm_counts %>% 
  data.frame() %>%
  filter(row.names(dds_L.9.5_norm_counts) %in% sig_L.9.5_norm$gene)

head(norm_sig_L.9.5)
             sample_100 sample_107 sample_108 sample_109 sample_110 sample_117
p4htmb        53.727408   78.23193   49.33584  44.069179   48.34665  86.072979
fkbp5        188.941383  163.09369  145.95187 258.366361  182.10573 360.209521
fbxo2          3.581827    2.65193   10.27830   5.184609   12.89244   9.432655
LOC132466537 368.928199  425.63475  419.86858 406.127724  290.07993 226.973266
LOC132466614 214.909630  145.85614  112.54739 273.056087  124.89553  93.147470
ccdc3b        35.818272  114.03298   76.05942  60.487108   27.39644  15.917606
             sample_118 sample_119 sample_120 sample_121 sample_127 sample_128
p4htmb         15.12887   16.06242   42.41875   13.12144   15.02789  30.123885
fkbp5         759.73235  331.19189 1065.11742  814.84117  674.70047 466.920222
fbxo2          11.83998   10.70828   15.68913  101.03506   11.91867   4.518583
LOC132466537  176.94199  165.21351  216.16131  253.24371  210.90867 331.362738
LOC132466614   87.48433  117.02623   91.22937   61.67075  137.84203 140.076066
ccdc3b         13.15554   22.94632   23.24315   30.17930   19.17352  24.099108
             sample_131 sample_137 sample_138 sample_139 sample_140 sample_147
p4htmb         29.18508  17.799905   25.14052   21.71330  25.066986   19.23673
fkbp5        1096.87252 453.897575 1064.28185  313.03347 198.969202  251.82632
fbxo2           7.29627   8.899952   13.96695   28.95107   7.833433   17.48794
LOC132466537  196.99928 195.798954  332.41349  258.75021 206.802635  416.21294
LOC132466614   87.55523  86.774536   41.90086   57.90215 111.234751   89.18849
ccdc3b         21.88881  31.149834   25.14052   12.66609  31.333733   26.23191
             sample_148 sample_150  sample_78 sample_79  sample_80  sample_83
p4htmb         28.61782  20.728754  30.208488  62.79026  50.095212  22.174947
fkbp5         504.21869 505.127001 416.097565 118.08318 166.001782 772.621851
fbxo2           8.63077   8.727896   1.948935  14.05752   5.893554   1.167102
LOC132466537  317.52150 404.756193 500.876226 359.87254 513.721492 461.005485
LOC132466614  123.55629 116.735614 194.893473 131.20353 186.629223 215.913961
ccdc3b         44.06235  43.093988  36.055293  30.92655  50.095212  44.349895
              sample_88  sample_90 sample_91 sample_92  sample_97  sample_98
p4htmb        26.914531  32.999136  59.06621  76.93003   6.986541   3.654154
fkbp5        218.826835 406.989341 272.55853 122.67221 262.693928  77.955289
fbxo2          9.361576   4.399885  10.67462   0.00000   9.781157   0.000000
LOC132466537 571.056126 831.578222 426.27300 265.09674 807.644097 460.423426
LOC132466614 156.806395 158.395852 180.04519 169.45399 183.047365  52.376210
ccdc3b        79.573395  65.998272  19.92595  33.26704  96.414261 168.091092
             sample_99 sample_RESUB.116 sample_RESUB.156 sample_RESUB.94
p4htmb        79.39684         64.16723        30.733755       122.18868
fkbp5        158.79368        120.31356       390.082280       315.11817
fbxo2         11.76250         13.63554        18.913080        12.05809
LOC132466537 379.34047        193.30379       184.402532       267.68967
LOC132466614 267.59676        171.64735        94.565401       154.34359
ccdc3b        28.42603         24.06271         5.516315        19.29295
# Annotate heatmap
annotation <- infosub_L.9.5 %>% 
    dplyr::select(temp_treatment)

# Set a color palette
heat_colors <- rev(brewer.pal(12, "RdYlBu"))

# Run pheatmap
h.L.9.5 <- pheatmap(norm_sig_L.9.5, 
                     color = heat_colors, 
                     cluster_rows = T, 
                     show_rownames = F,
                     annotation = annotation, 
                     border_color = NA, 
                     fontsize = 10,
                     scale = "row", 
                     fontsize_row = 10, 
                     height = 30,
                     main = "Normalized Significant Expression, Liver, 9*C and 5*C")

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-heatmap_L.9.5_norm_sig.png",
         plot   = h.L.9.5,
         res    = 600,
         width  = 5000,
         height = 5000)

Note the argument scale="row" was included, so the values plotted in the heat map are Z-scores, rather thn the normalized count value. This vastly improves the color visualization.

For DEGs based on adjusted p-value only

# Extract normalized expression for significant genes
norm_sig_L.9.5_noLFCcutoff <- dds_L.9.5_norm_counts %>% 
  data.frame() %>%
  filter(row.names(dds_L.9.5_norm_counts) %in% sig_L.9.5_norm_noLFCcutoff$gene)

head(norm_sig_L.9.5_noLFCcutoff)
                  sample_100 sample_107 sample_108 sample_109 sample_110
p4htmb             53.727408   78.23193   49.33584  44.069179   48.34665
patz1              55.518321   70.27614  108.43607  50.981991   38.67732
fkbp5             188.941383  163.09369  145.95187 258.366361  182.10573
si:ch211-117k10.3  44.772840   37.12702   34.94622  24.194843   40.28888
snrpe             468.323903  533.03791  362.82401 632.522328  614.80830
fbxo2               3.581827    2.65193   10.27830   5.184609   12.89244
                  sample_117 sample_118 sample_119 sample_120 sample_121
p4htmb             86.072979   15.12887   16.06242   42.41875   13.12144
patz1              69.565832   43.41328   21.41657   48.22954   59.04646
fkbp5             360.209521  759.73235  331.19189 1065.11742  814.84117
si:ch211-117k10.3  74.282160   73.01324   48.95215   67.98622   44.61288
snrpe             500.520267  569.63482  987.45666  471.83598  947.36767
fbxo2               9.432655   11.83998   10.70828   15.68913  101.03506
                  sample_127 sample_128 sample_131  sample_137 sample_138
p4htmb              15.02789  30.123885   29.18508   17.799905   25.14052
patz1               66.84820  84.346879   59.58620   60.074679   50.28103
fkbp5              674.70047 466.920222 1096.87252  453.897575 1064.28185
si:ch211-117k10.3   71.51203  55.729188   82.69105   60.074679   61.45459
snrpe              561.73219 652.182116  417.10341 1063.544318 1173.22409
fbxo2               11.91867   4.518583    7.29627    8.899952   13.96695
                  sample_139 sample_140 sample_147 sample_148 sample_150
p4htmb              21.71330  25.066986   19.23673   28.61782  20.728754
patz1               54.28326  57.967405   34.97588   60.86964  52.912872
fkbp5              313.03347 198.969202  251.82632  504.21869 505.127001
si:ch211-117k10.3   85.04378  65.800838  103.17884   51.78462  40.912014
snrpe              741.87123 777.076568  734.49343  463.33610 505.127001
fbxo2               28.95107   7.833433   17.48794    8.63077   8.727896
                   sample_78 sample_79  sample_80  sample_83  sample_88
p4htmb             30.208488  62.79026  50.095212  22.174947  26.914531
patz1              71.136118  42.17256 125.729160  51.352510 107.658122
fkbp5             416.097565 118.08318 166.001782 772.621851 218.826835
si:ch211-117k10.3  24.361684  44.04690  58.935544  44.349895  25.744334
snrpe             540.829388 428.28581 511.756973 548.538172 492.652929
fbxo2               1.948935  14.05752   5.893554   1.167102   9.361576
                   sample_90 sample_91 sample_92  sample_97  sample_98
p4htmb             32.999136  59.06621  76.93003   6.986541   3.654154
patz1             218.894267  43.41011  44.70259  88.030412 227.775610
fkbp5             406.989341 272.55853 122.67221 262.693928  77.955289
si:ch211-117k10.3  13.199654  49.10323  28.06907  22.356930  36.541542
snrpe             444.388362 411.32854 339.94758 496.044385 356.889058
fbxo2               4.399885  10.67462   0.00000   9.781157   0.000000
                  sample_99 sample_RESUB.116 sample_RESUB.156 sample_RESUB.94
p4htmb             79.39684         64.16723         30.73376       122.18868
patz1              82.33747         70.58396         62.25556       138.26613
fkbp5             158.79368        120.31356        390.08228       315.11817
si:ch211-117k10.3  84.29788        108.28221         57.52729        57.87885
snrpe             331.31028        297.57555        446.82152       295.82522
fbxo2              11.76250         13.63554         18.91308        12.05809
# Annotate heatmap
annotation <- infosub_L.9.5 %>% 
    dplyr::select(temp_treatment)

# Set a color palette
heat_colors <- rev(brewer.pal(12, "RdYlBu"))

# Run pheatmap
h.L.9.5 <- pheatmap(norm_sig_L.9.5_noLFCcutoff, 
                     color = heat_colors, 
                     cluster_rows = T, 
                     show_rownames = F,
                     annotation = annotation, 
                     border_color = NA, 
                     fontsize = 10,
                     scale = "row", 
                     fontsize_row = 10, 
                     height = 30,
                     main = "Normalized Significant Expression (no LFC cutoff), Liver, 9*C and 5*C")

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/heatmap_L.9.5_norm_sig_noLFCcutoff.png",
         plot   = h.L.9.5,
         res    = 600,
         width  = 5000,
         height = 5000)

6.3 Volcano plot

# Generate plot
v.L.9.5 <- 
  ggplot(res_table_L.9.5_norm_tb) +
  # Plot all
  geom_point(aes(x=log2FoldChange, y=-log10(padj),color="unchanged"),
             size=.5) +
  # Overlay all significantly upregulated in red
  geom_point(data = sig_L.9.5_norm[sig_L.9.5_norm$log2FoldChange > 0, ], 
             aes(x=log2FoldChange, y=-log10(padj), color="upregulated"), 
             size=.5) +
  # Overlay all significantly downregulated in blue
  geom_point(data = sig_L.9.5_norm[sig_L.9.5_norm$log2FoldChange < 0, ], 
             aes(x=log2FoldChange, y=-log10(padj), color="downregulated"), 
             size=.5) +
  ggtitle("Liver, 9*C and 0*C") +
  xlab("log2 fold change") + 
  ylab("-log10 adjusted p-value") +
  scale_x_continuous(limits = c(-4,4)) +
  scale_y_continuous(limits = c(0,30)) +
  scale_color_manual(values = c("unchanged" = "darkgrey", "upregulated" = "red", "downregulated" = "blue"),
                     labels = c("unchanged" = "Unchanged", "upregulated" = "Upregulated", "downregulated" = "Downregulated"),
                     name = NULL) +
  theme(legend.position = "top",
        plot.title = element_text(size = rel(1.5), hjust = 0.5),
        axis.title = element_text(size = rel(1.25)))

v.L.9.5

# Save plot
ggexport(filename = "../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/exon-volcano_L.9.5.png",
         plot   = v.L.9.0,
         res    = 600,
         width  = 6000,
         height = 4000)

6.4 Plot expression of top DEGs across treatments

top15DEGs_L.9.5 <- sig_L.9.5_norm_noLFCcutoff %>%
  arrange(padj) %>%
  slice_head(n=15)

L.9.5_DEG1 <- plot_gene_data(top15DEGs_L.9.5[1, ]$gene)
L.9.5_DEG1

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG1.",top15DEGs_L.9.5[1, ]$gene,".png"), plot = L.9.5_DEG1, res = 600, width = 5000, height = 5000)

L.9.5_DEG2 <- plot_gene_data(top15DEGs_L.9.5[2, ]$gene)
L.9.5_DEG2

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG2.",top15DEGs_L.9.5[2, ]$gene,".png"), plot = L.9.5_DEG2, res = 600, width = 5000, height = 5000)

L.9.5_DEG3 <- plot_gene_data(top15DEGs_L.9.5[3, ]$gene)
L.9.5_DEG3

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG3.",top15DEGs_L.9.5[3, ]$gene,".png"), plot = L.9.5_DEG3, res = 600, width = 5000, height = 5000)

L.9.5_DEG4 <- plot_gene_data(top15DEGs_L.9.5[4, ]$gene)
L.9.5_DEG4

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG4.",top15DEGs_L.9.5[4, ]$gene,".png"), plot = L.9.5_DEG4, res = 600, width = 5000, height = 5000)

L.9.5_DEG5 <- plot_gene_data(top15DEGs_L.9.5[5, ]$gene)
L.9.5_DEG5

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG5.",top15DEGs_L.9.5[5, ]$gene,".png"), plot = L.9.5_DEG5, res = 600, width = 5000, height = 5000)

L.9.5_DEG6 <- plot_gene_data(top15DEGs_L.9.5[6, ]$gene)
L.9.5_DEG6

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG6.",top15DEGs_L.9.5[6, ]$gene,".png"), plot = L.9.5_DEG6, res = 600, width = 5000, height = 5000)

L.9.5_DEG7 <- plot_gene_data(top15DEGs_L.9.5[7, ]$gene)
L.9.5_DEG7

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG7.",top15DEGs_L.9.5[7, ]$gene,".png"), plot = L.9.5_DEG7, res = 600, width = 5000, height = 5000)

L.9.5_DEG8 <- plot_gene_data(top15DEGs_L.9.5[8, ]$gene)
L.9.5_DEG8

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG8.",top15DEGs_L.9.5[8, ]$gene,".png"), plot = L.9.5_DEG8, res = 600, width = 5000, height = 5000)

L.9.5_DEG9 <- plot_gene_data(top15DEGs_L.9.5[9, ]$gene)
L.9.5_DEG9

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG9.",top15DEGs_L.9.5[9, ]$gene,".png"), plot = L.9.5_DEG9, res = 600, width = 5000, height = 5000)

L.9.5_DEG10 <- plot_gene_data(top15DEGs_L.9.5[10, ]$gene)
L.9.5_DEG10

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG10.",top15DEGs_L.9.5[10, ]$gene,".png"), plot = L.9.5_DEG10, res = 600, width = 5000, height = 5000)

L.9.5_DEG11 <- plot_gene_data(top15DEGs_L.9.5[11, ]$gene)
L.9.5_DEG11

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG11.",top15DEGs_L.9.5[11, ]$gene,".png"), plot = L.9.5_DEG11, res = 600, width = 5000, height = 5000)

L.9.5_DEG12 <- plot_gene_data(top15DEGs_L.9.5[12, ]$gene)
L.9.5_DEG12

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG12.",top15DEGs_L.9.5[12, ]$gene,".png"), plot = L.9.5_DEG12, res = 600, width = 5000, height = 5000)

L.9.5_DEG13 <- plot_gene_data(top15DEGs_L.9.5[13, ]$gene)
L.9.5_DEG13

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG13.",top15DEGs_L.9.5[13, ]$gene,".png"), plot = L.9.5_DEG13, res = 600, width = 5000, height = 5000)

L.9.5_DEG14 <- plot_gene_data(top15DEGs_L.9.5[14, ]$gene)
L.9.5_DEG14

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG14.",top15DEGs_L.9.5[14, ]$gene,".png"), plot = L.9.5_DEG14, res = 600, width = 5000, height = 5000)

L.9.5_DEG15 <- plot_gene_data(top15DEGs_L.9.5[15, ]$gene)
L.9.5_DEG15

ggexport(filename = paste("../output/07.2.1-cod-RNAseq-DESeq2-genome-exon/L.9.5_DEG15.",top15DEGs_L.9.5[15, ]$gene,".png"), plot = L.9.5_DEG15, res = 600, width = 5000, height = 5000)
LS0tCnRpdGxlOiAiMDcuMi4xLWNvZC1STkFzZXEtREVTZXEyZ2Vub21lLWV4b24iCmF1dGhvcjogIkthdGhsZWVuIER1cmtpbiIKZGF0ZTogIjIwMjQtMDQtMzAiCmFsd2F5c19hbGxvd19odG1sOiB0cnVlCm91dHB1dDogCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICBnaXRodWJfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBodG1sX3ByZXZpZXc6IHRydWUgCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwgICAgICAgICAjIERpc3BsYXkgY29kZSBjaHVua3MKICBldmFsID0gVFJVRSwgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKRGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBhbmFseXNpcyBmb3IgW1BhY2lmaWMgY29kIFJOQXNlcSBkYXRhXShodHRwczovL3NoZWR1cmtpbi5naXRodWIuaW8vUm9iZXJ0cy1MYWJOb3RlYm9vay9wb3N0cy9wcm9qZWN0cy9wYWNpZmljX2NvZC8yMDIzXzEyXzEzX3BhY2lmaWNfY29kLmh0bWwpLgoKLSAgIFJhdyByZWFkcyBmb3VuZCBbaGVyZV0oaHR0cHM6Ly9vd2wuZmlzaC53YXNoaW5ndG9uLmVkdS9uaWdodGluZ2FsZXMvR19tYWNyb2NlcGhhbHVzLzMwLTk0MzEzMzgwNi8pCi0gICBSZWFkcyBhbGlnbmVkIHRvIGdlbm9tZSBkb3dubG9hZGVkIGZyb20gW05DQkldKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvZGF0YXNldHMvZ2Vub21lL0dDRl8wMzExNjg5NTUuMS8pCi0gICBOT1RFIHRoaXMgYW5hbHlzaXMgaXMgZm9yIHRoZSBmZWF0dXJlQ291bnRzICpleG9ucyogKHNlZSBgMDYuMi1jb2QtUk5Bc2VxLWFsaWdubWVudC1nZW5vbWVgKQoKIyMjIEluc3RhbGwgYW5kIGxvYWQgcGFja2FnZXMKCmBgYHtyIGxvYWRfbGlicmFyaWVzLCBpbmxjdWRlID0gVFJVRX0KCiMjIGNsZWFyCnJtKGxpc3Q9bHMoKSkKCiMjIEluc3RhbGwgUnRvb2xzIGRpcmVjdGx5IGZyb20gKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL2Jpbi93aW5kb3dzL1J0b29scy8pLCB0aGVuIGluc3RhbGwgdGhlc2Ugb24gZmlyc3QgcnVuOgojIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikKIyBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiREVTZXEyIikKIyBCaW9jTWFuYWdlcjo6aW5zdGFsbCgidnNuIikKIyBCaW9jTWFuYWdlcjo6aW5zdGFsbCgidGlkeWJ1bGsiKQojIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJnb3NlcSIpCiMgQmlvY01hbmFnZXI6Omluc3RhbGwoImFmZnljb3JldG9vbHMiKQojIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJFbmhhbmNlZFZvbGNhbm8iKQojIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJwY2FFeHBsb3JlciIpCiMgQmlvY01hbmFnZXI6Omluc3RhbGwoImFwZWdsbSIpCiMgQmlvY01hbmFnZXI6Omluc3RhbGwoIlBDQXRvb2xzIikKCgojIExpc3Qgb2YgcGFja2FnZXMgd2Ugd2FudCB0byBpbnN0YWxsIChydW4gZXZlcnkgdGltZSkKbG9hZC5saWI8LWMoIkRFU2VxMiIsImVkZ2VSIiwiZ29zZXEiLCJkcGx5ciIsIkdlbm9taWNGZWF0dXJlcyIsImRhdGEudGFibGUiLCJjYWxpYnJhdGUiLCJhZmZ5Y29yZXRvb2xzIiwiZGF0YS50YWJsZSIsInZzbiIsInRpZHlidWxrIiwiZ2dwbG90MiIsImNvd3Bsb3QiLCJwaGVhdG1hcCIsImdwbG90cyIsIlJDb2xvckJyZXdlciIsIkVuaGFuY2VkVm9sY2FubyIsInBjYUV4cGxvcmVyIiwicmVhZHhsIiwiYXBlZ2xtIiwiYXNociIsInRpYmJsZSIsInBsb3RseSIsInNxbGRmIiwiUENBdG9vbHMiLCJnZ3B1YnIiLCJiZWVwciIsImdlbmVmaWx0ZXIiLCJDb21wbGV4SGVhdG1hcCIsImNpcmNsaXplIiwic2NhbGVzIiwgInRpZHl2ZXJzZSIsICJncmlkZXh0cmEnIikKCiMgU2VsZWN0IG9ubHkgdGhlIHBhY2thZ2VzIHRoYXQgYXJlbid0IGN1cnJlbnRseSBpbnN0YWxsZWQgKHJ1biBldmVyeSB0aW1lKQojIGluc3RhbGwubGliIDwtIGxvYWQubGliWyFsb2FkLmxpYiAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpXQoKIyBBbmQgZmluYWxseSB3ZSBpbnN0YWxsIHRoZSBtaXNzaW5nIHBhY2thZ2VzLCBpbmNsdWRpbmcgdGhlaXIgZGVwZW5kZW5jeS4KIyBmb3IobGliIGluIGluc3RhbGwubGliKSBpbnN0YWxsLnBhY2thZ2VzKGxpYixkZXBlbmRlbmNpZXM9VFJVRSkKIyBBZnRlciB0aGUgaW5zdGFsbGF0aW9uIHByb2Nlc3MgY29tcGxldGVzLCB3ZSBsb2FkIGFsbCBwYWNrYWdlcy4Kc2FwcGx5KGxvYWQubGliLHJlcXVpcmUsY2hhcmFjdGVyPVRSVUUpCiAgICAgICAgICAgICAgICAgICAgICAgIApgYGAKCkkgZm91bmQgdGhlIFtERVNlcTIgdmlnbmV0dGVdKGh0dHBzOi8vd3d3LmJpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL3ZpZ25ldHRlcy9ERVNlcTIvaW5zdC9kb2MvREVTZXEyLmh0bWwpIGFuZCB0aGUgW0hCQyBER0UgdHJhaW5pbmcgd29ya3Nob3BdKGh0dHBzOi8vZ2l0aHViLmNvbS9oYmN0cmFpbmluZy9ER0Vfd29ya3Nob3ApIHN1cGVyIGhlbHBmdWwgaW4gZmlndXJpbmcgb3V0IGhvdyB0byB1c2UgdGhlIERFU2VxMiBwYWNrYWdlIQoKIyBMb2FkIGRhdGEKCiMjIExvYWQgY291bnQgZGF0YQoKTG9hZCBpbiB0aGUgY291bnQgbWF0cml4IHdlIGdlbmVyYXRlZCBhZnRlciBhbGlnbm1lbnQgdXNpbmcgdGhlIGZlYXR1cmVDb3VudHMuIFdlIGFsc28gbmVlZCB0byBzbGlnaHRseSByZWZvcm1hdCB0aGUgY291bnQgbWF0cml4IHRvIG1ha2UgYWxsIG9mIHRoZSBlc3RpbWF0ZWQgY291bnRzIGludGVnZXJzLCBhcyByZXF1aXJlZCBmb3IgREVTZXEyLgoKYGBge3J9CiMgUmVhZCBpbiBjb3VudHMgZGF0YS4gVGhpcyBpcyBhIGdlbmUtbGV2ZWwgY291bnRzIG1hdHJpeCBnZW5lcmF0ZWQgZnJvbSBoaXNhdDIgYW5kIHN1bW1hcml6ZWQgdXNpbmcgZmVhdHVyZUNvdW50cwpjb2RfY291bnRzX2RhdGFfT0cgPC0gcmVhZF9kZWxpbSgiLi4vb3V0cHV0LzA2LjItY29kLVJOQXNlcS1hbGlnbm1lbnQtZ2Vub21lL2ZlYXR1cmVDb3VudHMtZXhvbi9mZWF0dXJlQ291bnRzX2V4b25fbWF0cml4X25vaGVhZGVyLnR4dCIsIGRlbGltPSJcdCIpIApoZWFkKGNvZF9jb3VudHNfZGF0YV9PRykKYGBgCgojIyBDb3VudCBkYXRhIG11bmdpbmcKCmBgYHtyfQojICMgV2UgbmVlZCB0byBtb2RpZnkgdGhpcyBkYXRhIGZyYW1lIHNvIHRoYXQgdGhlIHJvdyBuYW1lcyBhcmUgYWN0dWFsbHkgcm93IG5hbWVzLCBpbnN0ZWFkIG9mIGNvbXByaXNpbmcgdGhlIGZpcnN0IGNvbHVtbgpjb2RfY291bnRzX2RhdGEgPC0gY29kX2NvdW50c19kYXRhX09HICU+JSAKICBjb2x1bW5fdG9fcm93bmFtZXModmFyID0gIkdlbmVpZCIpCgojIEFkZGl0aW9uYWwgZm9ybWF0dGluZwojIFJlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW5zIApjb2RfY291bnRzX2RhdGEgPC0gc3Vic2V0KGNvZF9jb3VudHNfZGF0YSwgc2VsZWN0ID0gLWMoQ2hyLCBTdGFydCwgRW5kLCBTdHJhbmQsIExlbmd0aCkpCgojIFJlbW92ZSB0aGUgZGlyZWN0b3J5IHBhdGggYW5kIGZpbGUgdHlwZSBwb3J0aW9ucyBvZiB0aGUgY29sdW1uIG5hbWVzLCB0byBsZWF2ZSBqdXN0IHRoZSBzYW1wbGUgbmFtZXMKY29sbmFtZXMoY29kX2NvdW50c19kYXRhKSA8LSBzdWIoIi4uL291dHB1dC8wNi4yLWNvZC1STkFzZXEtYWxpZ25tZW50LWdlbm9tZS9oaXNhdDIvIiwgInNhbXBsZV8iLCBjb2xuYW1lcyhjb2RfY291bnRzX2RhdGEpKQpjb2xuYW1lcyhjb2RfY291bnRzX2RhdGEpIDwtIHN1YigiLnNvcnRlZC5iYW0iLCAiIiwgY29sbmFtZXMoY29kX2NvdW50c19kYXRhKSkKCiMgUmVvcmRlciB0aGUgY291bW5zIGludG8gYWxwaGFiZXRpY2FsIG9yZGVyICh0byBtYWtlIGl0IGVhc2llciB0byBjcmVhdGUgYW4gYXNzb2NpYXRlZCBtZXRhZGF0YSBzcHJlYWRzaGVldCkKY29kX2NvdW50c19kYXRhIDwtIGNvZF9jb3VudHNfZGF0YVssIG9yZGVyKGNvbG5hbWVzKGNvZF9jb3VudHNfZGF0YSkpXQoKY29kX3NhbXBsZV9uYW1lcyA8LSBuYW1lcyhjb2RfY291bnRzX2RhdGEpCgp3cml0ZS50YWJsZShjb2RfY291bnRzX2RhdGEsIGZpbGUgPSAiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9HbWFjX2dlbm9tZV9leG9uX2NvdW50c19mb3JtYXR0ZWQudGFiIiwgc2VwID0gIlx0IiwKICAgICAgICAgICAgcm93Lm5hbWVzID0gVFJVRSwgY29sLm5hbWVzID0gTkEpCgpoZWFkKGNvZF9jb3VudHNfZGF0YSkKY29kX3NhbXBsZV9uYW1lcwpgYGAKCiMjIEltcG9ydCBzYW1wbGUgbWV0YWRhdGEgc2hlZXRzCgpgYGB7cn0KIyBSZWFkIGluIHRoZSBjc3YgZmlsZSBhcyBhIGRhdGEgZnJhbWUKY29kX3NhbXBsZV9pbmZvX09HIDwtIHJlYWQuY3N2KCJ+L3Byb2plY3QtY29kLXRlbXBlcmF0dXJlL2RhdGEvREVTZXEyX1NhbXBsZV9JbmZvcm1hdGlvbi5jc3YiKQpjb2RfZXhwZXJpbWVudF9hbGxkYXRhX09HIDwtIHJlYWQuY3N2KCJ+L3Byb2plY3QtY29kLXRlbXBlcmF0dXJlL2RhdGEvdGVtcC1leHBlcmltZW50LmNzdiIpCmhlYWQoY29kX3NhbXBsZV9pbmZvX09HKQpoZWFkKGNvZF9leHBlcmltZW50X2FsbGRhdGFfT0cpCgojIFJlbmFtZSB0aGUgIkdlbmV0aWNTYW1wbGluZ0NvdW50IiBjb2x1bW4gb2YgdGhlIGV4cGVyaW1lbnRhbCBkYXRhIHRvICJzYW1wbGVfbnVtYmVyIgpjb2RfZXhwZXJpbWVudF9hbGxkYXRhIDwtIGNvZF9leHBlcmltZW50X2FsbGRhdGFfT0cKbmFtZXMoY29kX2V4cGVyaW1lbnRfYWxsZGF0YSlbbmFtZXMoY29kX2V4cGVyaW1lbnRfYWxsZGF0YSkgPT0gIkdlbmV0aWNTYW1wbGluZ0NvdW50Il0gPC0gInNhbXBsZV9udW1iZXIiCgojIENhbGN1bGF0ZSBsZW5ndGggZGlmZmVyZW5jZSBhbmQgd2VpZ2h0IGRpZmZlcmVuY2UgKGVuZC1iZWdpbm5pbmcpCmNvZF9leHBlcmltZW50X2FsbGRhdGEkU0xfZGlmZl9tbSA8LSBjb2RfZXhwZXJpbWVudF9hbGxkYXRhJFNMX21tIC0gY29kX2V4cGVyaW1lbnRfYWxsZGF0YSRTTF8xMTIxMjAyMgpjb2RfZXhwZXJpbWVudF9hbGxkYXRhJFdXVF9kaWZmX2cgPC0gY29kX2V4cGVyaW1lbnRfYWxsZGF0YSRXaG9sZUJvZHlXV19nIC0gY29kX2V4cGVyaW1lbnRfYWxsZGF0YSRXV1RfMTEyMTIwMjIKCiMgTWVyZ2UgdGhlIHR3byBkYXRhIGZyYW1lcyB0byBnZXQgZXhwZXJpbWVudGFsIGRhdGEgZm9yIGFsbCBvZiBvdXIgUk5Bc2VxJ2Qgc2FtcGxlcy4KIyBUaGlzIHNob3VsZCBpbmNsdWRlIGFsbCByb3dzIGZyb20gY29kX3NhbXBsZV9pbmZvX09HIGFuZCBtYXRjaGluZyByb3dzIGZyb20gY29kX2V4cGVyaW1lbnRfYWxsZGF0YSBiYXNlZCBvbiB0aGUgc2hhcmVkIHNhbXBsZV9udW1iZXIgY29sdW1uLiBTYW1wbGUgbnVtYmVyIGR1cGxpY2F0ZXMgKGUuZy4gZnJvbSBkaWZmZXJlbnQgdGlzc3VlIHR5cGVzKSBzaG91bGQgYmUgcmV0YWluZWQuCmNvZF9zYW1wbGVfaW5mbyA8LSBtZXJnZShjb2Rfc2FtcGxlX2luZm9fT0csIGNvZF9leHBlcmltZW50X2FsbGRhdGEsIGJ5ID0gInNhbXBsZV9udW1iZXIiLCBhbGwueCA9IFRSVUUpCgojIFJlb3JkZXIgdGhlIGRhdGEgZnJhbWUgaW50byBhbHBoYWJldGljYWwgb3JkZXIgYnkgdGhlIHNhbXBsZSBuYW1lcywgc28gdGhhdCB0aGUgcm93cyBhcmUgaW4gdGhlIHNhbWUgb3JkZXIgYXMgb3VyIGNvdW50IG1hdHJpeCBjb2x1bW5zCmNvZF9zYW1wbGVfaW5mbyA8LSBjb2Rfc2FtcGxlX2luZm9bb3JkZXIoY29kX3NhbXBsZV9pbmZvJHNhbXBsZV9uYW1lKSwgXQoKIyBBZ2Fpbiwgd2UgbmVlZCB0byByZWZvcm1hdCBzbyB0aGF0IHRoZSBkYXRhIGluIHRoZSBmaXJzdCBjb2x1bW4gYmVjb21lcyB0aGUgcm93IG5hbWVzCnJvd25hbWVzKGNvZF9zYW1wbGVfaW5mbykgPC0gY29kX3NhbXBsZV9pbmZvJHNhbXBsZV9uYW1lCgojIFJlbW92ZSBkdXBsaWNhdGUgY29sdW1ucyAoYXJ0aWZhY3Qgb2YgbWVyZ2luZyBkYXRhIGZyYW1lcyB3aXRoIG11bHRpcGxlIHNoYXJlZCBjb2x1bW5zIGFuZCBvZiBtYWluZyBzYW1wbGVfbmFtZSB0aGUgcm93bmFtZXMgaW5zdGVhZCBvZiBhIHZhcmlhYmxlKQpjb2Rfc2FtcGxlX2luZm8gPC0gc3Vic2V0KGNvZF9zYW1wbGVfaW5mbywgc2VsZWN0PS1UZW1wZXJhdHVyZSkKY29kX3NhbXBsZV9pbmZvIDwtIHN1YnNldChjb2Rfc2FtcGxlX2luZm8sIHNlbGVjdD0tVGFuaykKI2NvZF9zYW1wbGVfaW5mbyA8LSBzdWJzZXQoY29kX3NhbXBsZV9pbmZvLCBzZWxlY3Q9LXNhbXBsZV9uYW1lKQoKCmhlYWQoY29kX3NhbXBsZV9pbmZvKQpgYGAKCiMjIFNhbXBsZSBtZXRhZGF0YSBtdW5naW5nCgpgYGB7cn0KIyBGYWN0b3IgdmFyaWFibGVzCmNvZF9zYW1wbGVfaW5mbyR0ZW1wX3RyZWF0bWVudCA8LSBmYWN0b3IoY29kX3NhbXBsZV9pbmZvJHRlbXBfdHJlYXRtZW50KQpjb2Rfc2FtcGxlX2luZm8kdGFuayA8LSBmYWN0b3IoY29kX3NhbXBsZV9pbmZvJHRhbmspCmNvZF9zYW1wbGVfaW5mbyR0aXNzdWVfdHlwZSA8LSBmYWN0b3IoY29kX3NhbXBsZV9pbmZvJHRpc3N1ZV90eXBlKQoKIyBSZW1vdmUgYmFkL21pc3Npbmcgc2FtcGxlcwojIE11bGlRQyByZXBvcnQ6IDE0OSwgMTI5CiMgUENBIG91dGxpZXJzOiAzMSwgNDEgKHBlciBMYXVyYSkKY29kX3NhbXBsZV9pbmZvIDwtIGNvZF9zYW1wbGVfaW5mb1shKHJvdy5uYW1lcyhjb2Rfc2FtcGxlX2luZm8pICVpbiUgYygic2FtcGxlXzE0OSIsICJzYW1wbGVfMTI5IiwgInNhbXBsZV8zMSIsICJzYW1wbGVfNDEiKSksXQpjb2RfY291bnRzX2RhdGEgPC0gYXMubWF0cml4KHN1YnNldChjb2RfY291bnRzX2RhdGEsIHNlbGVjdD0tYyhzYW1wbGVfMTQ5LCBzYW1wbGVfMTI5LCBzYW1wbGVfMzEsIHNhbXBsZV80MSkpKQoKIyBDaGVjayB0aGF0IHRoZSBjb2x1bW4gbmFtZXMgb2Ygb3VyIGNvdW50IGRhdGEgbWF0Y2ggdGhlIHJvdyBuYW1lcyBvZiBvdXIgc2FtcGxlIGluZm8gc2hlZXQKbmNvbChjb2RfY291bnRzX2RhdGEpCm5yb3coY29kX3NhbXBsZV9pbmZvKQoKYWxsKGNvbG5hbWVzKGNvZF9jb3VudHNfZGF0YSkgJWluJSByb3duYW1lcyhjb2Rfc2FtcGxlX2luZm8pKQphbGwoY29sbmFtZXMoY29kX2NvdW50c19kYXRhKSA9PSByb3duYW1lcyhjb2Rfc2FtcGxlX2luZm8pKQpgYGAKCkNvbWJpbmUgY291bnRzIGRhdGEgYW5kIHNhbXBsZSBtZXRhZGF0YSBmb3IgbGF0ZXIgYW5hbHlzZXMKYGBge3J9CiMgTWVsdCBjb2RfY291bnRzX2RhdGEgdG8gbG9uZyBmb3JtYXQKY29kX2NvdW50c19kYXRhX2xvbmcgPC0gYXMuZGF0YS5mcmFtZShjb2RfY291bnRzX2RhdGEpCmNvZF9jb3VudHNfZGF0YV9sb25nJGdlbmUgPC0gcm93bmFtZXMoY29kX2NvdW50c19kYXRhX2xvbmcpCmNvZF9jb3VudHNfZGF0YV9sb25nIDwtIGNvZF9jb3VudHNfZGF0YV9sb25nICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXJ0c193aXRoKCJzYW1wbGUiKSwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInNhbXBsZV9uYW1lIiwgCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJjb3VudCIpCgpjb2xuYW1lcyhjb2RfY291bnRzX2RhdGFfbG9uZykKY29sbmFtZXMoY29kX3NhbXBsZV9pbmZvKQoKIyBNZXJnZSBjb2RfY291bnRzX2RhdGFfbG9uZyB3aXRoIGRmX0MgdG8gZ2V0IHRyZWF0bWVudCBpbmZvCmNvZF9jb3VudHNkYXRhX3BsdXNfc2FtcGxlaW5mbyA8LSBsZWZ0X2pvaW4oY29kX2NvdW50c19kYXRhX2xvbmcsIGNvZF9zYW1wbGVfaW5mbywgYnkgPSAic2FtcGxlX25hbWUiKQpgYGAKCiMgUHJlbGltaW5hcnkgUENBIHZpc3VhbGl6YXRpb24gKGxpdmVyIHRpc3N1ZSkKCiMjIERFU2VxIG9iamVjdAoKYGBge3IsIGNhY2hlPVRSVUV9CiMgRmlsdGVyIGRhdGEKaW5mb3N1Yl9MIDwtIGNvZF9zYW1wbGVfaW5mbyAlPiUgZmlsdGVyKHRpc3N1ZV90eXBlID09ICJMaXZlciIpCmNvdW50c3ViX0wgPC0gc3Vic2V0KGNvZF9jb3VudHNfZGF0YSwgc2VsZWN0PXJvdy5uYW1lcyhpbmZvc3ViX0wpKQoKIyBDYWxjdWxhdGUgREVTZXEgb2JqZWN0CmRkc19MIDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnREYXRhID0gY291bnRzdWJfTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IGluZm9zdWJfTCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiB0ZW1wX3RyZWF0bWVudCkgCgojIFJ1biBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNpcyAKIyAoTm90ZSB0aGF0IHRoaXMgREVTZXEoKSBmdW5jdGlvbiBydW5zIGFsbCBuZWNlc3Nhcnkgc3RlcHMsIGluY2x1ZGluZyBkYXRhIG5vcm1hbGl6YXRpb24sIAojIGVzdGltYXRpbmcgc2l6ZSBmYWN0b3JzLCBlc3RpbWF0aW5nIGRpc3BlcnNpb25zLCBnZW5lLXdpc2UgZGlzcGVyc2lvbiBlc3RpbWF0ZXMsIG1lYW4tZGlzcGVyc2lvbiAKIyByZWxhdGlvbnNoaXAsIGZpbmFsIGRpc3BlcnNpb24gZXN0aW1hdGVzLCBmaXR0aW5nIG1vZGVsLCBhbmQgdGVzdGluZykKZGRzX0wgPC0gREVTZXEoZGRzX0wpCnJlc3VsdHNOYW1lcyhkZHNfTCkgIyBsaXN0cyB0aGUgY29lZmZpY2llbnRzCmBgYAoKYGBge3J9CnBsb3REaXNwRXN0cyhkZHNfTCkKYGBgCgojIyBQQ0EgdmlzdWFsaXphdGlvbgoKYGBge3J9CiMgR2VuZXJhdGUgUENBcwojIHRvcCA1MDAgbW9zdCB2YXJpYWJsZSBnZW5lcwpwY2FfTF81MDA8LSBwbG90UENBKHZzdChkZHNfTCksIGludGdyb3VwID0gYygidGVtcF90cmVhdG1lbnQiKSwgcmV0dXJuRGF0YT1UUlVFKQpwZXJjZW50VmFyX0xfNTAwIDwtIHJvdW5kKDEwMCphdHRyKHBjYV9MXzUwMCwgInBlcmNlbnRWYXIiKSkKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIHNoZWV0IHNvIHdlIGNhbiBwbG90IHVzaW5nIG90aGVyIGZlYXR1cmVzCnBjYV9MXzUwMCA8LSBzdWJzZXQocGNhX0xfNTAwLCBzZWxlY3Q9LXRlbXBfdHJlYXRtZW50KSAjcmVtb3ZlIHRoZSB0ZW1wX3RyZWF0bWVudCBjb2x1bW4sIHdoaWNoIHdpbGwgYmUgYSBkdXBsaWNhdGUgcG9zdC1tZXJnZQpwY2FfTF81MDAgPC0gbWVyZ2UocGNhX0xfNTAwLCBjb2Rfc2FtcGxlX2luZm8sIGJ5LnggPSAibmFtZSIsIGJ5LnkgPSAicm93Lm5hbWVzIikKCiMgdG9wIDEwMDAgbW9zdCB2YXJpYWJsZSBnZW5lcwpwY2FfTF8xMDAwIDwtIHBsb3RQQ0EodnN0KGRkc19MKSwgaW50Z3JvdXAgPSBjKCJ0ZW1wX3RyZWF0bWVudCIpLCByZXR1cm5EYXRhPVRSVUUsIG50b3A9MTAwMCkKcGVyY2VudFZhcl9MXzEwMDAgPC0gcm91bmQoMTAwKmF0dHIocGNhX0xfMTAwMCwgInBlcmNlbnRWYXIiKSkKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIHNoZWV0IHNvIHdlIGNhbiBwbG90IHVzaW5nIG90aGVyIGZlYXR1cmVzCnBjYV9MXzEwMDAgPC0gc3Vic2V0KHBjYV9MXzEwMDAsIHNlbGVjdD0tdGVtcF90cmVhdG1lbnQpICNyZW1vdmUgdGhlIHRlbXBfdHJlYXRtZW50IGNvbHVtbiwgd2hpY2ggd2lsbCBiZSBhIGR1cGxpY2F0ZSBwb3N0LW1lcmdlCnBjYV9MXzEwMDAgPC0gbWVyZ2UocGNhX0xfMTAwMCwgY29kX3NhbXBsZV9pbmZvLCBieS54ID0gIm5hbWUiLCBieS55ID0gInJvdy5uYW1lcyIpCgojIGFsbCBnZW5lcwpwY2FfTF9hbGwgPC0gcGxvdFBDQSh2c3QoZGRzX0wpLCBpbnRncm91cCA9IGMoInRlbXBfdHJlYXRtZW50IiksIHJldHVybkRhdGE9VFJVRSwgbnRvcD1ucm93KGFzc2F5KHZzdChkZHNfTCkpKSkKcGVyY2VudFZhcl9MX2FsbCA8LSByb3VuZCgxMDAqYXR0cihwY2FfTF9hbGwsICJwZXJjZW50VmFyIikpCiMgbWVyZ2Ugd2l0aCBtZXRhZGF0YSBzaGVldCBzbyB3ZSBjYW4gcGxvdCB1c2luZyBvdGhlciBmZWF0dXJlcwpwY2FfTF9hbGwgPC0gc3Vic2V0KHBjYV9MX2FsbCwgc2VsZWN0PS10ZW1wX3RyZWF0bWVudCkgI3JlbW92ZSB0aGUgdGVtcF90cmVhdG1lbnQgY29sdW1uLCB3aGljaCB3aWxsIGJlIGEgZHVwbGljYXRlIHBvc3QtbWVyZ2UKcGNhX0xfYWxsIDwtIG1lcmdlKHBjYV9MX2FsbCwgY29kX3NhbXBsZV9pbmZvLCBieS54ID0gIm5hbWUiLCBieS55ID0gInJvdy5uYW1lcyIpCgojIEFzc2lnbiBzcGVjaWZpYyBjb2xvcnMgdG8gZWFjaCB0ZW1wZXJhdHVyZSB0cmVhdG1lbnQgbGV2ZWwKdGVtcF9jb2xvcnMgPC0gYygKICAiMCIgPSAiZGFya2JsdWUiLAogICI1IiA9ICJyb3lhbGJsdWUxIiwKICAiOSIgPSAiZ3JlZW4iLAogICIxNiIgPSAib3JhbmdlcmVkIikgCgojIFBsb3QgUENBcwpwLkwuNTAwIDwtIGdncGxvdChwY2FfTF81MDAsIGFlcyhQQzEsIFBDMiwgY29sb3I9dGVtcF90cmVhdG1lbnQpKSArIAogIGdlb21fcG9pbnQoc2l6ZT00LCBhbHBoYSA9IDUvMTApICsKICBnZ3RpdGxlKCJMaXZlciwgdG9wIDUwMCBtb3N0IHZhcmlhYmxlIGdlbmVzIikgKwogIHhsYWIocGFzdGUwKCJQQzE6ICIscGVyY2VudFZhcl9MXzUwMFsxXSwiJSB2YXJpYW5jZSIpKSArCiAgeWxhYihwYXN0ZTAoIlBDMjogIixwZXJjZW50VmFyX0xfNTAwWzJdLCIlIHZhcmlhbmNlIikpICsgCiAgY29vcmRfZml4ZWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz10ZW1wX2NvbG9ycykrCiAgc3RhdF9lbGxpcHNlKCkKCnAuTC41MDAuU0xkaWZmIDwtIGdncGxvdChwY2FfTF81MDAsIGFlcyhQQzEsIFBDMiwgY29sb3I9dGVtcF90cmVhdG1lbnQsIHNpemU9U0xfZGlmZl9tbSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdndGl0bGUoIkxpdmVyLCB0b3AgNTAwIG1vc3QgdmFyaWFibGUgZ2VuZXMiKSArCiAgeGxhYihwYXN0ZTAoIlBDMTogIiwgcGVyY2VudFZhcl9MXzUwMFsxXSwgIiUgdmFyaWFuY2UiKSkgKwogIHlsYWIocGFzdGUwKCJQQzI6ICIsIHBlcmNlbnRWYXJfTF81MDBbMl0sICIlIHZhcmlhbmNlIikpICsgCiAgY29vcmRfZml4ZWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHRlbXBfY29sb3JzKSArCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKCkgKyAgIyBBZGQgdGhpcyBsaW5lIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgcG9pbnRzCiAgc3RhdF9lbGxpcHNlKCkKCnAuTC41MDAuV1dUZGlmZiA8LSBnZ3Bsb3QocGNhX0xfNTAwLCBhZXMoUEMxLCBQQzIsIGNvbG9yPXRlbXBfdHJlYXRtZW50LCBzaXplPVdXVF9kaWZmX2cpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBnZ3RpdGxlKCJMaXZlciwgdG9wIDUwMCBtb3N0IHZhcmlhYmxlIGdlbmVzIikgKwogIHhsYWIocGFzdGUwKCJQQzE6ICIsIHBlcmNlbnRWYXJfTF81MDBbMV0sICIlIHZhcmlhbmNlIikpICsKICB5bGFiKHBhc3RlMCgiUEMyOiAiLCBwZXJjZW50VmFyX0xfNTAwWzJdLCAiJSB2YXJpYW5jZSIpKSArIAogIGNvb3JkX2ZpeGVkKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB0ZW1wX2NvbG9ycykgKwogIHNjYWxlX3NpemVfY29udGludW91cygpICsgICMgQWRkIHRoaXMgbGluZSB0byBjb250cm9sIHRoZSBzaXplIG9mIHBvaW50cwogIHN0YXRfZWxsaXBzZSgpCgpwLkwuMTAwMCA8LSBnZ3Bsb3QocGNhX0xfMTAwMCwgYWVzKFBDMSwgUEMyLCBjb2xvcj10ZW1wX3RyZWF0bWVudCkpICsgCiAgZ2VvbV9wb2ludChzaXplPTQsIGFscGhhID0gNS8xMCkgKwogIGdndGl0bGUoIkxpdmVyLCB0b3AgMTAwMCBtb3N0IHZhcmlhYmxlIGdlbmVzIikgKwogIHhsYWIocGFzdGUwKCJQQzE6ICIscGVyY2VudFZhcl9MXzEwMDBbMV0sIiUgdmFyaWFuY2UiKSkgKwogIHlsYWIocGFzdGUwKCJQQzI6ICIscGVyY2VudFZhcl9MXzEwMDBbMl0sIiUgdmFyaWFuY2UiKSkgKyAKICBjb29yZF9maXhlZCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPXRlbXBfY29sb3JzKSsKICBzdGF0X2VsbGlwc2UoKQoKcC5MLjEwMDAuU0xkaWZmIDwtIGdncGxvdChwY2FfTF8xMDAwLCBhZXMoUEMxLCBQQzIsIGNvbG9yPXRlbXBfdHJlYXRtZW50LCBzaXplPVNMX2RpZmZfbW0pKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBnZ3RpdGxlKCJMaXZlciwgdG9wIDEwMDAgbW9zdCB2YXJpYWJsZSBnZW5lcyIpICsKICB4bGFiKHBhc3RlMCgiUEMxOiAiLCBwZXJjZW50VmFyX0xfNTAwWzFdLCAiJSB2YXJpYW5jZSIpKSArCiAgeWxhYihwYXN0ZTAoIlBDMjogIiwgcGVyY2VudFZhcl9MXzUwMFsyXSwgIiUgdmFyaWFuY2UiKSkgKyAKICBjb29yZF9maXhlZCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gdGVtcF9jb2xvcnMpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMoKSArICAjIEFkZCB0aGlzIGxpbmUgdG8gY29udHJvbCB0aGUgc2l6ZSBvZiBwb2ludHMKICBzdGF0X2VsbGlwc2UoKQoKcC5MLjEwMDAuV1dUZGlmZiA8LSBnZ3Bsb3QocGNhX0xfMTAwMCwgYWVzKFBDMSwgUEMyLCBjb2xvcj10ZW1wX3RyZWF0bWVudCwgc2l6ZT1XV1RfZGlmZl9nKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgZ2d0aXRsZSgiTGl2ZXIsIHRvcCAxMDAwIG1vc3QgdmFyaWFibGUgZ2VuZXMiKSArCiAgeGxhYihwYXN0ZTAoIlBDMTogIiwgcGVyY2VudFZhcl9MXzUwMFsxXSwgIiUgdmFyaWFuY2UiKSkgKwogIHlsYWIocGFzdGUwKCJQQzI6ICIsIHBlcmNlbnRWYXJfTF81MDBbMl0sICIlIHZhcmlhbmNlIikpICsgCiAgY29vcmRfZml4ZWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHRlbXBfY29sb3JzKSArCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKCkgKyAgIyBBZGQgdGhpcyBsaW5lIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgcG9pbnRzCiAgc3RhdF9lbGxpcHNlKCkKCnAuTC5hbGwgPC0gZ2dwbG90KHBjYV9MX2FsbCwgYWVzKFBDMSwgUEMyLCBjb2xvcj10ZW1wX3RyZWF0bWVudCkpICsgCiAgZ2VvbV9wb2ludChzaXplPTQsIGFscGhhID0gNS8xMCkgKwogIGdndGl0bGUoIkxpdmVyLCBhbGwgZ2VuZXMiKSArCiAgeGxhYihwYXN0ZTAoIlBDMTogIixwZXJjZW50VmFyX0xfYWxsWzFdLCIlIHZhcmlhbmNlIikpICsKICB5bGFiKHBhc3RlMCgiUEMyOiAiLHBlcmNlbnRWYXJfTF9hbGxbMl0sIiUgdmFyaWFuY2UiKSkgKyAKICBjb29yZF9maXhlZCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPXRlbXBfY29sb3JzKSsKICBzdGF0X2VsbGlwc2UoKQoKcC5MLmFsbC5TTGRpZmYgPC0gZ2dwbG90KHBjYV9MX2FsbCwgYWVzKFBDMSwgUEMyLCBjb2xvcj10ZW1wX3RyZWF0bWVudCwgc2l6ZT1TTF9kaWZmX21tKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgZ2d0aXRsZSgiTGl2ZXIsIGFsbCBnZW5lcyIpICsKICB4bGFiKHBhc3RlMCgiUEMxOiAiLCBwZXJjZW50VmFyX0xfNTAwWzFdLCAiJSB2YXJpYW5jZSIpKSArCiAgeWxhYihwYXN0ZTAoIlBDMjogIiwgcGVyY2VudFZhcl9MXzUwMFsyXSwgIiUgdmFyaWFuY2UiKSkgKyAKICBjb29yZF9maXhlZCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gdGVtcF9jb2xvcnMpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMoKSArICAjIEFkZCB0aGlzIGxpbmUgdG8gY29udHJvbCB0aGUgc2l6ZSBvZiBwb2ludHMKICBzdGF0X2VsbGlwc2UoKQoKcC5MLmFsbC5XV1RkaWZmIDwtIGdncGxvdChwY2FfTF9hbGwsIGFlcyhQQzEsIFBDMiwgY29sb3I9dGVtcF90cmVhdG1lbnQsIHNpemU9V1dUX2RpZmZfZykpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdndGl0bGUoIkxpdmVyLCBhbGwgZ2VuZXMiKSArCiAgeGxhYihwYXN0ZTAoIlBDMTogIiwgcGVyY2VudFZhcl9MXzUwMFsxXSwgIiUgdmFyaWFuY2UiKSkgKwogIHlsYWIocGFzdGUwKCJQQzI6ICIsIHBlcmNlbnRWYXJfTF81MDBbMl0sICIlIHZhcmlhbmNlIikpICsgCiAgY29vcmRfZml4ZWQoKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHRlbXBfY29sb3JzKSArCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKCkgKyAgIyBBZGQgdGhpcyBsaW5lIHRvIGNvbnRyb2wgdGhlIHNpemUgb2YgcG9pbnRzCiAgc3RhdF9lbGxpcHNlKCkKCiMgVmlldyBQQ0FzCnAuTC41MDAKcC5MLjUwMC5TTGRpZmYKcC5MLjUwMC5XV1RkaWZmCnAuTC4xMDAwCnAuTC4xMDAwLlNMZGlmZgpwLkwuMTAwMC5XV1RkaWZmCnAuTC5hbGwKcC5MLmFsbC5TTGRpZmYKcC5MLmFsbC5XV1RkaWZmCgojIEV4cG9ydCBQQ0FzIGFzIHBuZ3MKZ2dleHBvcnQoZmlsZW5hbWUgPSAiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9leG9uLVBDQV9MXzUwMC5wbmciLCBwbG90ID0gcC5MLjUwMCwgcmVzID0gNjAwLCB3aWR0aCA9IDYwMDAsIGhlaWdodCA9IDQwMDApCgpnZ2V4cG9ydChmaWxlbmFtZSA9ICIuLi9vdXRwdXQvMDcuMi4xLWNvZC1STkFzZXEtREVTZXEyLWdlbm9tZS1leG9uL2V4b24tUENBX0xfMTAwMC5wbmciLCBwbG90ID0gcC5MLjEwMDAsIHJlcyA9IDYwMCwgd2lkdGggPSA2MDAwLCBoZWlnaHQgPSA0MDAwKQoKZ2dleHBvcnQoZmlsZW5hbWUgPSAiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9leG9uLVBDQV9MX2FsbC5wbmciLCBwbG90ID0gcC5MLmFsbCwgcmVzID0gNjAwLCB3aWR0aCA9IDYwMDAsIGhlaWdodCA9IDQwMDApCmBgYAoKIyBMaXZlciB0aXNzdWUsIDkqQyB2LiAxNipDCgpUaGUgOVwqQyB0ZW1wZXJhdHVyZSB0cmVhdG1lbnQgaXMgZWZmZWN0aXZlbHkgb3VyICJjb250cm9sLCIgYXMgaXQgcmVwcmVzZW50cyB0aGUgYW1iaWVudCB0ZW1wZXJhdHVyZSB0aGF0IHdpbGQganV2ZW5pbGUgUGFjaWZpYyBjb2Qgd291bGQgZXhwZXJpZW5jZS4KCmBgYHtyLCBjYWNoZT1UUlVFfQojIGxpdmVyIHRpc3N1ZSwgdGVtcGVyYXR1cmVzIDkgdnMuIDE2IAoKIyBGaWx0ZXIgZGF0YQppbmZvc3ViX0wuOS4xNiA8LSBjb2Rfc2FtcGxlX2luZm8gJT4lIGZpbHRlcih0aXNzdWVfdHlwZSA9PSAiTGl2ZXIiICYgKHRlbXBfdHJlYXRtZW50ID09ICI5IiB8IHRlbXBfdHJlYXRtZW50ID09ICIxNiIpKQpjb3VudHN1Yl9MLjkuMTYgPC0gc3Vic2V0KGNvZF9jb3VudHNfZGF0YSwgc2VsZWN0PXJvdy5uYW1lcyhpbmZvc3ViX0wuOS4xNikpCgojIENhbGN1bGF0ZSBERVNlcSBvYmplY3QKZGRzX0wuOS4xNiA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGNvdW50c3ViX0wuOS4xNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IGluZm9zdWJfTC45LjE2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSB+IHRlbXBfdHJlYXRtZW50KQoKZGRzX0wuOS4xNiA8LSBERVNlcShkZHNfTC45LjE2KQpyZXN1bHRzTmFtZXMoZGRzX0wuOS4xNikgIyBsaXN0cyB0aGUgY29lZmZpY2llbnRzCmBgYAoKYGBge3J9CnBsb3REaXNwRXN0cyhkZHNfTC45LjE2KQpgYGAKCmBgYHtyLCBjYWNoZT1UUlVFfQojIEZpbHRlcmluZzoga2VlcCBnZW5lcyB0aGF0IGhhdmUgYXQgbGVhc3QgMTAgY291bnRzIGFjcm9zcyAxLzMgb2YgdGhlIHNhbXBsZXMgLSBodHRwczovL3N1cHBvcnQuYmlvY29uZHVjdG9yLm9yZy9wLzExMDMwNy8Ka2VlcCA8LSByb3dTdW1zKERFU2VxMjo6Y291bnRzKGRkc19MLjkuMTYpID49IDEwKSA+PSBuY29sKGNvdW50c3ViX0wuOS4xNikvMwpkZHNfTC45LjE2PC0gZGRzX0wuOS4xNltrZWVwLF0KCiMgR2VuZXJhdGUgQ29udHJhc3RzCmNvbnRyYXN0X2xpc3RfTC45LjE2ICAgICAgICA8LSBjKCJ0ZW1wX3RyZWF0bWVudCIsICIxNiIsICI5IikgIyBvcmRlciBpcyBpbXBvcnRhbnQ6IGZhY3RvciwgdHJlYXRtZW50IGdyb3VwLCBjb250cm9sCnJlc190YWJsZV9MLjkuMTZfbm9zaHJpbmsgPC0gcmVzdWx0cyhkZHNfTC45LjE2LCBjb250cmFzdD1jb250cmFzdF9saXN0X0wuOS4xNiwgYWxwaGEgPSAwLjA1KQoKcmVzX3RhYmxlX0wuOS4xNl9ub3JtICAgICA8LSBsZmNTaHJpbmsoZGRzX0wuOS4xNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPSJub3JtYWwiKSAjIGxmY1RocmVzaG9sZCA9IDAuNTg1KSAgIyBhIGxmYyB0aHJlc2hvbGQgb2YgMSA9IDItZm9sZCBjaGFuZ2UsIDAuNTg1ID0gMS41LWZvbGQgY2hhbmdlCnJlc190YWJsZV9MLjkuMTZfYXBlZ2xtICAgPC0gbGZjU2hyaW5rKGRkc19MLjkuMTYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWY9MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9ImFwZWdsbSIpICMgbGZjVGhyZXNob2xkID0gMC41ODUpICAjIGEgbGZjIHRocmVzaG9sZCBvZiAxID0gMi1mb2xkIGNoYW5nZSwgMC41ODUgPSAxLjUtZm9sZCBjaGFuZ2UKcmVzX3RhYmxlX0wuOS4xNl9hc2hyICAgICA8LSBsZmNTaHJpbmsoZGRzX0wuOS4xNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0iYXNociIpCmBgYAoKYGBge3J9CiMgR2VuZXJhdGUgTUEgcGxvdHMKcGFyKG1mcm93PWMoMiwyKSwgbWFyPWMoNCw0LDIsMSkpCnhsaW0gPC0gYygxLDFlNSk7IHlsaW0gPC0gYygtNCw0KQpERVNlcTI6OnBsb3RNQShyZXNfdGFibGVfTC45LjE2X25vc2hyaW5rLCB4bGltPXhsaW0sIHlsaW09eWxpbSwgbWFpbj0ibm8gc2hyaW5rIikKREVTZXEyOjpwbG90TUEocmVzX3RhYmxlX0wuOS4xNl9ub3JtLCB4bGltPXhsaW0sIHlsaW09eWxpbSwgbWFpbj0ibm9ybWFsIikKREVTZXEyOjpwbG90TUEocmVzX3RhYmxlX0wuOS4xNl9hcGVnbG0sIHhsaW09eGxpbSwgeWxpbT15bGltLCBtYWluPSJhcGVnbG0iKQpERVNlcTI6OnBsb3RNQShyZXNfdGFibGVfTC45LjE2X2FzaHIsIHhsaW09eGxpbSwgeWxpbT15bGltLCBtYWluPSJhc2hyIikKYGBgCgpgYGB7cn0KIyBFeGFtaW5lIHJlc3VsdHMgZm9ybWF0dGluZwpyZXNfdGFibGVfTC45LjE2X25vcm0gJT4lIGRhdGEuZnJhbWUoKSAlPiUgaGVhZCgpCmBgYAoKTm90ZSB0aGF0IHRoZSBtZXRyaWMgd2Ugd2FudCB0byB1c2UgdG8gaWRlbnRpZnkgc2lnbmlmaWNhbnRseSBleHByZXNzZWQgZ2VuZXMgaXMgdGhlIGBwYWRqYCB2YWx1ZXMsICoqTk9UKiogdGhlIGBwdmFsdWVgLiBgcGFkamAgYXJlIHAtdmFsdWVzIGNvcnJlY3RlZCBmb3IgbXVsdGlwbGUgdGVzdGluZyAoZGVmYXVsdCBtZXRob2QgaXMgdGhlIEJlbmphbWluaSBhbmQgSG9jaGJlcmcgbWV0aG9kKS4KCmBgYHtyfQpzdW1tYXJ5KHJlc190YWJsZV9MLjkuMTZfbm9zaHJpbmspCnN1bW1hcnkocmVzX3RhYmxlX0wuOS4xNl9ub3JtKQpzdW1tYXJ5KHJlc190YWJsZV9MLjkuMTZfYXBlZ2xtKQpzdW1tYXJ5KHJlc190YWJsZV9MLjkuMTZfYXNocikKYGBgCgojIEV4dHJhY3Rpbmcgc2lnbmlmaWNhbnRseSBleHByZXNzZWQgZ2VuZXMKCmBgYHtyfQpwYWRqLmN1dG9mZiA8LSAwLjA1CmxmYy5jdXRvZmYgPC0gMC41OAoKIyBDb252ZXJ0IHJlc3VsdHMgdGFibGUgaW50byB0aWJibGUKcmVzX3RhYmxlX0wuOS4xNl9ub3JtX3RiIDwtIHJlc190YWJsZV9MLjkuMTZfbm9ybSAlPiUKICBkYXRhLmZyYW1lKCkgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhcj0iZ2VuZSIpICU+JQogIGFzX3RpYmJsZSgpCgojIHN1YnNldCB0aGF0IHRhYmxlIHRvIG9ubHkga2VlcCB0aGUgc2lnbmlmaWNhbnQgZ2VuZXMgdXNpbmcgb3VyIHByZS1kZWZpbmVkIHRocmVzaG9sZHM6CnNpZ19MLjkuMTZfbm9ybV9ub0xGQ2N1dG9mZiA8LSByZXNfdGFibGVfTC45LjE2X25vcm1fdGIgJT4lCiAgZmlsdGVyKHBhZGogPCBwYWRqLmN1dG9mZikKCnNpZ19MLjkuMTZfbm9ybSA8LSBzaWdfTC45LjE2X25vcm1fbm9MRkNjdXRvZmYgJT4lIAogIGZpbHRlcihhYnMobG9nMkZvbGRDaGFuZ2UpID4gbGZjLmN1dG9mZikKCmhlYWQoc2lnX0wuOS4xNl9ub3JtX25vTEZDY3V0b2ZmKQpwYXN0ZSgiTnVtYmVyIG9mIHNpZ25pZmljYW50IERFR3MgZm9yIDlDIHYgMTZDOiIsIG5yb3coc2lnX0wuOS4xNl9ub3JtX25vTEZDY3V0b2ZmKSwgIihwYWRqPCIsIHBhZGouY3V0b2ZmLCAiKSIpCgpoZWFkKHNpZ19MLjkuMTZfbm9ybSkKcGFzdGUoIk51bWJlciBvZiBzaWduaWZpY2FudCBERUdzIGZvciA5QyB2IDE2QzoiLCBucm93KHNpZ19MLjkuMTZfbm9ybSksICIocGFkajwiLCBwYWRqLmN1dG9mZiwgIiwgbG9nLWZvbGQgY2hhbmdlID4iLCBsZmMuY3V0b2ZmLCAiKSIpCgp3cml0ZS50YWJsZShzaWdfTC45LjE2X25vcm1fbm9MRkNjdXRvZmYsIGZpbGUgPSAiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9HbWFjX0RFR3Nfc2lnX0wuOS4xNl9ub3JtX25vTEZDY3V0b2ZmLnRhYiIsIHNlcCA9ICJcdCIsCiAgICAgICAgICAgIHJvdy5uYW1lcyA9IFRSVUUsIGNvbC5uYW1lcyA9IE5BKQoKd3JpdGUudGFibGUoc2lnX0wuOS4xNl9ub3JtLCBmaWxlID0gIi4uL291dHB1dC8wNy4yLjEtY29kLVJOQXNlcS1ERVNlcTItZ2Vub21lLWV4b24vR21hY19ERUdzX3NpZ19MLjkuMTZfbm9ybS50YWIiLCBzZXAgPSAiXHQiLAogICAgICAgICAgICByb3cubmFtZXMgPSBUUlVFLCBjb2wubmFtZXMgPSBOQSkKYGBgCgojIyBIZWF0bWFwCgpgYGB7cn0KIyBSZXRyaWV2ZSBub3JtYWxpemVkIGNvdW50cyBtYXRyaXgKZGRzX0wuOS4xNl9ub3JtX2NvdW50cyA8LSBjb3VudHMoZGRzX0wuOS4xNiwgbm9ybWFsaXplZD1UUlVFKQoKIyBFeHRyYWN0IG5vcm1hbGl6ZWQgZXhwcmVzc2lvbiBmb3Igc2lnbmlmaWNhbnQgZ2VuZXMKbm9ybV9zaWdfTC45LjE2IDwtIGRkc19MLjkuMTZfbm9ybV9jb3VudHMgJT4lIAogIGRhdGEuZnJhbWUoKSAlPiUKICBmaWx0ZXIocm93Lm5hbWVzKGRkc19MLjkuMTZfbm9ybV9jb3VudHMpICVpbiUgc2lnX0wuOS4xNl9ub3JtJGdlbmUpCgpoZWFkKG5vcm1fc2lnX0wuOS4xNikKCiMgQW5ub3RhdGUgaGVhdG1hcAphbm5vdGF0aW9uIDwtIGluZm9zdWJfTC45LjE2ICU+JSAKCWRwbHlyOjpzZWxlY3QodGVtcF90cmVhdG1lbnQpCgojIFNldCBhIGNvbG9yIHBhbGV0dGUKaGVhdF9jb2xvcnMgPC0gcmV2KGJyZXdlci5wYWwoMTIsICJSZFlsQnUiKSkKCiMgUnVuIHBoZWF0bWFwCmguTC45LjE2IDwtIHBoZWF0bWFwKG5vcm1fc2lnX0wuOS4xNiwgCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gaGVhdF9jb2xvcnMsIAogICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBULCAKICAgICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IEYsCiAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb24gPSBhbm5vdGF0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgYm9yZGVyX2NvbG9yID0gTkEsIAogICAgICAgICAgICAgICAgICAgICBmb250c2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICBzY2FsZSA9ICJyb3ciLCAKICAgICAgICAgICAgICAgICAgICAgZm9udHNpemVfcm93ID0gMTAsIAogICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSAzMCwKICAgICAgICAgICAgICAgICAgICAgbWFpbiA9ICJOb3JtYWxpemVkIFNpZ25pZmljYW50IEV4cHJlc3Npb24sIExpdmVyLCA5KkMgYW5kIDE2KkMiKQoKIyBTYXZlIHBsb3QKZ2dleHBvcnQoZmlsZW5hbWUgPSAiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9leG9uLWhlYXRtYXBfTC45LjE2X25vcm1fc2lnLnBuZyIsCiAgICAgICAgIHBsb3QgICA9IGguTC45LjE2LAogICAgICAgICByZXMgICAgPSA2MDAsCiAgICAgICAgIHdpZHRoICA9IDUwMDAsCiAgICAgICAgIGhlaWdodCA9IDUwMDApCmBgYAoKTm90ZSB0aGUgYXJndW1lbnQgYHNjYWxlPSJyb3ciYCB3YXMgaW5jbHVkZWQsIHNvIHRoZSB2YWx1ZXMgcGxvdHRlZCBpbiB0aGUgaGVhdCBtYXAgYXJlICpaLXNjb3JlcyosIHJhdGhlciB0aG4gdGhlIG5vcm1hbGl6ZWQgY291bnQgdmFsdWUuIFRoaXMgdmFzdGx5IGltcHJvdmVzIHRoZSBjb2xvciB2aXN1YWxpemF0aW9uLgoKRm9yIERFR3MgYmFzZWQgb24gYWRqdXN0ZWQgcC12YWx1ZSAqb25seSoKYGBge3J9CiMgRXh0cmFjdCBub3JtYWxpemVkIGV4cHJlc3Npb24gZm9yIHNpZ25pZmljYW50IGdlbmVzCm5vcm1fc2lnX0wuOS4xNl9ub0xGQ2N1dG9mZiA8LSBkZHNfTC45LjE2X25vcm1fY291bnRzICU+JSAKICBkYXRhLmZyYW1lKCkgJT4lCiAgZmlsdGVyKHJvdy5uYW1lcyhkZHNfTC45LjE2X25vcm1fY291bnRzKSAlaW4lIHNpZ19MLjkuMTZfbm9ybV9ub0xGQ2N1dG9mZiRnZW5lKQoKaGVhZChub3JtX3NpZ19MLjkuMTZfbm9MRkNjdXRvZmYpCgojIEFubm90YXRlIGhlYXRtYXAKYW5ub3RhdGlvbiA8LSBpbmZvc3ViX0wuOS4xNiAlPiUgCglkcGx5cjo6c2VsZWN0KHRlbXBfdHJlYXRtZW50KQoKIyBTZXQgYSBjb2xvciBwYWxldHRlCmhlYXRfY29sb3JzIDwtIHJldihicmV3ZXIucGFsKDEyLCAiUmRZbEJ1IikpCgojIFJ1biBwaGVhdG1hcApoLkwuOS4xNiA8LSBwaGVhdG1hcChub3JtX3NpZ19MLjkuMTZfbm9MRkNjdXRvZmYsIAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGhlYXRfY29sb3JzLCAKICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVCwgCiAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93bmFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uID0gYW5ub3RhdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgIGJvcmRlcl9jb2xvciA9IE5BLCAKICAgICAgICAgICAgICAgICAgICAgZm9udHNpemUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwgCiAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplX3JvdyA9IDEwLCAKICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gMzAsCiAgICAgICAgICAgICAgICAgICAgIG1haW4gPSAiTm9ybWFsaXplZCBTaWduaWZpY2FudCBFeHByZXNzaW9uIChubyBMRkMgY3V0b2ZmKSwgTGl2ZXIsIDkqQyBhbmQgMTYqQyIpCgojIFNhdmUgcGxvdApnZ2V4cG9ydChmaWxlbmFtZSA9ICIuLi9vdXRwdXQvMDcuMi4xLWNvZC1STkFzZXEtREVTZXEyLWdlbm9tZS1leG9uL2V4b24taGVhdG1hcF9MLjkuMTZfbm9ybV9zaWcucG5nIiwKICAgICAgICAgcGxvdCAgID0gaC5MLjkuMTYsCiAgICAgICAgIHJlcyAgICA9IDYwMCwKICAgICAgICAgd2lkdGggID0gNTAwMCwKICAgICAgICAgaGVpZ2h0ID0gNTAwMCkKYGBgCgojIyBWb2xjYW5vIHBsb3QKCmBgYHtyfQojIEdlbmVyYXRlIHBsb3QKdi5MLjkuMTYgPC0gCiAgZ2dwbG90KHJlc190YWJsZV9MLjkuMTZfbm9ybV90YikgKwogICMgUGxvdCBhbGwKICBnZW9tX3BvaW50KGFlcyh4PWxvZzJGb2xkQ2hhbmdlLCB5PS1sb2cxMChwYWRqKSxjb2xvcj0idW5jaGFuZ2VkIiksCiAgICAgICAgICAgICBzaXplPS41KSArCiAgIyBPdmVybGF5IGFsbCBzaWduaWZpY2FudGx5IHVwcmVndWxhdGVkIGluIHJlZAogIGdlb21fcG9pbnQoZGF0YSA9IHNpZ19MLjkuMTZfbm9ybVtzaWdfTC45LjE2X25vcm0kbG9nMkZvbGRDaGFuZ2UgPiAwLCBdLCAKICAgICAgICAgICAgIGFlcyh4PWxvZzJGb2xkQ2hhbmdlLCB5PS1sb2cxMChwYWRqKSwgY29sb3I9InVwcmVndWxhdGVkIiksIAogICAgICAgICAgICAgc2l6ZT0uNSkgKwogICMgT3ZlcmxheSBhbGwgc2lnbmlmaWNhbnRseSBkb3ducmVndWxhdGVkIGluIGJsdWUKICBnZW9tX3BvaW50KGRhdGEgPSBzaWdfTC45LjE2X25vcm1bc2lnX0wuOS4xNl9ub3JtJGxvZzJGb2xkQ2hhbmdlIDwgMCwgXSwgCiAgICAgICAgICAgICBhZXMoeD1sb2cyRm9sZENoYW5nZSwgeT0tbG9nMTAocGFkaiksIGNvbG9yPSJkb3ducmVndWxhdGVkIiksIAogICAgICAgICAgICAgc2l6ZT0uNSkgKwogIGdndGl0bGUoIkxpdmVyLCA5KkMgYW5kIDE2KkMiKSArCiAgeGxhYigibG9nMiBmb2xkIGNoYW5nZSIpICsgCiAgeWxhYigiLWxvZzEwIGFkanVzdGVkIHAtdmFsdWUiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTQsNCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDMwKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJ1bmNoYW5nZWQiID0gImRhcmtncmV5IiwgInVwcmVndWxhdGVkIiA9ICJyZWQiLCAiZG93bnJlZ3VsYXRlZCIgPSAiYmx1ZSIpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJ1bmNoYW5nZWQiID0gIlVuY2hhbmdlZCIsICJ1cHJlZ3VsYXRlZCIgPSAiVXByZWd1bGF0ZWQiLCAiZG93bnJlZ3VsYXRlZCIgPSAiRG93bnJlZ3VsYXRlZCIpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gTlVMTCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxLjUpLCBoanVzdCA9IDAuNSksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuMjUpKSkKCnYuTC45LjE2CgojIFNhdmUgcGxvdApnZ2V4cG9ydChmaWxlbmFtZSA9ICIuLi9vdXRwdXQvMDcuMi4xLWNvZC1STkFzZXEtREVTZXEyLWdlbm9tZS1leG9uL2V4b24tdm9sY2Fub19MLjkuMTYucG5nIiwKICAgICAgICAgcGxvdCAgID0gdi5MLjkuMTYsCiAgICAgICAgIHJlcyAgICA9IDYwMCwKICAgICAgICAgd2lkdGggID0gNjAwMCwKICAgICAgICAgaGVpZ2h0ID0gNDAwMCkKYGBgCgojIyBQbG90IGV4cHJlc3Npb24gb2YgdG9wIERFR3MgYWNyb3NzIHRyZWF0bWVudHMKCmBgYHtyfQp0b3AxNURFR3NfTC45LjE2IDwtIHNpZ19MLjkuMTZfbm9ybV9ub0xGQ2N1dG9mZiAlPiUKICBhcnJhbmdlKHBhZGopICU+JQogIHNsaWNlX2hlYWQobj0xNSkKCnBsb3RfZ2VuZV9kYXRhIDwtIGZ1bmN0aW9uKGdlbmVOYW1lKSB7CiAgZ2VuZV9kYXRhIDwtIGNvZF9jb3VudHNkYXRhX3BsdXNfc2FtcGxlaW5mbyAlPiUKICAgIGZpbHRlcihnZW5lID09IGdlbmVOYW1lKQogIAogIGdncGxvdChkYXRhID0gZ2VuZV9kYXRhLCAKICAgICAgICAgYWVzKHggPSB0ZW1wX3RyZWF0bWVudCwgeSA9IGNvdW50LCBjb2xvciA9IGZhY3Rvcih0ZW1wX3RyZWF0bWVudCkpKSArCiAgICBnZW9tX2JveHBsb3QoKSArCiAgICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4xKSwgc2l6ZSA9IDIpICsKICAgIGxhYnModGl0bGUgPSBnZW5lTmFtZSwgeCA9ICJTYW1wbGUiLCB5ID0gIkNvdW50IiwgY29sb3IgPSAiVHJlYXRtZW50IikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB0ZW1wX2NvbG9ycykgKwogICAgdGhlbWVfbWluaW1hbCgpCn0KCgpMLjkuMTZfREVHMSA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzEsIF0kZ2VuZSkKTC45LjE2X0RFRzEKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMS4iLHRvcDE1REVHc19MLjkuMTZbMSwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHMSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHMiA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzIsIF0kZ2VuZSkKTC45LjE2X0RFRzIKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMi4iLHRvcDE1REVHc19MLjkuMTZbMiwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHMiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHMyA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzMsIF0kZ2VuZSkKTC45LjE2X0RFRzMKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMy4iLHRvcDE1REVHc19MLjkuMTZbMywgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHMywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHNCA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzQsIF0kZ2VuZSkKTC45LjE2X0RFRzQKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHNC4iLHRvcDE1REVHc19MLjkuMTZbNCwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHNCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHNSA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzUsIF0kZ2VuZSkKTC45LjE2X0RFRzUKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHNS4iLHRvcDE1REVHc19MLjkuMTZbNSwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHNSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHNiA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzYsIF0kZ2VuZSkKTC45LjE2X0RFRzYKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHNi4iLHRvcDE1REVHc19MLjkuMTZbNiwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHNiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHNyA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzcsIF0kZ2VuZSkKTC45LjE2X0RFRzcKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHNy4iLHRvcDE1REVHc19MLjkuMTZbNywgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHNywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHOCA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzgsIF0kZ2VuZSkKTC45LjE2X0RFRzgKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHOC4iLHRvcDE1REVHc19MLjkuMTZbOCwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHOCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHOSA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjE2WzksIF0kZ2VuZSkKTC45LjE2X0RFRzkKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHOS4iLHRvcDE1REVHc19MLjkuMTZbOSwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMTZfREVHOSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHMTAgPC0gcGxvdF9nZW5lX2RhdGEodG9wMTVERUdzX0wuOS4xNlsxMCwgXSRnZW5lKQpMLjkuMTZfREVHMTAKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMTAuIix0b3AxNURFR3NfTC45LjE2WzEwLCBdJGdlbmUsIi5wbmciKSwgcGxvdCA9IEwuOS4xNl9ERUcxMCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHMTEgPC0gcGxvdF9nZW5lX2RhdGEodG9wMTVERUdzX0wuOS4xNlsxMSwgXSRnZW5lKQpMLjkuMTZfREVHMTEKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMTEuIix0b3AxNURFR3NfTC45LjE2WzExLCBdJGdlbmUsIi5wbmciKSwgcGxvdCA9IEwuOS4xNl9ERUcxMSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHMTIgPC0gcGxvdF9nZW5lX2RhdGEodG9wMTVERUdzX0wuOS4xNlsxMiwgXSRnZW5lKQpMLjkuMTZfREVHMTIKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMTIuIix0b3AxNURFR3NfTC45LjE2WzEyLCBdJGdlbmUsIi5wbmciKSwgcGxvdCA9IEwuOS4xNl9ERUcxMiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHMTMgPC0gcGxvdF9nZW5lX2RhdGEodG9wMTVERUdzX0wuOS4xNlsxMywgXSRnZW5lKQpMLjkuMTZfREVHMTMKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMTMuIix0b3AxNURFR3NfTC45LjE2WzEzLCBdJGdlbmUsIi5wbmciKSwgcGxvdCA9IEwuOS4xNl9ERUcxMywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHMTQgPC0gcGxvdF9nZW5lX2RhdGEodG9wMTVERUdzX0wuOS4xNlsxNCwgXSRnZW5lKQpMLjkuMTZfREVHMTQKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMTQuIix0b3AxNURFR3NfTC45LjE2WzE0LCBdJGdlbmUsIi5wbmciKSwgcGxvdCA9IEwuOS4xNl9ERUcxNCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMTZfREVHMTUgPC0gcGxvdF9nZW5lX2RhdGEodG9wMTVERUdzX0wuOS4xNlsxNSwgXSRnZW5lKQpMLjkuMTZfREVHMTUKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMTZfREVHMTUuIix0b3AxNURFR3NfTC45LjE2WzE1LCBdJGdlbmUsIi5wbmciKSwgcGxvdCA9IEwuOS4xNl9ERUcxNSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpgYGAKCiMgTGl2ZXIgdGlzc3VlLCA5KkMgdi4gMCpDCgpUaGUgOVwqQyB0ZW1wZXJhdHVyZSB0cmVhdG1lbnQgaXMgZWZmZWN0aXZlbHkgb3VyICJjb250cm9sLCIgYXMgaXQgcmVwcmVzZW50cyB0aGUgYW1iaWVudCB0ZW1wZXJhdHVyZSB0aGF0IHdpbGQganV2ZW5pbGUgUGFjaWZpYyBjb2Qgd291bGQgZXhwZXJpZW5jZS4KCmBgYHtyLCBjYWNoZT1UUlVFfQojIGxpdmVyIHRpc3N1ZSwgdGVtcGVyYXR1cmVzIDkgdnMuIDAgCgojIEZpbHRlciBkYXRhCmluZm9zdWJfTC45LjAgPC0gY29kX3NhbXBsZV9pbmZvICU+JSBmaWx0ZXIodGlzc3VlX3R5cGUgPT0gIkxpdmVyIiAmICh0ZW1wX3RyZWF0bWVudCA9PSAiOSIgfCB0ZW1wX3RyZWF0bWVudCA9PSAiMCIpKQpjb3VudHN1Yl9MLjkuMCA8LSBzdWJzZXQoY29kX2NvdW50c19kYXRhLCBzZWxlY3Q9cm93Lm5hbWVzKGluZm9zdWJfTC45LjApKQoKIyBDYWxjdWxhdGUgREVTZXEgb2JqZWN0CmRkc19MLjkuMCA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGNvdW50c3ViX0wuOS4wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gaW5mb3N1Yl9MLjkuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiB0ZW1wX3RyZWF0bWVudCkKCmRkc19MLjkuMCA8LSBERVNlcShkZHNfTC45LjApCnJlc3VsdHNOYW1lcyhkZHNfTC45LjApICMgbGlzdHMgdGhlIGNvZWZmaWNpZW50cwpgYGAKCmBgYHtyfQpwbG90RGlzcEVzdHMoZGRzX0wuOS4wKQpgYGAKCmBgYHtyLCBjYWNoZT1UUlVFfQojIEZpbHRlcmluZzoga2VlcCBnZW5lcyB0aGF0IGhhdmUgYXQgbGVhc3QgMTAgY291bnRzIGFjcm9zcyAxLzMgb2YgdGhlIHNhbXBsZXMgLSBodHRwczovL3N1cHBvcnQuYmlvY29uZHVjdG9yLm9yZy9wLzExMDMwNy8Ka2VlcCA8LSByb3dTdW1zKERFU2VxMjo6Y291bnRzKGRkc19MLjkuMCkgPj0gMTApID49IG5jb2woY291bnRzdWJfTC45LjApLzMKZGRzX0wuOS4wPC0gZGRzX0wuOS4wW2tlZXAsXQoKIyBHZW5lcmF0ZSBDb250cmFzdHMKY29udHJhc3RfbGlzdF9MLjkuMCAgICAgICAgPC0gYygidGVtcF90cmVhdG1lbnQiLCAiMCIsICI5IikgIyBvcmRlciBpcyBpbXBvcnRhbnQ6IGZhY3RvciwgdHJlYXRtZW50IGdyb3VwLCBjb250cm9sCnJlc190YWJsZV9MLjkuMF9ub3NocmluayA8LSByZXN1bHRzKGRkc19MLjkuMCwgY29udHJhc3Q9Y29udHJhc3RfbGlzdF9MLjkuMCwgYWxwaGEgPSAwLjA1KQoKcmVzX3RhYmxlX0wuOS4wX25vcm0gICAgIDwtIGxmY1NocmluayhkZHNfTC45LjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWY9MiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0ibm9ybWFsIikgIyBsZmNUaHJlc2hvbGQgPSAwLjU4NSkgICMgYSBsZmMgdGhyZXNob2xkIG9mIDEgPSAyLWZvbGQgY2hhbmdlLCAwLjU4NSA9IDEuNS1mb2xkIGNoYW5nZQpyZXNfdGFibGVfTC45LjBfYXBlZ2xtICAgPC0gbGZjU2hyaW5rKGRkc19MLjkuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0iYXBlZ2xtIikgIyBsZmNUaHJlc2hvbGQgPSAwLjU4NSkgICMgYSBsZmMgdGhyZXNob2xkIG9mIDEgPSAyLWZvbGQgY2hhbmdlLCAwLjU4NSA9IDEuNS1mb2xkIGNoYW5nZQpyZXNfdGFibGVfTC45LjBfYXNociAgICAgPC0gbGZjU2hyaW5rKGRkc19MLjkuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0iYXNociIpCmBgYAoKYGBge3J9CiMgR2VuZXJhdGUgTUEgcGxvdHMKcGFyKG1mcm93PWMoMiwyKSwgbWFyPWMoNCw0LDIsMSkpCnhsaW0gPC0gYygxLDFlNSk7IHlsaW0gPC0gYygtNCw0KQpERVNlcTI6OnBsb3RNQShyZXNfdGFibGVfTC45LjBfbm9zaHJpbmssIHhsaW09eGxpbSwgeWxpbT15bGltLCBtYWluPSJubyBzaHJpbmsiKQpERVNlcTI6OnBsb3RNQShyZXNfdGFibGVfTC45LjBfbm9ybSwgeGxpbT14bGltLCB5bGltPXlsaW0sIG1haW49Im5vcm1hbCIpCkRFU2VxMjo6cGxvdE1BKHJlc190YWJsZV9MLjkuMF9hcGVnbG0sIHhsaW09eGxpbSwgeWxpbT15bGltLCBtYWluPSJhcGVnbG0iKQpERVNlcTI6OnBsb3RNQShyZXNfdGFibGVfTC45LjBfYXNociwgeGxpbT14bGltLCB5bGltPXlsaW0sIG1haW49ImFzaHIiKQpgYGAKCmBgYHtyfQojIEV4YW1pbmUgcmVzdWx0cyBmb3JtYXR0aW5nCnJlc190YWJsZV9MLjkuMF9ub3JtICU+JSBkYXRhLmZyYW1lKCkgJT4lIGhlYWQoKQpgYGAKCk5vdGUgdGhhdCB0aGUgbWV0cmljIHdlIHdhbnQgdG8gdXNlIHRvIGlkZW50aWZ5IHNpZ25pZmljYW50bHkgZXhwcmVzc2VkIGdlbmVzIGlzIHRoZSBgcGFkamAgdmFsdWVzLCAqKk5PVCoqIHRoZSBgcHZhbHVlYC4gYHBhZGpgIGFyZSBwLXZhbHVlcyBjb3JyZWN0ZWQgZm9yIG11bHRpcGxlIHRlc3RpbmcgKGRlZmF1bHQgbWV0aG9kIGlzIHRoZSBCZW5qYW1pbmkgYW5kIEhvY2hiZXJnIG1ldGhvZCkuCgpgYGB7cn0Kc3VtbWFyeShyZXNfdGFibGVfTC45LjBfbm9zaHJpbmspCnN1bW1hcnkocmVzX3RhYmxlX0wuOS4wX25vcm0pCnN1bW1hcnkocmVzX3RhYmxlX0wuOS4wX2FwZWdsbSkKc3VtbWFyeShyZXNfdGFibGVfTC45LjBfYXNocikKYGBgCgojIyBFeHRyYWN0aW5nIHNpZ25pZmljYW50bHkgZXhwcmVzc2VkIGdlbmVzCgpgYGB7cn0KcGFkai5jdXRvZmYgPC0gMC4wNQpsZmMuY3V0b2ZmIDwtIDAuNTgKCiMgQ29udmVydCByZXN1bHRzIHRhYmxlIGludG8gdGliYmxlCnJlc190YWJsZV9MLjkuMF9ub3JtX3RiIDwtIHJlc190YWJsZV9MLjkuMF9ub3JtICU+JQogIGRhdGEuZnJhbWUoKSAlPiUKICByb3duYW1lc190b19jb2x1bW4odmFyPSJnZW5lIikgJT4lCiAgYXNfdGliYmxlKCkKCiMgc3Vic2V0IHRoYXQgdGFibGUgdG8gb25seSBrZWVwIHRoZSBzaWduaWZpY2FudCBnZW5lcyB1c2luZyBvdXIgcHJlLWRlZmluZWQgdGhyZXNob2xkczoKc2lnX0wuOS4wX25vcm1fbm9MRkNjdXRvZmYgPC0gcmVzX3RhYmxlX0wuOS4wX25vcm1fdGIgJT4lCiAgZmlsdGVyKHBhZGogPCBwYWRqLmN1dG9mZikKCnNpZ19MLjkuMF9ub3JtIDwtIHNpZ19MLjkuMF9ub3JtX25vTEZDY3V0b2ZmICU+JSAKICBmaWx0ZXIoYWJzKGxvZzJGb2xkQ2hhbmdlKSA+IGxmYy5jdXRvZmYpCgpoZWFkKHNpZ19MLjkuMF9ub3JtX25vTEZDY3V0b2ZmKQpwYXN0ZSgiTnVtYmVyIG9mIHNpZ25pZmljYW50IERFR3MgZm9yIDlDIHYgMEM6IiwgbnJvdyhzaWdfTC45LjBfbm9ybV9ub0xGQ2N1dG9mZiksICIocGFkajwiLCBwYWRqLmN1dG9mZiwgIikiKQoKaGVhZChzaWdfTC45LjBfbm9ybSkKcGFzdGUoIk51bWJlciBvZiBzaWduaWZpY2FudCBERUdzIGZvciA5QyB2IDBDOiIsIG5yb3coc2lnX0wuOS4wX25vcm0pLCAiKHBhZGo8IiwgcGFkai5jdXRvZmYsICIsIGxvZy1mb2xkIGNoYW5nZSA+IiwgbGZjLmN1dG9mZiwgIikiKQoKd3JpdGUudGFibGUoc2lnX0wuOS4wX25vcm1fbm9MRkNjdXRvZmYsIGZpbGUgPSAiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9HbWFjX0RFR3Nfc2lnX0wuOS4wX25vcm1fbm9MRkNjdXRvZmYudGFiIiwgc2VwID0gIlx0IiwKICAgICAgICAgICAgcm93Lm5hbWVzID0gVFJVRSwgY29sLm5hbWVzID0gTkEpCgp3cml0ZS50YWJsZShzaWdfTC45LjBfbm9ybSwgZmlsZSA9ICIuLi9vdXRwdXQvMDcuMi4xLWNvZC1STkFzZXEtREVTZXEyLWdlbm9tZS1leG9uL0dtYWNfREVHc19zaWdfTC45LjBfbm9ybS50YWIiLCBzZXAgPSAiXHQiLAogICAgICAgICAgICByb3cubmFtZXMgPSBUUlVFLCBjb2wubmFtZXMgPSBOQSkKYGBgCgojIyBIZWF0bWFwCgpgYGB7cn0KIyBSZXRyaWV2ZSBub3JtYWxpemVkIGNvdW50cyBtYXRyaXgKZGRzX0wuOS4wX25vcm1fY291bnRzIDwtIGNvdW50cyhkZHNfTC45LjAsIG5vcm1hbGl6ZWQ9VFJVRSkKCiMgRXh0cmFjdCBub3JtYWxpemVkIGV4cHJlc3Npb24gZm9yIHNpZ25pZmljYW50IGdlbmVzCm5vcm1fc2lnX0wuOS4wIDwtIGRkc19MLjkuMF9ub3JtX2NvdW50cyAlPiUgCiAgZGF0YS5mcmFtZSgpICU+JQogIGZpbHRlcihyb3cubmFtZXMoZGRzX0wuOS4wX25vcm1fY291bnRzKSAlaW4lIHNpZ19MLjkuMF9ub3JtJGdlbmUpCgpoZWFkKG5vcm1fc2lnX0wuOS4wKQoKIyBBbm5vdGF0ZSBoZWF0bWFwCmFubm90YXRpb24gPC0gaW5mb3N1Yl9MLjkuMCAlPiUgCglkcGx5cjo6c2VsZWN0KHRlbXBfdHJlYXRtZW50KQoKIyBTZXQgYSBjb2xvciBwYWxldHRlCmhlYXRfY29sb3JzIDwtIHJldihicmV3ZXIucGFsKDEyLCAiUmRZbEJ1IikpCgojIFJ1biBwaGVhdG1hcApoLkwuOS4wIDwtIHBoZWF0bWFwKG5vcm1fc2lnX0wuOS4wLCAKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBoZWF0X2NvbG9ycywgCiAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFQsIAogICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd25hbWVzID0gRiwKICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbiA9IGFubm90YXRpb24sIAogICAgICAgICAgICAgICAgICAgICBib3JkZXJfY29sb3IgPSBOQSwgCiAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplID0gMTAsCiAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gInJvdyIsIAogICAgICAgICAgICAgICAgICAgICBmb250c2l6ZV9yb3cgPSAxMCwgCiAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IDMwLAogICAgICAgICAgICAgICAgICAgICBtYWluID0gIk5vcm1hbGl6ZWQgU2lnbmlmaWNhbnQgRXhwcmVzc2lvbiwgTGl2ZXIsIDkqQyBhbmQgMCpDIikKCiMgU2F2ZSBwbG90CmdnZXhwb3J0KGZpbGVuYW1lID0gIi4uL291dHB1dC8wNy4yLjEtY29kLVJOQXNlcS1ERVNlcTItZ2Vub21lLWV4b24vZXhvbi1oZWF0bWFwX0wuOS4wX25vcm1fc2lnLnBuZyIsCiAgICAgICAgIHBsb3QgICA9IGguTC45LjAsCiAgICAgICAgIHJlcyAgICA9IDYwMCwKICAgICAgICAgd2lkdGggID0gNTAwMCwKICAgICAgICAgaGVpZ2h0ID0gNTAwMCkKYGBgCgpOb3RlIHRoZSBhcmd1bWVudCBgc2NhbGU9InJvdyJgIHdhcyBpbmNsdWRlZCwgc28gdGhlIHZhbHVlcyBwbG90dGVkIGluIHRoZSBoZWF0IG1hcCBhcmUgKlotc2NvcmVzKiwgcmF0aGVyIHRobiB0aGUgbm9ybWFsaXplZCBjb3VudCB2YWx1ZS4gVGhpcyB2YXN0bHkgaW1wcm92ZXMgdGhlIGNvbG9yIHZpc3VhbGl6YXRpb24uCgpGb3IgREVHcyBiYXNlZCBvbiBhZGp1c3RlZCBwLXZhbHVlICpvbmx5KgpgYGB7cn0KIyBFeHRyYWN0IG5vcm1hbGl6ZWQgZXhwcmVzc2lvbiBmb3Igc2lnbmlmaWNhbnQgZ2VuZXMKbm9ybV9zaWdfTC45LjBfbm9MRkNjdXRvZmYgPC0gZGRzX0wuOS4wX25vcm1fY291bnRzICU+JSAKICBkYXRhLmZyYW1lKCkgJT4lCiAgZmlsdGVyKHJvdy5uYW1lcyhkZHNfTC45LjBfbm9ybV9jb3VudHMpICVpbiUgc2lnX0wuOS4wX25vcm1fbm9MRkNjdXRvZmYkZ2VuZSkKCmhlYWQobm9ybV9zaWdfTC45LjBfbm9MRkNjdXRvZmYpCgojIEFubm90YXRlIGhlYXRtYXAKYW5ub3RhdGlvbiA8LSBpbmZvc3ViX0wuOS4wICU+JSAKCWRwbHlyOjpzZWxlY3QodGVtcF90cmVhdG1lbnQpCgojIFNldCBhIGNvbG9yIHBhbGV0dGUKaGVhdF9jb2xvcnMgPC0gcmV2KGJyZXdlci5wYWwoMTIsICJSZFlsQnUiKSkKCiMgUnVuIHBoZWF0bWFwCmguTC45LjAgPC0gcGhlYXRtYXAobm9ybV9zaWdfTC45LjBfbm9MRkNjdXRvZmYsIAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGhlYXRfY29sb3JzLCAKICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVCwgCiAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93bmFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uID0gYW5ub3RhdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgIGJvcmRlcl9jb2xvciA9IE5BLCAKICAgICAgICAgICAgICAgICAgICAgZm9udHNpemUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwgCiAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplX3JvdyA9IDEwLCAKICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gMzAsCiAgICAgICAgICAgICAgICAgICAgIG1haW4gPSAiTm9ybWFsaXplZCBTaWduaWZpY2FudCBFeHByZXNzaW9uIChubyBMRkMgY3V0b2ZmKSwgTGl2ZXIsIDkqQyBhbmQgMCpDIikKCiMgU2F2ZSBwbG90CmdnZXhwb3J0KGZpbGVuYW1lID0gIi4uL291dHB1dC8wNy4yLjEtY29kLVJOQXNlcS1ERVNlcTItZ2Vub21lLWV4b24vaGVhdG1hcF9MLjkuMF9ub3JtX3NpZ19ub0xGQ2N1dG9mZi5wbmciLAogICAgICAgICBwbG90ICAgPSBoLkwuOS4wLAogICAgICAgICByZXMgICAgPSA2MDAsCiAgICAgICAgIHdpZHRoICA9IDUwMDAsCiAgICAgICAgIGhlaWdodCA9IDUwMDApCmBgYAoKIyMgVm9sY2FubyBwbG90CgpgYGB7cn0KIyBHZW5lcmF0ZSBwbG90CnYuTC45LjAgPC0gCiAgZ2dwbG90KHJlc190YWJsZV9MLjkuMF9ub3JtX3RiKSArCiAgIyBQbG90IGFsbAogIGdlb21fcG9pbnQoYWVzKHg9bG9nMkZvbGRDaGFuZ2UsIHk9LWxvZzEwKHBhZGopLGNvbG9yPSJ1bmNoYW5nZWQiKSwKICAgICAgICAgICAgIHNpemU9LjUpICsKICAjIE92ZXJsYXkgYWxsIHNpZ25pZmljYW50bHkgdXByZWd1bGF0ZWQgaW4gcmVkCiAgZ2VvbV9wb2ludChkYXRhID0gc2lnX0wuOS4wX25vcm1bc2lnX0wuOS4wX25vcm0kbG9nMkZvbGRDaGFuZ2UgPiAwLCBdLCAKICAgICAgICAgICAgIGFlcyh4PWxvZzJGb2xkQ2hhbmdlLCB5PS1sb2cxMChwYWRqKSwgY29sb3I9InVwcmVndWxhdGVkIiksIAogICAgICAgICAgICAgc2l6ZT0uNSkgKwogICMgT3ZlcmxheSBhbGwgc2lnbmlmaWNhbnRseSBkb3ducmVndWxhdGVkIGluIGJsdWUKICBnZW9tX3BvaW50KGRhdGEgPSBzaWdfTC45LjBfbm9ybVtzaWdfTC45LjBfbm9ybSRsb2cyRm9sZENoYW5nZSA8IDAsIF0sIAogICAgICAgICAgICAgYWVzKHg9bG9nMkZvbGRDaGFuZ2UsIHk9LWxvZzEwKHBhZGopLCBjb2xvcj0iZG93bnJlZ3VsYXRlZCIpLCAKICAgICAgICAgICAgIHNpemU9LjUpICsKICBnZ3RpdGxlKCJMaXZlciwgOSpDIGFuZCAwKkMiKSArCiAgeGxhYigibG9nMiBmb2xkIGNoYW5nZSIpICsgCiAgeWxhYigiLWxvZzEwIGFkanVzdGVkIHAtdmFsdWUiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTQsNCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDMwKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJ1bmNoYW5nZWQiID0gImRhcmtncmV5IiwgInVwcmVndWxhdGVkIiA9ICJyZWQiLCAiZG93bnJlZ3VsYXRlZCIgPSAiYmx1ZSIpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJ1bmNoYW5nZWQiID0gIlVuY2hhbmdlZCIsICJ1cHJlZ3VsYXRlZCIgPSAiVXByZWd1bGF0ZWQiLCAiZG93bnJlZ3VsYXRlZCIgPSAiRG93bnJlZ3VsYXRlZCIpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gTlVMTCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxLjUpLCBoanVzdCA9IDAuNSksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuMjUpKSkKCnYuTC45LjAKCiMgU2F2ZSBwbG90CmdnZXhwb3J0KGZpbGVuYW1lID0gIi4uL291dHB1dC8wNy4yLjEtY29kLVJOQXNlcS1ERVNlcTItZ2Vub21lLWV4b24vZXhvbi12b2xjYW5vX0wuOS4wLnBuZyIsCiAgICAgICAgIHBsb3QgICA9IHYuTC45LjAsCiAgICAgICAgIHJlcyAgICA9IDYwMCwKICAgICAgICAgd2lkdGggID0gNjAwMCwKICAgICAgICAgaGVpZ2h0ID0gNDAwMCkKYGBgCgojIyBQbG90IGV4cHJlc3Npb24gb2YgdG9wIERFR3MgYWNyb3NzIHRyZWF0bWVudHMKCmBgYHtyfQp0b3AxNURFR3NfTC45LjAgPC0gc2lnX0wuOS4wX25vcm1fbm9MRkNjdXRvZmYgJT4lCiAgYXJyYW5nZShwYWRqKSAlPiUKICBzbGljZV9oZWFkKG49MTUpCgpMLjkuMF9ERUcxIDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFsxLCBdJGdlbmUpCkwuOS4wX0RFRzEKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUcxLiIsdG9wMTVERUdzX0wuOS4wWzEsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHMSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUcyIDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFsyLCBdJGdlbmUpCkwuOS4wX0RFRzIKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUcyLiIsdG9wMTVERUdzX0wuOS4wWzIsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHMiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUczIDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFszLCBdJGdlbmUpCkwuOS4wX0RFRzMKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUczLiIsdG9wMTVERUdzX0wuOS4wWzMsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHMywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUc0IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFs0LCBdJGdlbmUpCkwuOS4wX0RFRzQKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUc0LiIsdG9wMTVERUdzX0wuOS4wWzQsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHNCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUc1IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFs1LCBdJGdlbmUpCkwuOS4wX0RFRzUKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUc1LiIsdG9wMTVERUdzX0wuOS4wWzUsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHNSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUc2IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFs2LCBdJGdlbmUpCkwuOS4wX0RFRzYKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUc2LiIsdG9wMTVERUdzX0wuOS4wWzYsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHNiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUc3IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFs3LCBdJGdlbmUpCkwuOS4wX0RFRzcKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUc3LiIsdG9wMTVERUdzX0wuOS4wWzcsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHNywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUc4IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFs4LCBdJGdlbmUpCkwuOS4wX0RFRzgKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUc4LiIsdG9wMTVERUdzX0wuOS4wWzgsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHOCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUc5IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuMFs5LCBdJGdlbmUpCkwuOS4wX0RFRzkKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUc5LiIsdG9wMTVERUdzX0wuOS4wWzksIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjBfREVHOSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUcxMCA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjBbMTAsIF0kZ2VuZSkKTC45LjBfREVHMTAKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUcxMC4iLHRvcDE1REVHc19MLjkuMFsxMCwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMF9ERUcxMCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUcxMSA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjBbMTEsIF0kZ2VuZSkKTC45LjBfREVHMTEKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUcxMS4iLHRvcDE1REVHc19MLjkuMFsxMSwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMF9ERUcxMSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUcxMiA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjBbMTIsIF0kZ2VuZSkKTC45LjBfREVHMTIKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUcxMi4iLHRvcDE1REVHc19MLjkuMFsxMiwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMF9ERUcxMiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUcxMyA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjBbMTMsIF0kZ2VuZSkKTC45LjBfREVHMTMKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUcxMy4iLHRvcDE1REVHc19MLjkuMFsxMywgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMF9ERUcxMywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUcxNCA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjBbMTQsIF0kZ2VuZSkKTC45LjBfREVHMTQKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUcxNC4iLHRvcDE1REVHc19MLjkuMFsxNCwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMF9ERUcxNCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuMF9ERUcxNSA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjBbMTUsIF0kZ2VuZSkKTC45LjBfREVHMTUKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuMF9ERUcxNS4iLHRvcDE1REVHc19MLjkuMFsxNSwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuMF9ERUcxNSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpgYGAKCiMgTGl2ZXIgdGlzc3VlLCA5KkMgdi4gNSpDCgpUaGUgOVwqQyB0ZW1wZXJhdHVyZSB0cmVhdG1lbnQgaXMgZWZmZWN0aXZlbHkgb3VyICJjb250cm9sLCIgYXMgaXQgcmVwcmVzZW50cyB0aGUgYW1iaWVudCB0ZW1wZXJhdHVyZSB0aGF0IHdpbGQganV2ZW5pbGUgUGFjaWZpYyBjb2Qgd291bGQgZXhwZXJpZW5jZS4KCmBgYHtyLCBjYWNoZT1UUlVFfQojIGxpdmVyIHRpc3N1ZSwgdGVtcGVyYXR1cmVzIDkgdnMuIDUgCgojIEZpbHRlciBkYXRhCmluZm9zdWJfTC45LjUgPC0gY29kX3NhbXBsZV9pbmZvICU+JSBmaWx0ZXIodGlzc3VlX3R5cGUgPT0gIkxpdmVyIiAmICh0ZW1wX3RyZWF0bWVudCA9PSAiOSIgfCB0ZW1wX3RyZWF0bWVudCA9PSAiNSIpKQpjb3VudHN1Yl9MLjkuNSA8LSBzdWJzZXQoY29kX2NvdW50c19kYXRhLCBzZWxlY3Q9cm93Lm5hbWVzKGluZm9zdWJfTC45LjUpKQoKIyBDYWxjdWxhdGUgREVTZXEgb2JqZWN0CmRkc19MLjkuNSA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGNvdW50c3ViX0wuOS41LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gaW5mb3N1Yl9MLjkuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduID0gfiB0ZW1wX3RyZWF0bWVudCkKCmRkc19MLjkuNSA8LSBERVNlcShkZHNfTC45LjUpCnJlc3VsdHNOYW1lcyhkZHNfTC45LjUpICMgbGlzdHMgdGhlIGNvZWZmaWNpZW50cwpgYGAKCmBgYHtyfQpwbG90RGlzcEVzdHMoZGRzX0wuOS41KQpgYGAKCmBgYHtyLCBjYWNoZT1UUlVFfQojIEZpbHRlcmluZzoga2VlcCBnZW5lcyB0aGF0IGhhdmUgYXQgbGVhc3QgMTAgY291bnRzIGFjcm9zcyAxLzMgb2YgdGhlIHNhbXBsZXMgLSBodHRwczovL3N1cHBvcnQuYmlvY29uZHVjdG9yLm9yZy9wLzExMDMwNy8Ka2VlcCA8LSByb3dTdW1zKERFU2VxMjo6Y291bnRzKGRkc19MLjkuNSkgPj0gMTApID49IG5jb2woY291bnRzdWJfTC45LjUpLzMKZGRzX0wuOS41PC0gZGRzX0wuOS41W2tlZXAsXQoKIyBHZW5lcmF0ZSBDb250cmFzdHMKY29udHJhc3RfbGlzdF9MLjkuNSAgICAgICAgPC0gYygidGVtcF90cmVhdG1lbnQiLCAiNSIsICI5IikgIyBvcmRlciBpcyBpbXBvcnRhbnQ6IGZhY3RvciwgdHJlYXRtZW50IGdyb3VwLCBjb250cm9sCnJlc190YWJsZV9MLjkuNV9ub3NocmluayA8LSByZXN1bHRzKGRkc19MLjkuNSwgY29udHJhc3Q9Y29udHJhc3RfbGlzdF9MLjkuNSwgYWxwaGEgPSAwLjA1KQoKcmVzX3RhYmxlX0wuOS41X25vcm0gICAgIDwtIGxmY1NocmluayhkZHNfTC45LjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWY9MiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0ibm9ybWFsIikgIyBsZmNUaHJlc2hvbGQgPSAwLjU4NSkgICMgYSBsZmMgdGhyZXNob2xkIG9mIDEgPSAyLWZvbGQgY2hhbmdlLCAwLjU4NSA9IDEuNS1mb2xkIGNoYW5nZQpyZXNfdGFibGVfTC45LjVfYXBlZ2xtICAgPC0gbGZjU2hyaW5rKGRkc19MLjkuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0iYXBlZ2xtIikgIyBsZmNUaHJlc2hvbGQgPSAwLjU4NSkgICMgYSBsZmMgdGhyZXNob2xkIG9mIDEgPSAyLWZvbGQgY2hhbmdlLCAwLjU4NSA9IDEuNS1mb2xkIGNoYW5nZQpyZXNfdGFibGVfTC45LjVfYXNociAgICAgPC0gbGZjU2hyaW5rKGRkc19MLjkuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0yLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT0iYXNociIpCmBgYAoKYGBge3J9CiMgR2VuZXJhdGUgTUEgcGxvdHMKcGFyKG1mcm93PWMoMiwyKSwgbWFyPWMoNCw0LDIsMSkpCnhsaW0gPC0gYygxLDFlNSk7IHlsaW0gPC0gYygtNCw0KQpERVNlcTI6OnBsb3RNQShyZXNfdGFibGVfTC45LjVfbm9zaHJpbmssIHhsaW09eGxpbSwgeWxpbT15bGltLCBtYWluPSJubyBzaHJpbmsiKQpERVNlcTI6OnBsb3RNQShyZXNfdGFibGVfTC45LjVfbm9ybSwgeGxpbT14bGltLCB5bGltPXlsaW0sIG1haW49Im5vcm1hbCIpCkRFU2VxMjo6cGxvdE1BKHJlc190YWJsZV9MLjkuNV9hcGVnbG0sIHhsaW09eGxpbSwgeWxpbT15bGltLCBtYWluPSJhcGVnbG0iKQpERVNlcTI6OnBsb3RNQShyZXNfdGFibGVfTC45LjVfYXNociwgeGxpbT14bGltLCB5bGltPXlsaW0sIG1haW49ImFzaHIiKQpgYGAKCmBgYHtyfQojIEV4YW1pbmUgcmVzdWx0cyBmb3JtYXR0aW5nCnJlc190YWJsZV9MLjkuNV9ub3JtICU+JSBkYXRhLmZyYW1lKCkgJT4lIGhlYWQoKQpgYGAKCk5vdGUgdGhhdCB0aGUgbWV0cmljIHdlIHdhbnQgdG8gdXNlIHRvIGlkZW50aWZ5IHNpZ25pZmljYW50bHkgZXhwcmVzc2VkIGdlbmVzIGlzIHRoZSBgcGFkamAgdmFsdWVzLCAqKk5PVCoqIHRoZSBgcHZhbHVlYC4gYHBhZGpgIGFyZSBwLXZhbHVlcyBjb3JyZWN0ZWQgZm9yIG11bHRpcGxlIHRlc3RpbmcgKGRlZmF1bHQgbWV0aG9kIGlzIHRoZSBCZW5qYW1pbmkgYW5kIEhvY2hiZXJnIG1ldGhvZCkuCgpgYGB7cn0Kc3VtbWFyeShyZXNfdGFibGVfTC45LjVfbm9zaHJpbmspCnN1bW1hcnkocmVzX3RhYmxlX0wuOS41X25vcm0pCnN1bW1hcnkocmVzX3RhYmxlX0wuOS41X2FwZWdsbSkKc3VtbWFyeShyZXNfdGFibGVfTC45LjVfYXNocikKYGBgCgojIyBFeHRyYWN0aW5nIHNpZ25pZmljYW50bHkgZXhwcmVzc2VkIGdlbmVzCgpgYGB7cn0KcGFkai5jdXRvZmYgPC0gMC4wNQpsZmMuY3V0b2ZmIDwtIDAuNTgKCiMgQ29udmVydCByZXN1bHRzIHRhYmxlIGludG8gdGliYmxlCnJlc190YWJsZV9MLjkuNV9ub3JtX3RiIDwtIHJlc190YWJsZV9MLjkuNV9ub3JtICU+JQogIGRhdGEuZnJhbWUoKSAlPiUKICByb3duYW1lc190b19jb2x1bW4odmFyPSJnZW5lIikgJT4lCiAgYXNfdGliYmxlKCkKCiMgc3Vic2V0IHRoYXQgdGFibGUgdG8gb25seSBrZWVwIHRoZSBzaWduaWZpY2FudCBnZW5lcyB1c2luZyBvdXIgcHJlLWRlZmluZWQgdGhyZXNob2xkczoKc2lnX0wuOS41X25vcm1fbm9MRkNjdXRvZmYgPC0gcmVzX3RhYmxlX0wuOS41X25vcm1fdGIgJT4lCiAgZmlsdGVyKHBhZGogPCBwYWRqLmN1dG9mZikKCnNpZ19MLjkuNV9ub3JtIDwtIHNpZ19MLjkuNV9ub3JtX25vTEZDY3V0b2ZmICU+JSAKICBmaWx0ZXIoYWJzKGxvZzJGb2xkQ2hhbmdlKSA+IGxmYy5jdXRvZmYpCgpoZWFkKHNpZ19MLjkuNV9ub3JtKQpwYXN0ZSgiTnVtYmVyIG9mIHNpZ25pZmljYW50IERFR3MgZm9yIDlDIHYgNUM6IiwgbnJvdyhzaWdfTC45LjVfbm9ybV9ub0xGQ2N1dG9mZiksICIocGFkajwiLCBwYWRqLmN1dG9mZiwgIikiKQoKaGVhZChzaWdfTC45LjVfbm9ybSkKcGFzdGUoIk51bWJlciBvZiBzaWduaWZpY2FudCBERUdzIGZvciA5QyB2IDVDOiIsIG5yb3coc2lnX0wuOS41X25vcm0pLCAiKHBhZGo8IiwgcGFkai5jdXRvZmYsICIsIGxvZy1mb2xkIGNoYW5nZSA+IiwgbGZjLmN1dG9mZiwgIikiKQoKd3JpdGUudGFibGUoc2lnX0wuOS41X25vcm1fbm9MRkNjdXRvZmYsIGZpbGUgPSAiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9HbWFjX0RFR3Nfc2lnX0wuOS41X25vcm1fbm9MRkNjdXRvZmYudGFiIiwgc2VwID0gIlx0IiwKICAgICAgICAgICAgcm93Lm5hbWVzID0gVFJVRSwgY29sLm5hbWVzID0gTkEpCgp3cml0ZS50YWJsZShzaWdfTC45LjVfbm9ybSwgZmlsZSA9ICIuLi9vdXRwdXQvMDcuMi4xLWNvZC1STkFzZXEtREVTZXEyLWdlbm9tZS1leG9uL0dtYWNfREVHc19zaWdfTC45LjVfbm9ybS50YWIiLCBzZXAgPSAiXHQiLAogICAgICAgICAgICByb3cubmFtZXMgPSBUUlVFLCBjb2wubmFtZXMgPSBOQSkKYGBgCgojIyBIZWF0bWFwCgpgYGB7cn0KIyBSZXRyaWV2ZSBub3JtYWxpemVkIGNvdW50cyBtYXRyaXgKZGRzX0wuOS41X25vcm1fY291bnRzIDwtIGNvdW50cyhkZHNfTC45LjUsIG5vcm1hbGl6ZWQ9VFJVRSkKCiMgRXh0cmFjdCBub3JtYWxpemVkIGV4cHJlc3Npb24gZm9yIHNpZ25pZmljYW50IGdlbmVzCm5vcm1fc2lnX0wuOS41IDwtIGRkc19MLjkuNV9ub3JtX2NvdW50cyAlPiUgCiAgZGF0YS5mcmFtZSgpICU+JQogIGZpbHRlcihyb3cubmFtZXMoZGRzX0wuOS41X25vcm1fY291bnRzKSAlaW4lIHNpZ19MLjkuNV9ub3JtJGdlbmUpCgpoZWFkKG5vcm1fc2lnX0wuOS41KQoKIyBBbm5vdGF0ZSBoZWF0bWFwCmFubm90YXRpb24gPC0gaW5mb3N1Yl9MLjkuNSAlPiUgCglkcGx5cjo6c2VsZWN0KHRlbXBfdHJlYXRtZW50KQoKIyBTZXQgYSBjb2xvciBwYWxldHRlCmhlYXRfY29sb3JzIDwtIHJldihicmV3ZXIucGFsKDEyLCAiUmRZbEJ1IikpCgojIFJ1biBwaGVhdG1hcApoLkwuOS41IDwtIHBoZWF0bWFwKG5vcm1fc2lnX0wuOS41LCAKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBoZWF0X2NvbG9ycywgCiAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFQsIAogICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd25hbWVzID0gRiwKICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbiA9IGFubm90YXRpb24sIAogICAgICAgICAgICAgICAgICAgICBib3JkZXJfY29sb3IgPSBOQSwgCiAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplID0gMTAsCiAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gInJvdyIsIAogICAgICAgICAgICAgICAgICAgICBmb250c2l6ZV9yb3cgPSAxMCwgCiAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IDMwLAogICAgICAgICAgICAgICAgICAgICBtYWluID0gIk5vcm1hbGl6ZWQgU2lnbmlmaWNhbnQgRXhwcmVzc2lvbiwgTGl2ZXIsIDkqQyBhbmQgNSpDIikKCiMgU2F2ZSBwbG90CmdnZXhwb3J0KGZpbGVuYW1lID0gIi4uL291dHB1dC8wNy4yLjEtY29kLVJOQXNlcS1ERVNlcTItZ2Vub21lLWV4b24vZXhvbi1oZWF0bWFwX0wuOS41X25vcm1fc2lnLnBuZyIsCiAgICAgICAgIHBsb3QgICA9IGguTC45LjUsCiAgICAgICAgIHJlcyAgICA9IDYwMCwKICAgICAgICAgd2lkdGggID0gNTAwMCwKICAgICAgICAgaGVpZ2h0ID0gNTAwMCkKYGBgCgpOb3RlIHRoZSBhcmd1bWVudCBgc2NhbGU9InJvdyJgIHdhcyBpbmNsdWRlZCwgc28gdGhlIHZhbHVlcyBwbG90dGVkIGluIHRoZSBoZWF0IG1hcCBhcmUgKlotc2NvcmVzKiwgcmF0aGVyIHRobiB0aGUgbm9ybWFsaXplZCBjb3VudCB2YWx1ZS4gVGhpcyB2YXN0bHkgaW1wcm92ZXMgdGhlIGNvbG9yIHZpc3VhbGl6YXRpb24uCgpGb3IgREVHcyBiYXNlZCBvbiBhZGp1c3RlZCBwLXZhbHVlICpvbmx5KgpgYGB7cn0KIyBFeHRyYWN0IG5vcm1hbGl6ZWQgZXhwcmVzc2lvbiBmb3Igc2lnbmlmaWNhbnQgZ2VuZXMKbm9ybV9zaWdfTC45LjVfbm9MRkNjdXRvZmYgPC0gZGRzX0wuOS41X25vcm1fY291bnRzICU+JSAKICBkYXRhLmZyYW1lKCkgJT4lCiAgZmlsdGVyKHJvdy5uYW1lcyhkZHNfTC45LjVfbm9ybV9jb3VudHMpICVpbiUgc2lnX0wuOS41X25vcm1fbm9MRkNjdXRvZmYkZ2VuZSkKCmhlYWQobm9ybV9zaWdfTC45LjVfbm9MRkNjdXRvZmYpCgojIEFubm90YXRlIGhlYXRtYXAKYW5ub3RhdGlvbiA8LSBpbmZvc3ViX0wuOS41ICU+JSAKCWRwbHlyOjpzZWxlY3QodGVtcF90cmVhdG1lbnQpCgojIFNldCBhIGNvbG9yIHBhbGV0dGUKaGVhdF9jb2xvcnMgPC0gcmV2KGJyZXdlci5wYWwoMTIsICJSZFlsQnUiKSkKCiMgUnVuIHBoZWF0bWFwCmguTC45LjUgPC0gcGhlYXRtYXAobm9ybV9zaWdfTC45LjVfbm9MRkNjdXRvZmYsIAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGhlYXRfY29sb3JzLCAKICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVCwgCiAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93bmFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uID0gYW5ub3RhdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgIGJvcmRlcl9jb2xvciA9IE5BLCAKICAgICAgICAgICAgICAgICAgICAgZm9udHNpemUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwgCiAgICAgICAgICAgICAgICAgICAgIGZvbnRzaXplX3JvdyA9IDEwLCAKICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gMzAsCiAgICAgICAgICAgICAgICAgICAgIG1haW4gPSAiTm9ybWFsaXplZCBTaWduaWZpY2FudCBFeHByZXNzaW9uIChubyBMRkMgY3V0b2ZmKSwgTGl2ZXIsIDkqQyBhbmQgNSpDIikKCiMgU2F2ZSBwbG90CmdnZXhwb3J0KGZpbGVuYW1lID0gIi4uL291dHB1dC8wNy4yLjEtY29kLVJOQXNlcS1ERVNlcTItZ2Vub21lLWV4b24vaGVhdG1hcF9MLjkuNV9ub3JtX3NpZ19ub0xGQ2N1dG9mZi5wbmciLAogICAgICAgICBwbG90ICAgPSBoLkwuOS41LAogICAgICAgICByZXMgICAgPSA2MDAsCiAgICAgICAgIHdpZHRoICA9IDUwMDAsCiAgICAgICAgIGhlaWdodCA9IDUwMDApCmBgYAoKIyMgVm9sY2FubyBwbG90CgpgYGB7cn0KIyBHZW5lcmF0ZSBwbG90CnYuTC45LjUgPC0gCiAgZ2dwbG90KHJlc190YWJsZV9MLjkuNV9ub3JtX3RiKSArCiAgIyBQbG90IGFsbAogIGdlb21fcG9pbnQoYWVzKHg9bG9nMkZvbGRDaGFuZ2UsIHk9LWxvZzEwKHBhZGopLGNvbG9yPSJ1bmNoYW5nZWQiKSwKICAgICAgICAgICAgIHNpemU9LjUpICsKICAjIE92ZXJsYXkgYWxsIHNpZ25pZmljYW50bHkgdXByZWd1bGF0ZWQgaW4gcmVkCiAgZ2VvbV9wb2ludChkYXRhID0gc2lnX0wuOS41X25vcm1bc2lnX0wuOS41X25vcm0kbG9nMkZvbGRDaGFuZ2UgPiAwLCBdLCAKICAgICAgICAgICAgIGFlcyh4PWxvZzJGb2xkQ2hhbmdlLCB5PS1sb2cxMChwYWRqKSwgY29sb3I9InVwcmVndWxhdGVkIiksIAogICAgICAgICAgICAgc2l6ZT0uNSkgKwogICMgT3ZlcmxheSBhbGwgc2lnbmlmaWNhbnRseSBkb3ducmVndWxhdGVkIGluIGJsdWUKICBnZW9tX3BvaW50KGRhdGEgPSBzaWdfTC45LjVfbm9ybVtzaWdfTC45LjVfbm9ybSRsb2cyRm9sZENoYW5nZSA8IDAsIF0sIAogICAgICAgICAgICAgYWVzKHg9bG9nMkZvbGRDaGFuZ2UsIHk9LWxvZzEwKHBhZGopLCBjb2xvcj0iZG93bnJlZ3VsYXRlZCIpLCAKICAgICAgICAgICAgIHNpemU9LjUpICsKICBnZ3RpdGxlKCJMaXZlciwgOSpDIGFuZCAwKkMiKSArCiAgeGxhYigibG9nMiBmb2xkIGNoYW5nZSIpICsgCiAgeWxhYigiLWxvZzEwIGFkanVzdGVkIHAtdmFsdWUiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTQsNCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDMwKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJ1bmNoYW5nZWQiID0gImRhcmtncmV5IiwgInVwcmVndWxhdGVkIiA9ICJyZWQiLCAiZG93bnJlZ3VsYXRlZCIgPSAiYmx1ZSIpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJ1bmNoYW5nZWQiID0gIlVuY2hhbmdlZCIsICJ1cHJlZ3VsYXRlZCIgPSAiVXByZWd1bGF0ZWQiLCAiZG93bnJlZ3VsYXRlZCIgPSAiRG93bnJlZ3VsYXRlZCIpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gTlVMTCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxLjUpLCBoanVzdCA9IDAuNSksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuMjUpKSkKCnYuTC45LjUKCiMgU2F2ZSBwbG90CmdnZXhwb3J0KGZpbGVuYW1lID0gIi4uL291dHB1dC8wNy4yLjEtY29kLVJOQXNlcS1ERVNlcTItZ2Vub21lLWV4b24vZXhvbi12b2xjYW5vX0wuOS41LnBuZyIsCiAgICAgICAgIHBsb3QgICA9IHYuTC45LjAsCiAgICAgICAgIHJlcyAgICA9IDYwMCwKICAgICAgICAgd2lkdGggID0gNjAwMCwKICAgICAgICAgaGVpZ2h0ID0gNDAwMCkKYGBgCgojIyBQbG90IGV4cHJlc3Npb24gb2YgdG9wIERFR3MgYWNyb3NzIHRyZWF0bWVudHMKCmBgYHtyfQp0b3AxNURFR3NfTC45LjUgPC0gc2lnX0wuOS41X25vcm1fbm9MRkNjdXRvZmYgJT4lCiAgYXJyYW5nZShwYWRqKSAlPiUKICBzbGljZV9oZWFkKG49MTUpCgpMLjkuNV9ERUcxIDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVsxLCBdJGdlbmUpCkwuOS41X0RFRzEKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUcxLiIsdG9wMTVERUdzX0wuOS41WzEsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHMSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUcyIDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVsyLCBdJGdlbmUpCkwuOS41X0RFRzIKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUcyLiIsdG9wMTVERUdzX0wuOS41WzIsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHMiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUczIDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVszLCBdJGdlbmUpCkwuOS41X0RFRzMKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUczLiIsdG9wMTVERUdzX0wuOS41WzMsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHMywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUc0IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVs0LCBdJGdlbmUpCkwuOS41X0RFRzQKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUc0LiIsdG9wMTVERUdzX0wuOS41WzQsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHNCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUc1IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVs1LCBdJGdlbmUpCkwuOS41X0RFRzUKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUc1LiIsdG9wMTVERUdzX0wuOS41WzUsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHNSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUc2IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVs2LCBdJGdlbmUpCkwuOS41X0RFRzYKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUc2LiIsdG9wMTVERUdzX0wuOS41WzYsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHNiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUc3IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVs3LCBdJGdlbmUpCkwuOS41X0RFRzcKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUc3LiIsdG9wMTVERUdzX0wuOS41WzcsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHNywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUc4IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVs4LCBdJGdlbmUpCkwuOS41X0RFRzgKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUc4LiIsdG9wMTVERUdzX0wuOS41WzgsIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHOCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUc5IDwtIHBsb3RfZ2VuZV9kYXRhKHRvcDE1REVHc19MLjkuNVs5LCBdJGdlbmUpCkwuOS41X0RFRzkKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUc5LiIsdG9wMTVERUdzX0wuOS41WzksIF0kZ2VuZSwiLnBuZyIpLCBwbG90ID0gTC45LjVfREVHOSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUcxMCA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjVbMTAsIF0kZ2VuZSkKTC45LjVfREVHMTAKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUcxMC4iLHRvcDE1REVHc19MLjkuNVsxMCwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuNV9ERUcxMCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUcxMSA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjVbMTEsIF0kZ2VuZSkKTC45LjVfREVHMTEKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUcxMS4iLHRvcDE1REVHc19MLjkuNVsxMSwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuNV9ERUcxMSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUcxMiA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjVbMTIsIF0kZ2VuZSkKTC45LjVfREVHMTIKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUcxMi4iLHRvcDE1REVHc19MLjkuNVsxMiwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuNV9ERUcxMiwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUcxMyA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjVbMTMsIF0kZ2VuZSkKTC45LjVfREVHMTMKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUcxMy4iLHRvcDE1REVHc19MLjkuNVsxMywgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuNV9ERUcxMywgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUcxNCA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjVbMTQsIF0kZ2VuZSkKTC45LjVfREVHMTQKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUcxNC4iLHRvcDE1REVHc19MLjkuNVsxNCwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuNV9ERUcxNCwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpMLjkuNV9ERUcxNSA8LSBwbG90X2dlbmVfZGF0YSh0b3AxNURFR3NfTC45LjVbMTUsIF0kZ2VuZSkKTC45LjVfREVHMTUKZ2dleHBvcnQoZmlsZW5hbWUgPSBwYXN0ZSgiLi4vb3V0cHV0LzA3LjIuMS1jb2QtUk5Bc2VxLURFU2VxMi1nZW5vbWUtZXhvbi9MLjkuNV9ERUcxNS4iLHRvcDE1REVHc19MLjkuNVsxNSwgXSRnZW5lLCIucG5nIiksIHBsb3QgPSBMLjkuNV9ERUcxNSwgcmVzID0gNjAwLCB3aWR0aCA9IDUwMDAsIGhlaWdodCA9IDUwMDApCgpgYGAK