Gene expression summary for Pocillopora tuahiniensis RNA-seq data.

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

  • Reads aligned to Pocillopora meandrina 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
Ptuh_counts_data_OG <- read_delim("../../../deep-dive/F-Pmea/output/14-Pmea-RNAseq-kallisto/kallisto/kallisto.isoform.counts.matrix") 
head(Ptuh_counts_data_OG)
# A tibble: 6 × 6
  ...1      kallisto_quant_sampl…¹ kallisto_quant_sampl…² kallisto_quant_sampl…³
  <chr>                      <dbl>                  <dbl>                  <dbl>
1 Pocillop…                  242                     271                   390  
2 Pocillop…                    0                       9                     3  
3 Pocillop…                 1067                    1666.                 2432  
4 Pocillop…                   56                      43                     9  
5 Pocillop…                    0                       0                     5  
6 Pocillop…                   40.4                     0                    21.9
# ℹ abbreviated names: ¹​kallisto_quant_sample47, ²​kallisto_quant_sample48,
#   ³​kallisto_quant_sample50
# ℹ 2 more variables: kallisto_quant_sample53 <dbl>,
#   kallisto_quant_sample57 <dbl>
# Read in ID mapping of transcripts and associated GO terms etc.
Ptuh_IDmapping <- read_delim("../output/02-Ptuh-reference-annotation/Pocillopora_meandrina_HIv1-IDmapping-2024_09_04.tab") %>%
  select(-...1)
head(Ptuh_IDmapping)
# A tibble: 6 × 7
  V1               V3          V13 Protein.names Organism Gene.Ontology..biolo…¹
  <chr>            <chr>     <dbl> <chr>         <chr>    <chr>                 
