Gene expression summary for Porites evermanni RNA-seq data.

  • trimmed reads generated in deep-dive project, trimming and QC details in 01-Peve-RNA-trimming-FastQC

  • Reads aligned to Porites evermanni transcriptome, details here

0.0.1 Install and load packages

library(tidyverse)
library(ggplot2)
library(reshape2)

1 Load data

1.1 Load count data

Load in the count matrix we generated after kallisto pseudoalignment using the Trinity abundance_estimates_to_matrix.pl script. We also need to slightly reformat the count matrix

# Read in counts data. This is a gene-level counts matrix generated from kallisto transcript abundances using Trinity
Peve_counts_data_OG <- read_delim("../../../deep-dive/E-Peve/output/12-Peve-RNAseq-kallisto/kallisto/kallisto.isoform.counts.matrix") 
head(Peve_counts_data_OG)
# A tibble: 6 × 6
  ...1      kallisto_quant_sampl…¹ kallisto_quant_sampl…² kallisto_quant_sampl…³
  <chr>                      <dbl>                  <dbl>                  <dbl>
1 Parent=P…                    0                      0                      0  
2 Parent=P…                   42                      3                    122  
3 Parent=P…                   56.5                   46.5                   15.4
4 Parent=P…                  873                    403                   2305  
5 Parent=P…                   78.9                   86.6                  252. 
6 Parent=P…                   83                     59                     93  
# ℹ abbreviated names: ¹​kallisto_quant_sample71, ²​kallisto_quant_sample73,
#   ³​kallisto_quant_sample76
# ℹ 2 more variables: kallisto_quant_sample79 <dbl>,
#   kallisto_quant_sample82 <dbl>
# Read in ID mapping of transcripts and associated GO terms etc.
Peve_IDmapping <- read_delim("../output/02-Peve-reference-annotation/Porites_evermanni_CDS-IDmapping-2024_09_04.tab") %>%
  select(-...1)
head(Peve_IDmapping)
# A tibble: 6 × 7
  V1               V3          V13 Protein.names Organism Gene.Ontology..biolo…¹
  <chr>            <chr>     <dbl> <chr>         <chr>    <chr>                 