1 Pocillopora_mea… Q7ZT… 3.67e- 66 DNA replicat… Xenopus… DNA replication [GO:0…
2 Pocillopora_mea… P551… 1.16e- 38 Zinc metallo… Caenorh… proteolysis [GO:00065…
3 Pocillopora_mea… Q9Y4… 7.59e-138 Diacylglycer… Homo sa… arachidonic acid meta…
4 Pocillopora_mea… Q616… 1.32e- 21 H2.0-like ho… Mus mus… animal organ developm…
5 Pocillopora_mea… Q107… 2.44e- 41 Angiotensin-… Gallus … angiotensin maturatio…
6 Pocillopora_mea… Q107… 3.91e- 40 Angiotensin-… Gallus … angiotensin maturatio…
# ℹ 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
Ptuh_counts_data <- Ptuh_counts_data_OG %>%
  column_to_rownames(var = "...1")

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

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

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

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

Ptuh_sample_names <- names(Ptuh_counts_data)

head(Ptuh_counts_data)
                                              sample47 sample48 sample50
Pocillopora_meandrina_HIv1___RNAseq.g5509.t1       242      271      390
Pocillopora_meandrina_HIv1___RNAseq.g3856.t1         0        9        3
Pocillopora_meandrina_HIv1___RNAseq.g29982.t1     1067     1666     2432
Pocillopora_meandrina_HIv1___TS.g21722.t1           56       43        9
Pocillopora_meandrina_HIv1___RNAseq.g23510.t1       40        0       22
Pocillopora_meandrina_HIv1___RNAseq.g2438.t1         8       72       16
                                              sample53 sample57
Pocillopora_meandrina_HIv1___RNAseq.g5509.t1       235      238
Pocillopora_meandrina_HIv1___RNAseq.g3856.t1         5        1
Pocillopora_meandrina_HIv1___RNAseq.g29982.t1     1275     1783
Pocillopora_meandrina_HIv1___TS.g21722.t1           76       80
Pocillopora_meandrina_HIv1___RNAseq.g23510.t1       60        0
Pocillopora_meandrina_HIv1___RNAseq.g2438.t1        25        8
Ptuh_sample_names
[1] "sample47" "sample48" "sample50" "sample53" "sample57"
Ptuh_counts_GO <- Ptuh_counts_data %>%
  rownames_to_column(var = "transcript") %>%
  left_join(Ptuh_IDmapping, by = c("transcript" = "V1"))

head(Ptuh_counts_GO)
                                     transcript sample47 sample48 sample50
1  Pocillopora_meandrina_HIv1___RNAseq.g5509.t1      242      271      390
2  Pocillopora_meandrina_HIv1___RNAseq.g3856.t1        0        9        3
3 Pocillopora_meandrina_HIv1___RNAseq.g29982.t1     1067     1666     2432
4     Pocillopora_meandrina_HIv1___TS.g21722.t1       56       43        9
5 Pocillopora_meandrina_HIv1___RNAseq.g23510.t1       40        0       22
6  Pocillopora_meandrina_HIv1___RNAseq.g2438.t1        8       72       16
  sample53 sample57     V3      V13
1      235      238 Q56P03 5.85e-49
2        5        1   <NA>       NA
3     1275     1783   <NA>       NA
4       76       80   <NA>       NA
5       60        0 P51635 1.38e-70
6       25        8 Q9EQD2 2.00e-48
                                                                                                                                                                                                                                                  Protein.names
1                                                                                                                                                                                                                          E2F-associated phosphoprotein (EAPP)
2                                                                                                                                                                                                                                                          <NA>
3                                                                                                                                                                                                                                                          <NA>
4                                                                                                                                                                                                                                                          <NA>
5 Aldo-keto reductase family 1 member A1 (EC 1.1.1.2) (EC 1.1.1.33) (EC 1.1.1.372) (EC 1.1.1.54) (3-DG-reducing enzyme) (Alcohol dehydrogenase [NADP(+)]) (Aldehyde reductase) (Glucuronate reductase) (EC 1.1.1.19) (Glucuronolactone reductase) (EC 1.1.1.20)
6                                                                                                                                                          Neuropeptide FF receptor 2 (G-protein coupled receptor 74) (Neuropeptide G-protein coupled receptor)
                 Organism
1    Homo sapiens (Human)
2                    <NA>
3                    <NA>
4                    <NA>
5 Rattus norvegicus (Rat)
6 Rattus norvegicus (Rat)
                                                                                                                                                                                                                                                                                                                                                             Gene.Ontology..biological.process.
1                                                                                                                                                       negative regulation of transcription elongation by RNA polymerase II [GO:0034244]; positive regulation of cell population proliferation [GO:0008284]; positive regulation of transcription elongation by RNA polymerase II [GO:0032968]
2                                                                                                                                                                                                                                                                                                                                                                                          <NA>
3                                                                                                                                                                                                                                                                                                                                                                                          <NA>
4                                                                                                                                                                                                                                                                                                                                                                                          <NA>
5 aldehyde catabolic process [GO:0046185]; cellular detoxification of aldehyde [GO:0110095]; D-glucuronate catabolic process [GO:0042840]; daunorubicin metabolic process [GO:0044597]; doxorubicin metabolic process [GO:0044598]; glucuronate catabolic process to xylulose 5-phosphate [GO:0019640]; L-ascorbic acid biosynthetic process [GO:0019853]; lipid metabolic process [GO:0006629]
6                                                                                                                                                                  G protein-coupled receptor signaling pathway [GO:0007186]; regulation of adenylate cyclase activity [GO:0045761]; regulation of cAMP-dependent protein kinase activity [GO:2000479]; regulation of MAPK cascade [GO:0043408]
                                                                                                                                                                                                                   Gene.Ontology.IDs
1                                                                                                                                                                         GO:0005634; GO:0005737; GO:0008284; GO:0032968; GO:0034244
2                                                                                                                                                                                                                               <NA>
3                                                                                                                                                                                                                               <NA>
4                                                                                                                                                                                                                               <NA>
5 GO:0004032; GO:0005829; GO:0006629; GO:0016324; GO:0016657; GO:0019640; GO:0019726; GO:0019853; GO:0042840; GO:0044597; GO:0044598; GO:0045202; GO:0046185; GO:0047655; GO:0047939; GO:0047941; GO:0047956; GO:0110095; GO:1990002
6                                                                                                             GO:0004930; GO:0005886; GO:0007186; GO:0008188; GO:0015629; GO:0031628; GO:0042277; GO:0043408; GO:0045761; GO:2000479

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
Ptuh_counts_melted <- melt(Ptuh_counts_data, variable.name = "sample", value.name = "counts")

# Plot the expression level histograms for each sample
ggplot(Ptuh_counts_melted, aes(x = counts)) +
  geom_histogram(binwidth = 1, fill = "#7A2048", 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(Ptuh_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 = "#7A2048", 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(Ptuh_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 = "#7A2048", 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-Ptuh-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(Ptuh_counts_GO)[colnames(Ptuh_counts_GO) == "Gene.Ontology..biological.process."] <- "Biological_Process"

# Separate the `Biological_Process` column into individual biological processes
data_separated <- unlist(strsplit(Ptuh_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-Ptuh-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-Ptuh-RNA-summary/GOlegend.png")

rm ../output/03-Ptuh-RNA-summary/GOlegend.png
LS0tCnRpdGxlOiAiMDMtUHR1aC1STkEtc3VtbWFyeSIKYXV0aG9yOiAiS2F0aGxlZW4gRHVya2luIgpkYXRlOiAiMjAyNC0wOS0wNCIKYWx3YXlzX2FsbG93X2h0bWw6IHRydWUKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGh0bWxfcHJldmlldzogdHJ1ZSAKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBUUlVFLCAgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKR2VuZSBleHByZXNzaW9uIHN1bW1hcnkgZm9yICpQb2NpbGxvcG9yYSB0dWFoaW5pZW5zaXMqIFJOQS1zZXEgZGF0YS4KCi0gICB0cmltbWVkIHJlYWRzIGdlbmVyYXRlZCBpbiBgZGVlcC1kaXZlYCBwcm9qZWN0LCB0cmltbWluZyBhbmQgUUMgZGV0YWlscyBpbiBgMDEtUHR1aC1STkEtdHJpbW1pbmctRmFzdFFDYAoKLSAgIFJlYWRzIGFsaWduZWQgdG8gKlBvY2lsbG9wb3JhIG1lYW5kcmluYSogdHJhbnNjcmlwdG9tZSwgZGV0YWlscyBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9GLVB0dWgvY29kZS8xMi1QdHVoLVJOQXNlcS1rYWxsaXN0by5tZCkKCiMjIyBJbnN0YWxsIGFuZCBsb2FkIHBhY2thZ2VzCgpgYGB7ciBsb2FkX2xpYnJhcmllcywgaW5sY3VkZSA9IFRSVUV9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmVzaGFwZTIpCmBgYAoKIyBMb2FkIGRhdGEKCiMjIExvYWQgY291bnQgZGF0YQoKTG9hZCBpbiB0aGUgY291bnQgbWF0cml4IHdlIGdlbmVyYXRlZCBhZnRlciBrYWxsaXN0byBwc2V1ZG9hbGlnbm1lbnQgdXNpbmcgdGhlIFRyaW5pdHkgYWJ1bmRhbmNlX2VzdGltYXRlc190b19tYXRyaXgucGwgc2NyaXB0LiBXZSBhbHNvIG5lZWQgdG8gc2xpZ2h0bHkgcmVmb3JtYXQgdGhlIGNvdW50IG1hdHJpeAoKYGBge3IgbG9hZC1jb3VudC1kYXRhfQojIFJlYWQgaW4gY291bnRzIGRhdGEuIFRoaXMgaXMgYSBnZW5lLWxldmVsIGNvdW50cyBtYXRyaXggZ2VuZXJhdGVkIGZyb20ga2FsbGlzdG8gdHJhbnNjcmlwdCBhYnVuZGFuY2VzIHVzaW5nIFRyaW5pdHkKUHR1aF9jb3VudHNfZGF0YV9PRyA8LSByZWFkX2RlbGltKCIuLi8uLi8uLi9kZWVwLWRpdmUvRi1QbWVhL291dHB1dC8xNC1QbWVhLVJOQXNlcS1rYWxsaXN0by9rYWxsaXN0by9rYWxsaXN0by5pc29mb3JtLmNvdW50cy5tYXRyaXgiKSAKaGVhZChQdHVoX2NvdW50c19kYXRhX09HKQoKIyBSZWFkIGluIElEIG1hcHBpbmcgb2YgdHJhbnNjcmlwdHMgYW5kIGFzc29jaWF0ZWQgR08gdGVybXMgZXRjLgpQdHVoX0lEbWFwcGluZyA8LSByZWFkX2RlbGltKCIuLi9vdXRwdXQvMDItUHR1aC1yZWZlcmVuY2UtYW5ub3RhdGlvbi9Qb2NpbGxvcG9yYV9tZWFuZHJpbmFfSEl2MS1JRG1hcHBpbmctMjAyNF8wOV8wNC50YWIiKSAlPiUKICBzZWxlY3QoLS4uLjEpCmhlYWQoUHR1aF9JRG1hcHBpbmcpCmBgYAoKIyMgQ291bnQgZGF0YSBtdW5naW5nCgpgYGB7ciBjb3VudC1kYXRhLW11bmdpbmd9CiMgV2UgbmVlZCB0byBtb2RpZnkgdGhpcyBkYXRhIGZyYW1lIHNvIHRoYXQgdGhlIHJvdyBuYW1lcyBhcmUgYWN0dWFsbHkgcm93IG5hbWVzLCBpbnN0ZWFkIG9mIGNvbXByaXNpbmcgdGhlIGZpcnN0IGNvbHVtbgpQdHVoX2NvdW50c19kYXRhIDwtIFB0dWhfY291bnRzX2RhdGFfT0cgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICIuLi4xIikKCiMgQWRkaXRpb25hbCBmb3JtYXR0aW5nCiMgUm91bmQgYWxsIGVzdGltYXRlZCBjb3VudHMgdG8gaW50ZWdlcnMKUHR1aF9jb3VudHNfZGF0YSA8LSByb3VuZChQdHVoX2NvdW50c19kYXRhLCBkaWdpdHMgPSAwKQoKIyBSZW1vdmUgYWxsIHRyYW5zY3JpcHRzIHdpdGggNSBvciBmZXdlciBjb3VudHMgaW4gYWxsIHNhbXBsZXMKUHR1aF9jb3VudHNfZGF0YSA8LSBQdHVoX2NvdW50c19kYXRhWyFhcHBseShQdHVoX2NvdW50c19kYXRhLCAxLCBmdW5jdGlvbihyb3cpIGFsbChyb3cgPCA2KSksIF0KCiMgUmVtb3ZlIHRoZSAia2FsbGlzdG9fcXVhbnRfIiBwb3J0aW9uIG9mIHRoZSBjb2x1bW4gbmFtZXMsIHRvIGxlYXZlIGp1c3QgdGhlIHNhbXBsZSBuYW1lcwpjb2xuYW1lcyhQdHVoX2NvdW50c19kYXRhKSA8LSBzdWIoImthbGxpc3RvX3F1YW50XyIsICIiLCBjb2xuYW1lcyhQdHVoX2NvdW50c19kYXRhKSkKCiMgUmVvcmRlciB0aGUgY29sdW1ucyBpbnRvIGFscGhhYmV0aWNhbCBvcmRlciAodG8gbWFrZSBpdCBlYXNpZXIgdG8gY3JlYXRlIGFuIGFzc29jaWF0ZWQgbWV0YWRhdGEgc3ByZWFkc2hlZXQpClB0dWhfY291bnRzX2RhdGEgPC0gUHR1aF9jb3VudHNfZGF0YVssIG9yZGVyKGNvbG5hbWVzKFB0dWhfY291bnRzX2RhdGEpKV0KClB0dWhfc2FtcGxlX25hbWVzIDwtIG5hbWVzKFB0dWhfY291bnRzX2RhdGEpCgpoZWFkKFB0dWhfY291bnRzX2RhdGEpClB0dWhfc2FtcGxlX25hbWVzCmBgYAoKYGBge3Igam9pbi1jb3VudHMtYW5ub3RhdGlvbnMsIGV2YWw9VFJVRX0KUHR1aF9jb3VudHNfR08gPC0gUHR1aF9jb3VudHNfZGF0YSAlPiUKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInRyYW5zY3JpcHQiKSAlPiUKICBsZWZ0X2pvaW4oUHR1aF9JRG1hcHBpbmcsIGJ5ID0gYygidHJhbnNjcmlwdCIgPSAiVjEiKSkKCmhlYWQoUHR1aF9jb3VudHNfR08pCmBgYAoKIyBTdW1tYXJ5IHN0YXRzIGFuZCB2aXN1YWxpemF0aW9ucwoKIyMgRXhwcmVzc2lvbiBsZXZlbHMKClBsb3QgaGlzdG9ncmFtcyBvZiB0aGUgZXhwcmVzc2lvbiBsZXZlbHMgaW4gZWFjaCBzYW1wbGUKCmBgYHtyIGV4cHJlc3Npb24tbGV2ZWwtaGlzdG9ncmFtc30KIyBNZWx0IHRoZSBjb3VudCBtYXRyaXggaW50byBsb25nIGZvcm1hdApQdHVoX2NvdW50c19tZWx0ZWQgPC0gbWVsdChQdHVoX2NvdW50c19kYXRhLCB2YXJpYWJsZS5uYW1lID0gInNhbXBsZSIsIHZhbHVlLm5hbWUgPSAiY291bnRzIikKCiMgUGxvdCB0aGUgZXhwcmVzc2lvbiBsZXZlbCBoaXN0b2dyYW1zIGZvciBlYWNoIHNhbXBsZQpnZ3Bsb3QoUHR1aF9jb3VudHNfbWVsdGVkLCBhZXMoeCA9IGNvdW50cykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAiIzdBMjA0OCIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfbG9nMTAoKSArICAjIE9wdGlvbmFsOiBMb2ctdHJhbnNmb3JtIHRoZSB4LWF4aXMgZm9yIGJldHRlciB2aXN1YWxpemF0aW9uCiAgZmFjZXRfd3JhcCh+c2FtcGxlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnModGl0bGUgPSAiR2VuZSBFeHByZXNzaW9uIExldmVsIEhpc3RvZ3JhbSBmb3IgRWFjaCBTYW1wbGUiLAogICAgICAgeCA9ICJFeHByZXNzaW9uIExldmVsIChDb3VudHMpIiwKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIFRyYW5zY3JpcHQgY291bnRzCgpGaXJzdCBsZXQncyBjaGVjayB0aGUgdG90YWwgbnVtYmVyIG9mIHRyYW5zY3JpcHRzIGluIGVhY2ggc2FtcGxlIC0tIGtlZXAgaW4gbWluZCB0aGlzIGV4cHJlc3Npb24gZGF0YSBoYXMgKm5vdCogYmVlbiBub3JtYWxpemVkIHlldCwgc28gdGhlcmUgbWF5IGJlIGRpZmZlcmVudCB0b3RhbHMgZm9yIGVhY2ggc2FtcGxlCmBgYHtyIHRyYW5zY3JpcHQtY291bnRzLXBsb3R9CiMgQ2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2YgdHJhbnNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlCnRvdGFsX3RyYW5zY3JpcHRzIDwtIGNvbFN1bXMoUHR1aF9jb3VudHNfZGF0YSkKCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgcGxvdHRpbmcKdG90YWxfdHJhbnNjcmlwdHNfZGYgPC0gZGF0YS5mcmFtZShzYW1wbGUgPSBuYW1lcyh0b3RhbF90cmFuc2NyaXB0cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxzID0gdG90YWxfdHJhbnNjcmlwdHMpCgojIFBsb3QgdGhlIHRvdGFsIG51bWJlciBvZiB0cmFuc2NyaXB0cyBmb3IgZWFjaCBzYW1wbGUKZ2dwbG90KHRvdGFsX3RyYW5zY3JpcHRzX2RmLCBhZXMoeCA9IHNhbXBsZSwgeSA9IHRvdGFscykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICIjN0EyMDQ4IiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBOdW1iZXIgb2YgVHJhbnNjcmlwdHMgcGVyIFNhbXBsZSIsCiAgICAgICB4ID0gIlNhbXBsZSIsCiAgICAgICB5ID0gIlRvdGFsIFRyYW5zY3JpcHRzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIHJlYWRhYmlsaXR5CmBgYAoKTm93IGxldCdzIGNoZWNrIHRoZSBudW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIGluIGVhY2ggc2FtcGxlIC0tIHRoYXQgaXMsIGhvdyBtYW55IGdlbmVzIGFyZSBleHByZXNzZWQgaW4gZWFjaCBzYW1wbGU/IFRoaXMgc2hvdWxkIGJlIHByZXR0eSBtdWNoIHRoZSBzYW1lIGFjcm9zcyBzYW1wbGVzLCBldmVuIHdpdGhvdXQgbm9ybWFsaXphdGlvbi4KCmBgYHtyIHRvdGFsLXVuaXF1ZS10cmFuc2NyaXB0cy1wbG90fQojIENhbGN1bGF0ZSB0aGUgbnVtYmVyIG9mIHVuaXF1ZSB0cmFuc2NyaXB0cyAobm9uLXplcm8gY291bnRzKSBmb3IgZWFjaCBzYW1wbGUKdW5pcXVlX3RyYW5zY3JpcHRzIDwtIGNvbFN1bXMoUHR1aF9jb3VudHNfZGF0YSA+IDApCgojIENyZWF0ZSBhIGRhdGEgZnJhbWUgZm9yIHBsb3R0aW5nCnVuaXF1ZV90cmFuc2NyaXB0c19kZiA8LSBkYXRhLmZyYW1lKHNhbXBsZSA9IG5hbWVzKHVuaXF1ZV90cmFuc2NyaXB0cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXF1ZXMgPSB1bmlxdWVfdHJhbnNjcmlwdHMpCgojIFBsb3QgdGhlIHRvdGFsIG51bWJlciBvZiB1bmlxdWUgdHJhbnNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlCmdncGxvdCh1bmlxdWVfdHJhbnNjcmlwdHNfZGYsIGFlcyh4ID0gc2FtcGxlLCB5ID0gdW5pcXVlcykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICIjN0EyMDQ4IiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBOdW1iZXIgb2YgVW5pcXVlIEV4cHJlc3NlZCBUcmFuc2NyaXB0cyBwZXIgU2FtcGxlIiwKICAgICAgIHggPSAiU2FtcGxlIiwKICAgICAgIHkgPSAiVW5pcXVlIFRyYW5zY3JpcHRzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIHJlYWRhYmlsaXR5CmBgYAogICAKCgojIyBNb3N0IGNvbW1vbiBiaW9sb2dpY2FsIHByb2Nlc3NlcwoKU2ltaWxhciB0byB0aGUgcGxvdCBnZW5lcmF0ZWQgaW4gYDAyLVB0dWgtcmVmZXJlbmNlLWFubm90YXRpb25gLCBsZXQncyBwbG90IHRoZSBiaW9sb2dpY2FsIHByb2Nlc3NlcyBtb3N0IHJlcHJlc2VudGVkIGluIHRoZXNlIHNhbXBsZXMnIGV4cHJlc3Npb24KCmBgYHtyIG1vc3QtY29tbW9uLXByb2Nlc3Nlc30KCiMgUmVuYW1lIHRoZSBgR2VuZS5PbnRvbG9neS4uYmlvbG9naWNhbC5wcm9jZXNzLmAgY29sdW1uIHRvIGBCaW9sb2dpY2FsX1Byb2Nlc3NgCmNvbG5hbWVzKFB0dWhfY291bnRzX0dPKVtjb2xuYW1lcyhQdHVoX2NvdW50c19HTykgPT0gIkdlbmUuT250b2xvZ3kuLmJpb2xvZ2ljYWwucHJvY2Vzcy4iXSA8LSAiQmlvbG9naWNhbF9Qcm9jZXNzIgoKIyBTZXBhcmF0ZSB0aGUgYEJpb2xvZ2ljYWxfUHJvY2Vzc2AgY29sdW1uIGludG8gaW5kaXZpZHVhbCBiaW9sb2dpY2FsIHByb2Nlc3NlcwpkYXRhX3NlcGFyYXRlZCA8LSB1bmxpc3Qoc3Ryc3BsaXQoUHR1aF9jb3VudHNfR08kQmlvbG9naWNhbF9Qcm9jZXNzLCBzcGxpdCA9ICI7IikpCgojIFRyaW0gd2hpdGVzcGFjZSBmcm9tIHRoZSBiaW9sb2dpY2FsIHByb2Nlc3NlcwpkYXRhX3NlcGFyYXRlZCA8LSBnc3ViKCJeXFxzK3xcXHMrJCIsICIiLCBkYXRhX3NlcGFyYXRlZCkKCiMgQ291bnQgdGhlIG9jY3VycmVuY2VzIG9mIGVhY2ggYmlvbG9naWNhbCBwcm9jZXNzCnByb2Nlc3NfY291bnRzIDwtIHRhYmxlKGRhdGFfc2VwYXJhdGVkKQpwcm9jZXNzX2NvdW50cyA8LSBkYXRhLmZyYW1lKEJpb2xvZ2ljYWxfUHJvY2VzcyA9IG5hbWVzKHByb2Nlc3NfY291bnRzKSwgQ291bnQgPSBhcy5pbnRlZ2VyKHByb2Nlc3NfY291bnRzKSkKcHJvY2Vzc19jb3VudHMgPC0gcHJvY2Vzc19jb3VudHNbb3JkZXIoLXByb2Nlc3NfY291bnRzJENvdW50KSwgXQoKIyBTZWxlY3QgdGhlIDIwIG1vc3QgcHJlZG9taW5hbnQgYmlvbG9naWNhbCBwcm9jZXNzZXMKdG9wXzIwX3Byb2Nlc3NlcyA8LSBwcm9jZXNzX2NvdW50c1sxOjIwLCBdCgojIENyZWF0ZSBhIGNvbG9yIHBhbGV0dGUgZm9yIHRoZSBiYXJzCmJhcl9jb2xvcnMgPC0gcmFpbmJvdyhucm93KHRvcF8yMF9wcm9jZXNzZXMpKQoKIyBDcmVhdGUgYSBzdGFnZ2VyZWQgdmVydGljYWwgYmFyIHBsb3Qgd2l0aCBkaWZmZXJlbnQgY29sb3JzIGZvciBlYWNoIGJhcgpiYXJwbG90KHRvcF8yMF9wcm9jZXNzZXMkQ291bnQsIG5hbWVzLmFyZyA9IHJlcCgiIiwgbnJvdyh0b3BfMjBfcHJvY2Vzc2VzKSksIGNvbCA9IGJhcl9jb2xvcnMsCiAgICAgICAgeWxpbSA9IGMoMCwgbWF4KHRvcF8yMF9wcm9jZXNzZXMkQ291bnQpICogMS4yNSksCiAgICAgICAgbWFpbiA9ICJPY2N1cnJlbmNlcyBvZiB0aGUgMjAgTW9zdCBQcmVkb21pbmFudCBCaW9sb2dpY2FsIFByb2Nlc3NlcyIsIHhsYWIgPSAiQmlvbG9naWNhbCBQcm9jZXNzIiwgeWxhYiA9ICJDb3VudCIpCgoKIyBDcmVhdGUgYSBzZXBhcmF0ZSBwbG90IGZvciB0aGUgbGVnZW5kCnBuZygiLi4vb3V0cHV0LzAzLVB0dWgtUk5BLXN1bW1hcnkvR09sZWdlbmQucG5nIiwgd2lkdGggPSA4MDAsIGhlaWdodCA9IDYwMCkKcGFyKG1hciA9IGMoMCwgMCwgMCwgMCkpCnBsb3QubmV3KCkKbGVnZW5kKCJjZW50ZXIiLCBsZWdlbmQgPSB0b3BfMjBfcHJvY2Vzc2VzJEJpb2xvZ2ljYWxfUHJvY2VzcywgZmlsbCA9IGJhcl9jb2xvcnMsIGNleCA9IDEsIHRpdGxlID0gIkJpb2xvZ2ljYWwgUHJvY2Vzc2VzIikKZGV2Lm9mZigpCmBgYAoKYGBge3IgZ28tbGVnZW5kLCBldmFsPVRSVUUsIGZpZy53aWR0aCA9IDEwMCAsZmlnLmhlaWdodCA9IDEwMH0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi4uL291dHB1dC8wMy1QdHVoLVJOQS1zdW1tYXJ5L0dPbGVnZW5kLnBuZyIpCmBgYAoKYGBge3IgcmVtb3ZlLWxlZ2VuZC1maWxlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CnJtIC4uL291dHB1dC8wMy1QdHVoLVJOQS1zdW1tYXJ5L0dPbGVnZW5kLnBuZwpgYGA=