1 Parent=Peve_000… P619… 2.22e- 58 DELTA-actito… Actinia… cation transport [GO:…
2 Parent=Peve_000… Q569… 1.43e- 45 Ubiquitin ca… Rattus … DNA repair [GO:000628…
3 Parent=Peve_000… O356… 1.55e-159 DNA polymera… Mus mus… DNA biosynthetic proc…
4 Parent=Peve_000… Q96P… 1.93e-174 Kelch-like p… Homo sa… <NA>                  
5 Parent=Peve_000… P525… 5.43e-132 Dual specifi… Homo sa… apoptotic process [GO…
6 Parent=Peve_000… Q616… 0         Probable ATP… Mus mus… alternative mRNA spli…
# ℹ abbreviated name: ¹​Gene.Ontology..biological.process.
# ℹ 1 more variable: Gene.Ontology.IDs <chr>

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
Peve_counts_data <- Peve_counts_data_OG %>%
  column_to_rownames(var = "...1")

# Additional formatting
# Round all estimated counts to integers
Peve_counts_data <- round(Peve_counts_data, digits = 0)

# Remove all transcripts with 5 or fewer counts in all samples
Peve_counts_data <- Peve_counts_data[!apply(Peve_counts_data, 1, function(row) all(row < 6)), ]

# Remove the "kallisto_quant_" portion of the column names, to leave just the sample names
colnames(Peve_counts_data) <- sub("kallisto_quant_", "", colnames(Peve_counts_data))

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

Peve_sample_names <- names(Peve_counts_data)

head(Peve_counts_data)
                     sample71 sample73 sample76 sample79 sample82
Parent=Peve_00028719       42        3      122       61      143
Parent=Peve_00034830       57       47       15       24       43
Parent=Peve_00003312      873      403     2305      282      864
Parent=Peve_00036754       79       87      252       71      159
Parent=Peve_00033536       83       59       93       42      175
Parent=Peve_00015150       14       34      272       16       49
Peve_sample_names
[1] "sample71" "sample73" "sample76" "sample79" "sample82"
Peve_counts_GO <- Peve_counts_data %>%
  rownames_to_column(var = "transcript") %>%
  left_join(Peve_IDmapping, by = c("transcript" = "V1"))

head(Peve_counts_GO)
            transcript sample71 sample73 sample76 sample79 sample82     V3
1 Parent=Peve_00028719       42        3      122       61      143 E7FAM5
2 Parent=Peve_00034830       57       47       15       24       43 P21127
3 Parent=Peve_00003312      873      403     2305      282      864 O13166
4 Parent=Peve_00003312      873      403     2305      282      864 O13166
5 Parent=Peve_00036754       79       87      252       71      159 Q14161
6 Parent=Peve_00036754       79       87      252       71      159 Q14161
        V13
1 1.42e-124
2 4.25e-176
3  0.00e+00
4  1.53e-55
5 2.59e-130
6  4.33e-41
                                                                                                                                                                                                                                               Protein.names
1                                                                                             E3 ubiquitin-protein ligase TRIM71 (EC 2.3.2.27) (Protein lin-41 homolog) (RING-type E3 ubiquitin transferase TRIM71) (Tripartite motif-containing protein 71)
2 Cyclin-dependent kinase 11B (EC 2.7.11.22) (Cell division cycle 2-like protein kinase 1) (CLK-1) (Cell division protein kinase 11B) (Galactosyltransferase-associated protein kinase p58/GTA) (PITSLRE serine/threonine-protein kinase CDC2L1) (p58 CLK-1)
3                                                                                                                                                                    Transducin-like enhancer protein 3-A (Groucho-related protein grg2) (Protein groucho-2)
4                                                                                                                                                                    Transducin-like enhancer protein 3-A (Groucho-related protein grg2) (Protein groucho-2)
5                                                         ARF GTPase-activating protein GIT2 (ARF GAP GIT2) (Cool-interacting tyrosine-phosphorylated protein 2) (CAT-2) (CAT2) (G protein-coupled receptor kinase-interactor 2) (GRK-interacting protein 2)
6                                                         ARF GTPase-activating protein GIT2 (ARF GAP GIT2) (Cool-interacting tyrosine-phosphorylated protein 2) (CAT-2) (CAT2) (G protein-coupled receptor kinase-interactor 2) (GRK-interacting protein 2)
                                     Organism
1 Danio rerio (Zebrafish) (Brachydanio rerio)
2                        Homo sapiens (Human)
3 Danio rerio (Zebrafish) (Brachydanio rerio)
4 Danio rerio (Zebrafish) (Brachydanio rerio)
5                        Homo sapiens (Human)
6                        Homo sapiens (Human)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Gene.Ontology..biological.process.
1 embryonic body morphogenesis [GO:0010172]; fibroblast growth factor receptor signaling pathway [GO:0008543]; G1/S transition of mitotic cell cycle [GO:0000082]; miRNA metabolic process [GO:0010586]; miRNA-mediated gene silencing by inhibition of translation [GO:0035278]; negative regulation of translation [GO:0017148]; neural tube development [GO:0021915]; proteasome-mediated ubiquitin-dependent protein catabolic process [GO:0043161]; protein autoubiquitination [GO:0051865]; protein polyubiquitination [GO:0000209]; regulation of miRNA-mediated gene silencing [GO:0060964]; regulation of neural precursor cell proliferation [GO:2000177]; stem cell proliferation [GO:0072089]
2                                                                                                                                                                                                                             apoptotic process [GO:0006915]; mitotic cell cycle [GO:0000278]; protein phosphorylation [GO:0006468]; regulation of apoptotic process [GO:0042981]; regulation of cell cycle [GO:0051726]; regulation of cell growth [GO:0001558]; regulation of centrosome cycle [GO:0046605]; regulation of DNA-templated transcription [GO:0006355]; regulation of mitotic cell cycle [GO:0007346]; regulation of mRNA processing [GO:0050684]; regulation of RNA splicing [GO:0043484]
3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 negative regulation of canonical Wnt signaling pathway [GO:0090090]; regulation of retinoic acid biosynthetic process [GO:1900052]; sclerotome development [GO:0061056]
4                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 negative regulation of canonical Wnt signaling pathway [GO:0090090]; regulation of retinoic acid biosynthetic process [GO:1900052]; sclerotome development [GO:0061056]
5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            brain development [GO:0007420]; regulation of ARF protein signal transduction [GO:0032012]; regulation of G protein-coupled receptor signaling pathway [GO:0008277]; synaptic vesicle recycling [GO:0036465]
6                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            brain development [GO:0007420]; regulation of ARF protein signal transduction [GO:0032012]; regulation of G protein-coupled receptor signaling pathway [GO:0008277]; synaptic vesicle recycling [GO:0036465]
                                                                                                                                                                                                                               Gene.Ontology.IDs
1             GO:0000082; GO:0000209; GO:0000932; GO:0004842; GO:0008270; GO:0008543; GO:0010172; GO:0010586; GO:0017148; GO:0021915; GO:0030371; GO:0035198; GO:0035278; GO:0043161; GO:0051865; GO:0060964; GO:0061630; GO:0072089; GO:2000177
2 GO:0000278; GO:0000307; GO:0001558; GO:0003723; GO:0004672; GO:0004674; GO:0004693; GO:0005524; GO:0005634; GO:0005737; GO:0006355; GO:0006468; GO:0006915; GO:0007346; GO:0042981; GO:0043484; GO:0046605; GO:0050684; GO:0051726; GO:0106310
3                                                                                                                                                                         GO:0003714; GO:0005634; GO:0005667; GO:0061056; GO:0090090; GO:1900052
4                                                                                                                                                                         GO:0003714; GO:0005634; GO:0005667; GO:0061056; GO:0090090; GO:1900052
5                                                                                                             GO:0005096; GO:0005654; GO:0005925; GO:0007420; GO:0008277; GO:0031267; GO:0032012; GO:0036465; GO:0045202; GO:0046872; GO:0098793
6                                                                                                             GO:0005096; GO:0005654; GO:0005925; GO:0007420; GO:0008277; GO:0031267; GO:0032012; GO:0036465; GO:0045202; GO:0046872; GO:0098793

2 Summary stats and visualizations

2.1 Expression levels

Plot histograms of the expression levels in each sample

# Melt the count matrix into long format
Peve_counts_melted <- melt(Peve_counts_data, variable.name = "sample", value.name = "counts")

# Plot the expression level histograms for each sample
ggplot(Peve_counts_melted, aes(x = counts)) +
  geom_histogram(binwidth = 1, fill = "#1E2761", color = "black") +
  scale_x_log10() +  # Optional: Log-transform the x-axis for better visualization
  facet_wrap(~sample, scales = "free_y") +
  labs(title = "Gene Expression Level Histogram for Each Sample",
       x = "Expression Level (Counts)",
       y = "Frequency") +
  theme_minimal()

2.2 Transcript counts

First let’s check the total number of transcripts in each sample – keep in mind this expression data has not been normalized yet, so there may be different totals for each sample

# Calculate the total number of transcripts for each sample
total_transcripts <- colSums(Peve_counts_data)

# Create a data frame for plotting
total_transcripts_df <- data.frame(sample = names(total_transcripts),
                                   totals = total_transcripts)

# Plot the total number of transcripts for each sample
ggplot(total_transcripts_df, aes(x = sample, y = totals)) +
  geom_bar(stat = "identity", fill = "#1E2761", color = "black") +
  labs(title = "Total Number of Transcripts per Sample",
       x = "Sample",
       y = "Total Transcripts") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # Rotate x-axis labels for readability

Now let’s check the number of unique transcripts in each sample – that is, how many genes are expressed in each sample? This should be pretty much the same across samples, even without normalization.

# Calculate the number of unique transcripts (non-zero counts) for each sample
unique_transcripts <- colSums(Peve_counts_data > 0)

# Create a data frame for plotting
unique_transcripts_df <- data.frame(sample = names(unique_transcripts),
                                    uniques = unique_transcripts)

# Plot the total number of unique transcripts for each sample
ggplot(unique_transcripts_df, aes(x = sample, y = uniques)) +
  geom_bar(stat = "identity", fill = "#1E2761", color = "black") +
  labs(title = "Total Number of Unique Expressed Transcripts per Sample",
       x = "Sample",
       y = "Unique Transcripts") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # Rotate x-axis labels for readability

2.3 Most common biological processes

Similar to the plot generated in 02-Peve-reference-annotation, let’s plot the biological processes most represented in these samples’ expression

# Rename the `Gene.Ontology..biological.process.` column to `Biological_Process`
colnames(Peve_counts_GO)[colnames(Peve_counts_GO) == "Gene.Ontology..biological.process."] <- "Biological_Process"

# Separate the `Biological_Process` column into individual biological processes
data_separated <- unlist(strsplit(Peve_counts_GO$Biological_Process, split = ";"))

# Trim whitespace from the biological processes
data_separated <- gsub("^\\s+|\\s+$", "", data_separated)

# Count the occurrences of each biological process
process_counts <- table(data_separated)
process_counts <- data.frame(Biological_Process = names(process_counts), Count = as.integer(process_counts))
process_counts <- process_counts[order(-process_counts$Count), ]

# Select the 20 most predominant biological processes
top_20_processes <- process_counts[1:20, ]

# Create a color palette for the bars
bar_colors <- rainbow(nrow(top_20_processes))

# Create a staggered vertical bar plot with different colors for each bar
barplot(top_20_processes$Count, names.arg = rep("", nrow(top_20_processes)), col = bar_colors,
        ylim = c(0, max(top_20_processes$Count) * 1.25),
        main = "Occurrences of the 20 Most Predominant Biological Processes", xlab = "Biological Process", ylab = "Count")

# Create a separate plot for the legend
png("../output/03-Peve-RNA-summary/GOlegend.png", width = 800, height = 600)
par(mar = c(0, 0, 0, 0))
plot.new()
legend("center", legend = top_20_processes$Biological_Process, fill = bar_colors, cex = 1, title = "Biological Processes")
dev.off()
png 
  2 
knitr::include_graphics("../output/03-Peve-RNA-summary/GOlegend.png")

rm ../output/03-Peve-RNA-summary/GOlegend.png
LS0tCnRpdGxlOiAiMDMtUGV2ZS1STkEtc3VtbWFyeSIKYXV0aG9yOiAiS2F0aGxlZW4gRHVya2luIgpkYXRlOiAiMjAyNC0wOS0wNCIKYWx3YXlzX2FsbG93X2h0bWw6IHRydWUKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGh0bWxfcHJldmlldzogdHJ1ZSAKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBUUlVFLCAgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKR2VuZSBleHByZXNzaW9uIHN1bW1hcnkgZm9yICpQb3JpdGVzIGV2ZXJtYW5uaSogUk5BLXNlcSBkYXRhLgoKLSAgIHRyaW1tZWQgcmVhZHMgZ2VuZXJhdGVkIGluIGBkZWVwLWRpdmVgIHByb2plY3QsIHRyaW1taW5nIGFuZCBRQyBkZXRhaWxzIGluIGAwMS1QZXZlLVJOQS10cmltbWluZy1GYXN0UUNgCgotICAgUmVhZHMgYWxpZ25lZCB0byAqUG9yaXRlcyBldmVybWFubmkqIHRyYW5zY3JpcHRvbWUsIGRldGFpbHMgW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS91cm9sLWU1L2RlZXAtZGl2ZS9ibG9iL21haW4vRS1QZXZlL2NvZGUvMTItUGV2ZS1STkFzZXEta2FsbGlzdG8ubWQpCgojIyMgSW5zdGFsbCBhbmQgbG9hZCBwYWNrYWdlcwoKYGBge3IgbG9hZF9saWJyYXJpZXMsIGlubGN1ZGUgPSBUUlVFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQpgYGAKCiMgTG9hZCBkYXRhCgojIyBMb2FkIGNvdW50IGRhdGEKCkxvYWQgaW4gdGhlIGNvdW50IG1hdHJpeCB3ZSBnZW5lcmF0ZWQgYWZ0ZXIga2FsbGlzdG8gcHNldWRvYWxpZ25tZW50IHVzaW5nIHRoZSBUcmluaXR5IGFidW5kYW5jZV9lc3RpbWF0ZXNfdG9fbWF0cml4LnBsIHNjcmlwdC4gV2UgYWxzbyBuZWVkIHRvIHNsaWdodGx5IHJlZm9ybWF0IHRoZSBjb3VudCBtYXRyaXgKCmBgYHtyIGxvYWQtY291bnQtZGF0YX0KIyBSZWFkIGluIGNvdW50cyBkYXRhLiBUaGlzIGlzIGEgZ2VuZS1sZXZlbCBjb3VudHMgbWF0cml4IGdlbmVyYXRlZCBmcm9tIGthbGxpc3RvIHRyYW5zY3JpcHQgYWJ1bmRhbmNlcyB1c2luZyBUcmluaXR5ClBldmVfY291bnRzX2RhdGFfT0cgPC0gcmVhZF9kZWxpbSgiLi4vLi4vLi4vZGVlcC1kaXZlL0UtUGV2ZS9vdXRwdXQvMTItUGV2ZS1STkFzZXEta2FsbGlzdG8va2FsbGlzdG8va2FsbGlzdG8uaXNvZm9ybS5jb3VudHMubWF0cml4IikgCmhlYWQoUGV2ZV9jb3VudHNfZGF0YV9PRykKCiMgUmVhZCBpbiBJRCBtYXBwaW5nIG9mIHRyYW5zY3JpcHRzIGFuZCBhc3NvY2lhdGVkIEdPIHRlcm1zIGV0Yy4KUGV2ZV9JRG1hcHBpbmcgPC0gcmVhZF9kZWxpbSgiLi4vb3V0cHV0LzAyLVBldmUtcmVmZXJlbmNlLWFubm90YXRpb24vUG9yaXRlc19ldmVybWFubmlfQ0RTLUlEbWFwcGluZy0yMDI0XzA5XzA0LnRhYiIpICU+JQogIHNlbGVjdCgtLi4uMSkKaGVhZChQZXZlX0lEbWFwcGluZykKYGBgCgojIyBDb3VudCBkYXRhIG11bmdpbmcKCmBgYHtyIGNvdW50LWRhdGEtbXVuZ2luZ30KIyBXZSBuZWVkIHRvIG1vZGlmeSB0aGlzIGRhdGEgZnJhbWUgc28gdGhhdCB0aGUgcm93IG5hbWVzIGFyZSBhY3R1YWxseSByb3cgbmFtZXMsIGluc3RlYWQgb2YgY29tcHJpc2luZyB0aGUgZmlyc3QgY29sdW1uClBldmVfY291bnRzX2RhdGEgPC0gUGV2ZV9jb3VudHNfZGF0YV9PRyAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXModmFyID0gIi4uLjEiKQoKIyBBZGRpdGlvbmFsIGZvcm1hdHRpbmcKIyBSb3VuZCBhbGwgZXN0aW1hdGVkIGNvdW50cyB0byBpbnRlZ2VycwpQZXZlX2NvdW50c19kYXRhIDwtIHJvdW5kKFBldmVfY291bnRzX2RhdGEsIGRpZ2l0cyA9IDApCgojIFJlbW92ZSBhbGwgdHJhbnNjcmlwdHMgd2l0aCA1IG9yIGZld2VyIGNvdW50cyBpbiBhbGwgc2FtcGxlcwpQZXZlX2NvdW50c19kYXRhIDwtIFBldmVfY291bnRzX2RhdGFbIWFwcGx5KFBldmVfY291bnRzX2RhdGEsIDEsIGZ1bmN0aW9uKHJvdykgYWxsKHJvdyA8IDYpKSwgXQoKIyBSZW1vdmUgdGhlICJrYWxsaXN0b19xdWFudF8iIHBvcnRpb24gb2YgdGhlIGNvbHVtbiBuYW1lcywgdG8gbGVhdmUganVzdCB0aGUgc2FtcGxlIG5hbWVzCmNvbG5hbWVzKFBldmVfY291bnRzX2RhdGEpIDwtIHN1Yigia2FsbGlzdG9fcXVhbnRfIiwgIiIsIGNvbG5hbWVzKFBldmVfY291bnRzX2RhdGEpKQoKIyBSZW9yZGVyIHRoZSBjb2x1bW5zIGludG8gYWxwaGFiZXRpY2FsIG9yZGVyICh0byBtYWtlIGl0IGVhc2llciB0byBjcmVhdGUgYW4gYXNzb2NpYXRlZCBtZXRhZGF0YSBzcHJlYWRzaGVldCkKUGV2ZV9jb3VudHNfZGF0YSA8LSBQZXZlX2NvdW50c19kYXRhWywgb3JkZXIoY29sbmFtZXMoUGV2ZV9jb3VudHNfZGF0YSkpXQoKUGV2ZV9zYW1wbGVfbmFtZXMgPC0gbmFtZXMoUGV2ZV9jb3VudHNfZGF0YSkKCmhlYWQoUGV2ZV9jb3VudHNfZGF0YSkKUGV2ZV9zYW1wbGVfbmFtZXMKYGBgCgpgYGB7ciBqb2luLWNvdW50cy1hbm5vdGF0aW9ucywgZXZhbD1UUlVFfQpQZXZlX2NvdW50c19HTyA8LSBQZXZlX2NvdW50c19kYXRhICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAidHJhbnNjcmlwdCIpICU+JQogIGxlZnRfam9pbihQZXZlX0lEbWFwcGluZywgYnkgPSBjKCJ0cmFuc2NyaXB0IiA9ICJWMSIpKQoKaGVhZChQZXZlX2NvdW50c19HTykKYGBgCgojIFN1bW1hcnkgc3RhdHMgYW5kIHZpc3VhbGl6YXRpb25zCgojIyBFeHByZXNzaW9uIGxldmVscwoKUGxvdCBoaXN0b2dyYW1zIG9mIHRoZSBleHByZXNzaW9uIGxldmVscyBpbiBlYWNoIHNhbXBsZQoKYGBge3IgZXhwcmVzc2lvbi1sZXZlbC1oaXN0b2dyYW1zfQojIE1lbHQgdGhlIGNvdW50IG1hdHJpeCBpbnRvIGxvbmcgZm9ybWF0ClBldmVfY291bnRzX21lbHRlZCA8LSBtZWx0KFBldmVfY291bnRzX2RhdGEsIHZhcmlhYmxlLm5hbWUgPSAic2FtcGxlIiwgdmFsdWUubmFtZSA9ICJjb3VudHMiKQoKIyBQbG90IHRoZSBleHByZXNzaW9uIGxldmVsIGhpc3RvZ3JhbXMgZm9yIGVhY2ggc2FtcGxlCmdncGxvdChQZXZlX2NvdW50c19tZWx0ZWQsIGFlcyh4ID0gY291bnRzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICIjMUUyNzYxIiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfeF9sb2cxMCgpICsgICMgT3B0aW9uYWw6IExvZy10cmFuc2Zvcm0gdGhlIHgtYXhpcyBmb3IgYmV0dGVyIHZpc3VhbGl6YXRpb24KICBmYWNldF93cmFwKH5zYW1wbGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh0aXRsZSA9ICJHZW5lIEV4cHJlc3Npb24gTGV2ZWwgSGlzdG9ncmFtIGZvciBFYWNoIFNhbXBsZSIsCiAgICAgICB4ID0gIkV4cHJlc3Npb24gTGV2ZWwgKENvdW50cykiLAogICAgICAgeSA9ICJGcmVxdWVuY3kiKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyMgVHJhbnNjcmlwdCBjb3VudHMKCkZpcnN0IGxldCdzIGNoZWNrIHRoZSB0b3RhbCBudW1iZXIgb2YgdHJhbnNjcmlwdHMgaW4gZWFjaCBzYW1wbGUgLS0ga2VlcCBpbiBtaW5kIHRoaXMgZXhwcmVzc2lvbiBkYXRhIGhhcyAqbm90KiBiZWVuIG5vcm1hbGl6ZWQgeWV0LCBzbyB0aGVyZSBtYXkgYmUgZGlmZmVyZW50IHRvdGFscyBmb3IgZWFjaCBzYW1wbGUKYGBge3IgdHJhbnNjcmlwdC1jb3VudHMtcGxvdH0KIyBDYWxjdWxhdGUgdGhlIHRvdGFsIG51bWJlciBvZiB0cmFuc2NyaXB0cyBmb3IgZWFjaCBzYW1wbGUKdG90YWxfdHJhbnNjcmlwdHMgPC0gY29sU3VtcyhQZXZlX2NvdW50c19kYXRhKQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBwbG90dGluZwp0b3RhbF90cmFuc2NyaXB0c19kZiA8LSBkYXRhLmZyYW1lKHNhbXBsZSA9IG5hbWVzKHRvdGFsX3RyYW5zY3JpcHRzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbHMgPSB0b3RhbF90cmFuc2NyaXB0cykKCiMgUGxvdCB0aGUgdG90YWwgbnVtYmVyIG9mIHRyYW5zY3JpcHRzIGZvciBlYWNoIHNhbXBsZQpnZ3Bsb3QodG90YWxfdHJhbnNjcmlwdHNfZGYsIGFlcyh4ID0gc2FtcGxlLCB5ID0gdG90YWxzKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gIiMxRTI3NjEiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIE51bWJlciBvZiBUcmFuc2NyaXB0cyBwZXIgU2FtcGxlIiwKICAgICAgIHggPSAiU2FtcGxlIiwKICAgICAgIHkgPSAiVG90YWwgVHJhbnNjcmlwdHMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSAgIyBSb3RhdGUgeC1heGlzIGxhYmVscyBmb3IgcmVhZGFiaWxpdHkKYGBgCgpOb3cgbGV0J3MgY2hlY2sgdGhlIG51bWJlciBvZiB1bmlxdWUgdHJhbnNjcmlwdHMgaW4gZWFjaCBzYW1wbGUgLS0gdGhhdCBpcywgaG93IG1hbnkgZ2VuZXMgYXJlIGV4cHJlc3NlZCBpbiBlYWNoIHNhbXBsZT8gVGhpcyBzaG91bGQgYmUgcHJldHR5IG11Y2ggdGhlIHNhbWUgYWNyb3NzIHNhbXBsZXMsIGV2ZW4gd2l0aG91dCBub3JtYWxpemF0aW9uLgoKYGBge3IgdG90YWwtdW5pcXVlLXRyYW5zY3JpcHRzLXBsb3R9CiMgQ2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIChub24temVybyBjb3VudHMpIGZvciBlYWNoIHNhbXBsZQp1bmlxdWVfdHJhbnNjcmlwdHMgPC0gY29sU3VtcyhQZXZlX2NvdW50c19kYXRhID4gMCkKCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgcGxvdHRpbmcKdW5pcXVlX3RyYW5zY3JpcHRzX2RmIDwtIGRhdGEuZnJhbWUoc2FtcGxlID0gbmFtZXModW5pcXVlX3RyYW5zY3JpcHRzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pcXVlcyA9IHVuaXF1ZV90cmFuc2NyaXB0cykKCiMgUGxvdCB0aGUgdG90YWwgbnVtYmVyIG9mIHVuaXF1ZSB0cmFuc2NyaXB0cyBmb3IgZWFjaCBzYW1wbGUKZ2dwbG90KHVuaXF1ZV90cmFuc2NyaXB0c19kZiwgYWVzKHggPSBzYW1wbGUsIHkgPSB1bmlxdWVzKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gIiMxRTI3NjEiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIE51bWJlciBvZiBVbmlxdWUgRXhwcmVzc2VkIFRyYW5zY3JpcHRzIHBlciBTYW1wbGUiLAogICAgICAgeCA9ICJTYW1wbGUiLAogICAgICAgeSA9ICJVbmlxdWUgVHJhbnNjcmlwdHMiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSAgIyBSb3RhdGUgeC1heGlzIGxhYmVscyBmb3IgcmVhZGFiaWxpdHkKYGBgCiAgIAoKCiMjIE1vc3QgY29tbW9uIGJpb2xvZ2ljYWwgcHJvY2Vzc2VzCgpTaW1pbGFyIHRvIHRoZSBwbG90IGdlbmVyYXRlZCBpbiBgMDItUGV2ZS1yZWZlcmVuY2UtYW5ub3RhdGlvbmAsIGxldCdzIHBsb3QgdGhlIGJpb2xvZ2ljYWwgcHJvY2Vzc2VzIG1vc3QgcmVwcmVzZW50ZWQgaW4gdGhlc2Ugc2FtcGxlcycgZXhwcmVzc2lvbgoKYGBge3IgbW9zdC1jb21tb24tcHJvY2Vzc2VzfQoKIyBSZW5hbWUgdGhlIGBHZW5lLk9udG9sb2d5Li5iaW9sb2dpY2FsLnByb2Nlc3MuYCBjb2x1bW4gdG8gYEJpb2xvZ2ljYWxfUHJvY2Vzc2AKY29sbmFtZXMoUGV2ZV9jb3VudHNfR08pW2NvbG5hbWVzKFBldmVfY291bnRzX0dPKSA9PSAiR2VuZS5PbnRvbG9neS4uYmlvbG9naWNhbC5wcm9jZXNzLiJdIDwtICJCaW9sb2dpY2FsX1Byb2Nlc3MiCgojIFNlcGFyYXRlIHRoZSBgQmlvbG9naWNhbF9Qcm9jZXNzYCBjb2x1bW4gaW50byBpbmRpdmlkdWFsIGJpb2xvZ2ljYWwgcHJvY2Vzc2VzCmRhdGFfc2VwYXJhdGVkIDwtIHVubGlzdChzdHJzcGxpdChQZXZlX2NvdW50c19HTyRCaW9sb2dpY2FsX1Byb2Nlc3MsIHNwbGl0ID0gIjsiKSkKCiMgVHJpbSB3aGl0ZXNwYWNlIGZyb20gdGhlIGJpb2xvZ2ljYWwgcHJvY2Vzc2VzCmRhdGFfc2VwYXJhdGVkIDwtIGdzdWIoIl5cXHMrfFxccyskIiwgIiIsIGRhdGFfc2VwYXJhdGVkKQoKIyBDb3VudCB0aGUgb2NjdXJyZW5jZXMgb2YgZWFjaCBiaW9sb2dpY2FsIHByb2Nlc3MKcHJvY2Vzc19jb3VudHMgPC0gdGFibGUoZGF0YV9zZXBhcmF0ZWQpCnByb2Nlc3NfY291bnRzIDwtIGRhdGEuZnJhbWUoQmlvbG9naWNhbF9Qcm9jZXNzID0gbmFtZXMocHJvY2Vzc19jb3VudHMpLCBDb3VudCA9IGFzLmludGVnZXIocHJvY2Vzc19jb3VudHMpKQpwcm9jZXNzX2NvdW50cyA8LSBwcm9jZXNzX2NvdW50c1tvcmRlcigtcHJvY2Vzc19jb3VudHMkQ291bnQpLCBdCgojIFNlbGVjdCB0aGUgMjAgbW9zdCBwcmVkb21pbmFudCBiaW9sb2dpY2FsIHByb2Nlc3Nlcwp0b3BfMjBfcHJvY2Vzc2VzIDwtIHByb2Nlc3NfY291bnRzWzE6MjAsIF0KCiMgQ3JlYXRlIGEgY29sb3IgcGFsZXR0ZSBmb3IgdGhlIGJhcnMKYmFyX2NvbG9ycyA8LSByYWluYm93KG5yb3codG9wXzIwX3Byb2Nlc3NlcykpCgojIENyZWF0ZSBhIHN0YWdnZXJlZCB2ZXJ0aWNhbCBiYXIgcGxvdCB3aXRoIGRpZmZlcmVudCBjb2xvcnMgZm9yIGVhY2ggYmFyCmJhcnBsb3QodG9wXzIwX3Byb2Nlc3NlcyRDb3VudCwgbmFtZXMuYXJnID0gcmVwKCIiLCBucm93KHRvcF8yMF9wcm9jZXNzZXMpKSwgY29sID0gYmFyX2NvbG9ycywKICAgICAgICB5bGltID0gYygwLCBtYXgodG9wXzIwX3Byb2Nlc3NlcyRDb3VudCkgKiAxLjI1KSwKICAgICAgICBtYWluID0gIk9jY3VycmVuY2VzIG9mIHRoZSAyMCBNb3N0IFByZWRvbWluYW50IEJpb2xvZ2ljYWwgUHJvY2Vzc2VzIiwgeGxhYiA9ICJCaW9sb2dpY2FsIFByb2Nlc3MiLCB5bGFiID0gIkNvdW50IikKCgojIENyZWF0ZSBhIHNlcGFyYXRlIHBsb3QgZm9yIHRoZSBsZWdlbmQKcG5nKCIuLi9vdXRwdXQvMDMtUGV2ZS1STkEtc3VtbWFyeS9HT2xlZ2VuZC5wbmciLCB3aWR0aCA9IDgwMCwgaGVpZ2h0ID0gNjAwKQpwYXIobWFyID0gYygwLCAwLCAwLCAwKSkKcGxvdC5uZXcoKQpsZWdlbmQoImNlbnRlciIsIGxlZ2VuZCA9IHRvcF8yMF9wcm9jZXNzZXMkQmlvbG9naWNhbF9Qcm9jZXNzLCBmaWxsID0gYmFyX2NvbG9ycywgY2V4ID0gMSwgdGl0bGUgPSAiQmlvbG9naWNhbCBQcm9jZXNzZXMiKQpkZXYub2ZmKCkKYGBgCgpgYGB7ciBnby1sZWdlbmQsIGV2YWw9VFJVRSwgZmlnLndpZHRoID0gMTAwICxmaWcuaGVpZ2h0ID0gMTAwfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vb3V0cHV0LzAzLVBldmUtUk5BLXN1bW1hcnkvR09sZWdlbmQucG5nIikKYGBgCgpgYGB7ciByZW1vdmUtbGVnZW5kLWZpbGUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0Kcm0gLi4vb3V0cHV0LzAzLVBldmUtUk5BLXN1bW1hcnkvR09sZWdlbmQucG5nCmBgYA==