Gene expression summary for Pocillopora tuahiniensis sRNA-seq data.

  • trimmed reads generated in deep-dive project

  • Reads aligned to Pocillopora meandrina transcriptome, details here

0.0.1 Install and load packages

library(tidyverse)
library(ggplot2)
library(reshape2)
library(pheatmap)
library(RColorBrewer)

1 sRNA

1.1 Load count data

Load in the sRNA count matrix generated using ShortStack. Keep in mind this data includes counts of all sRNAs, not just miRNAs. Also note, while we have 5 samples from which RNA was sequenced, only 3 of those were sequenced for sRNA in P. evermanni.

# Read in sRNA counts data
Ptuh_counts_sRNA_data_OG <- read_delim("../../../deep-dive/F-Pmea/output/13.2.1-Pmea-sRNAseq-ShortStack-31bp-fastp-merged-cnidarian_miRBase/ShortStack_out/Counts.txt", delim="\t") 
head(Ptuh_counts_sRNA_data_OG)
# A tibble: 6 × 8
  Coords               Name  MIRNA sRNA-POC-47-S1-TP2-f…¹ sRNA-POC-48-S1-TP2-f…²
  <chr>                <chr> <chr>                  <dbl>                  <dbl>
1 Pocillopora_meandri… Clus… N                       1568                   1337
2 Pocillopora_meandri… Clus… N                         24                     51
3 Pocillopora_meandri… Clus… N                        244                    526
4 Pocillopora_meandri… Clus… N                        166                    167
5 Pocillopora_meandri… Clus… N                          4                     16
6 Pocillopora_meandri… Clus… N                         35                     37
# ℹ abbreviated names: ¹​`sRNA-POC-47-S1-TP2-fastp-adapters-polyG-31bp-merged`,
#   ²​`sRNA-POC-48-S1-TP2-fastp-adapters-polyG-31bp-merged`
# ℹ 3 more variables:
#   `sRNA-POC-50-S1-TP2-fastp-adapters-polyG-31bp-merged` <dbl>,
#   `sRNA-POC-53-S1-TP2-fastp-adapters-polyG-31bp-merged` <dbl>,
#   `sRNA-POC-57-S1-TP2-fastp-adapters-polyG-31bp-merged` <dbl>

1.2 Count data munging

Ptuh_counts_sRNA <- Ptuh_counts_sRNA_data_OG

# Remove excess portions of sample column names to just "sample###"
colnames(Ptuh_counts_sRNA) <- sub("-S1-TP2-fastp-adapters-polyG-31bp-merged", "", colnames(Ptuh_counts_sRNA))
colnames(Ptuh_counts_sRNA) <- sub("sRNA-POC-", "sample", colnames(Ptuh_counts_sRNA))

# Keep just the counts and cluster names
Ptuh_counts_sRNA <- Ptuh_counts_sRNA %>% select("sample47", "sample48", "sample50", "sample53", "sample57","Name")

# I'm not going to be doing any removal of low-count sRNAs for now

# Make the cluster names our new row names
Ptuh_counts_sRNA <- Ptuh_counts_sRNA %>% column_to_rownames(var = "Name")

head(Ptuh_counts_sRNA)
          sample47 sample48 sample50 sample53 sample57
Cluster_1     1568     1337     1563     3006     3339
Cluster_2       24       51       67       54       91
Cluster_3      244      526      433      397      949
Cluster_4      166      167      273      318      333
Cluster_5        4       16       26       66       73
Cluster_6       35       37       33       58      123

1.3 Expression levels

Plot histograms of the expression levels in each sample

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

# Plot the expression level histograms for each sample
ggplot(Ptuh_counts_sRNA_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()

1.4 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_sRNA)

# 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 unique sRNAs 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_sRNA > 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 miRNA

2.1 Load miRNA metadata

The ShortStack output Results.txt includes all clusters of sRNA reads, including those not annotated as valid miRNAs. Now that we’ve looked at all the sRNAs a bit, let’s focus in on those classified as miRNAs.

# Join with full metadata sheet, which only contains valid miRNAs
Ptuh_metadata_miRNA <- read_csv("../../../deep-dive/DEF-cross-species/output/10-shortRNA-ShortStack-comparison/Ptuh_results_mature_named.csv") 

Ptuh_counts_sRNA <- rownames_to_column(Ptuh_counts_sRNA, var = "Name")

Ptuh_counts_miRNA <- left_join(Ptuh_metadata_miRNA, Ptuh_counts_sRNA, by = c("Name" = "Name"))

# Keep just the counts and given miRNA names (e.g., based on match to previously described miRNA)
Ptuh_counts_miRNA <- Ptuh_counts_miRNA %>% select("sample47", "sample48", "sample50", "sample53", "sample57","given_miRNA_name")

# Make the miRNA names our new row names
Ptuh_counts_miRNA <- Ptuh_counts_miRNA %>% column_to_rownames(var = "given_miRNA_name")

head(Ptuh_counts_miRNA)
                  sample47 sample48 sample50 sample53 sample57
ptuh-mir-novel-32   142599   101636   141199    84760    52034
ptuh-mir-novel-1      2201      960     1596      944      621
ptuh-mir-novel-2       824      527      640      641      337
ptuh-mir-novel-7        74       26       58       94       15
ptuh-mir-novel-3      3949     1963     2559     2213      678
ptuh-mir-novel-4      6841     6398     8987     7176     1555

2.2 Expression levels

Plot histograms of the miRNA expression levels in each sample

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

# Plot the expression level histograms for each sample
ggplot(Ptuh_counts_miRNA_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 = "miRNA Expression Level Histogram for Each Sample",
       x = "Expression Level (Counts)",
       y = "Frequency") +
  theme_minimal()

2.3 miRNA counts

First let’s check the total number of miRNAs 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_miRNA <- colSums(Ptuh_counts_miRNA)

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

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

Huh, it’s interesting that samples 47, 48, and 50 had lower total sRNA transcript counts but higher total miRNA counts.

Now let’s check the number of unique miRNAs 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_miRNA <- colSums(Ptuh_counts_miRNA > 0)

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

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

2.4 Heatmap

heat_colors <- rev(brewer.pal(12, "RdYlBu"))

pheatmap(Ptuh_counts_miRNA,
         cluster_rows = TRUE,
         cluster_cols = TRUE,
         show_rownames = TRUE,
         show_colnames = TRUE,
         color = heat_colors,
         fontsize_row = 8,
         fontsize_col = 8)

Well… there’s like 2 miRNAs with much higher expression than the others, which is making visualizing relative differences difficult. Let’s redo the heatmap, normalizing each row to view relative difference in expression between samples (scale='row')

pheatmap(Ptuh_counts_miRNA,
         cluster_rows = TRUE,
         cluster_cols = TRUE,
         show_rownames = TRUE,
         show_colnames = TRUE,
         scale = 'row',
         color = heat_colors,
         fontsize_row = 8,
         fontsize_col = 8)

LS0tCnRpdGxlOiAiMDMuMS1QdHVoLXNSTkEtc3VtbWFyeSIKYXV0aG9yOiAiS2F0aGxlZW4gRHVya2luIgpkYXRlOiAiMjAyNC0wOS0wNiIKYWx3YXlzX2FsbG93X2h0bWw6IHRydWUKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGh0bWxfcHJldmlldzogdHJ1ZSAKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBUUlVFLCAgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKR2VuZSBleHByZXNzaW9uIHN1bW1hcnkgZm9yICpQb2NpbGxvcG9yYSB0dWFoaW5pZW5zaXMqIHNSTkEtc2VxIGRhdGEuCgotICAgdHJpbW1lZCByZWFkcyBnZW5lcmF0ZWQgaW4gYGRlZXAtZGl2ZWAgcHJvamVjdAoKLSAgIFJlYWRzIGFsaWduZWQgdG8gKlBvY2lsbG9wb3JhIG1lYW5kcmluYSogdHJhbnNjcmlwdG9tZSwgZGV0YWlscyBbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9GLVB0dWgvY29kZS8xMi1QdHVoLVJOQXNlcS1rYWxsaXN0by5tZCkKCgojIyMgSW5zdGFsbCBhbmQgbG9hZCBwYWNrYWdlcwoKYGBge3IgbG9hZF9saWJyYXJpZXMsIGlubGN1ZGUgPSBUUlVFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKYGBgCgoKIyBzUk5BCgojIyBMb2FkIGNvdW50IGRhdGEKCkxvYWQgaW4gdGhlIHNSTkEgY291bnQgbWF0cml4IGdlbmVyYXRlZCB1c2luZyBTaG9ydFN0YWNrLiBLZWVwIGluIG1pbmQgdGhpcyBkYXRhIGluY2x1ZGVzIGNvdW50cyBvZiBhbGwgc1JOQXMsIG5vdCBqdXN0IG1pUk5Bcy4gQWxzbyBub3RlLCB3aGlsZSB3ZSBoYXZlIDUgc2FtcGxlcyBmcm9tIHdoaWNoIFJOQSB3YXMgc2VxdWVuY2VkLCBvbmx5IDMgb2YgdGhvc2Ugd2VyZSBzZXF1ZW5jZWQgZm9yIHNSTkEgaW4gUC4gZXZlcm1hbm5pLgoKYGBge3IgbG9hZC1zUk5BLWNvdW50c30KIyBSZWFkIGluIHNSTkEgY291bnRzIGRhdGEKUHR1aF9jb3VudHNfc1JOQV9kYXRhX09HIDwtIHJlYWRfZGVsaW0oIi4uLy4uLy4uL2RlZXAtZGl2ZS9GLVBtZWEvb3V0cHV0LzEzLjIuMS1QbWVhLXNSTkFzZXEtU2hvcnRTdGFjay0zMWJwLWZhc3RwLW1lcmdlZC1jbmlkYXJpYW5fbWlSQmFzZS9TaG9ydFN0YWNrX291dC9Db3VudHMudHh0IiwgZGVsaW09Ilx0IikgCmhlYWQoUHR1aF9jb3VudHNfc1JOQV9kYXRhX09HKQpgYGAKCiMjIENvdW50IGRhdGEgbXVuZ2luZwoKYGBge3Igc1JOQS1jb3VudC1kYXRhLW11bmdpbmd9ClB0dWhfY291bnRzX3NSTkEgPC0gUHR1aF9jb3VudHNfc1JOQV9kYXRhX09HCgojIFJlbW92ZSBleGNlc3MgcG9ydGlvbnMgb2Ygc2FtcGxlIGNvbHVtbiBuYW1lcyB0byBqdXN0ICJzYW1wbGUjIyMiCmNvbG5hbWVzKFB0dWhfY291bnRzX3NSTkEpIDwtIHN1YigiLVMxLVRQMi1mYXN0cC1hZGFwdGVycy1wb2x5Ry0zMWJwLW1lcmdlZCIsICIiLCBjb2xuYW1lcyhQdHVoX2NvdW50c19zUk5BKSkKY29sbmFtZXMoUHR1aF9jb3VudHNfc1JOQSkgPC0gc3ViKCJzUk5BLVBPQy0iLCAic2FtcGxlIiwgY29sbmFtZXMoUHR1aF9jb3VudHNfc1JOQSkpCgojIEtlZXAganVzdCB0aGUgY291bnRzIGFuZCBjbHVzdGVyIG5hbWVzClB0dWhfY291bnRzX3NSTkEgPC0gUHR1aF9jb3VudHNfc1JOQSAlPiUgc2VsZWN0KCJzYW1wbGU0NyIsICJzYW1wbGU0OCIsICJzYW1wbGU1MCIsICJzYW1wbGU1MyIsICJzYW1wbGU1NyIsIk5hbWUiKQoKIyBJJ20gbm90IGdvaW5nIHRvIGJlIGRvaW5nIGFueSByZW1vdmFsIG9mIGxvdy1jb3VudCBzUk5BcyBmb3Igbm93CgojIE1ha2UgdGhlIGNsdXN0ZXIgbmFtZXMgb3VyIG5ldyByb3cgbmFtZXMKUHR1aF9jb3VudHNfc1JOQSA8LSBQdHVoX2NvdW50c19zUk5BICU+JSBjb2x1bW5fdG9fcm93bmFtZXModmFyID0gIk5hbWUiKQoKaGVhZChQdHVoX2NvdW50c19zUk5BKQpgYGAKCgojIyBFeHByZXNzaW9uIGxldmVscwoKUGxvdCBoaXN0b2dyYW1zIG9mIHRoZSBleHByZXNzaW9uIGxldmVscyBpbiBlYWNoIHNhbXBsZQoKYGBge3IgZXhwcmVzc2lvbi1sZXZlbC1oaXN0b2dyYW1zfQojIE1lbHQgdGhlIGNvdW50IG1hdHJpeCBpbnRvIGxvbmcgZm9ybWF0ClB0dWhfY291bnRzX3NSTkFfbWVsdGVkIDwtIG1lbHQoUHR1aF9jb3VudHNfc1JOQSwgdmFyaWFibGUubmFtZSA9ICJzYW1wbGUiLCB2YWx1ZS5uYW1lID0gImNvdW50cyIpCgojIFBsb3QgdGhlIGV4cHJlc3Npb24gbGV2ZWwgaGlzdG9ncmFtcyBmb3IgZWFjaCBzYW1wbGUKZ2dwbG90KFB0dWhfY291bnRzX3NSTkFfbWVsdGVkLCBhZXMoeCA9IGNvdW50cykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAiIzdBMjA0OCIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfbG9nMTAoKSArICAjIE9wdGlvbmFsOiBMb2ctdHJhbnNmb3JtIHRoZSB4LWF4aXMgZm9yIGJldHRlciB2aXN1YWxpemF0aW9uCiAgZmFjZXRfd3JhcCh+c2FtcGxlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnModGl0bGUgPSAiR2VuZSBFeHByZXNzaW9uIExldmVsIEhpc3RvZ3JhbSBmb3IgRWFjaCBTYW1wbGUiLAogICAgICAgeCA9ICJFeHByZXNzaW9uIExldmVsIChDb3VudHMpIiwKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIFRyYW5zY3JpcHQgY291bnRzCgpGaXJzdCBsZXQncyBjaGVjayB0aGUgdG90YWwgbnVtYmVyIG9mIHRyYW5zY3JpcHRzIGluIGVhY2ggc2FtcGxlIC0tIGtlZXAgaW4gbWluZCB0aGlzIGV4cHJlc3Npb24gZGF0YSBoYXMgKm5vdCogYmVlbiBub3JtYWxpemVkIHlldCwgc28gdGhlcmUgbWF5IGJlIGRpZmZlcmVudCB0b3RhbHMgZm9yIGVhY2ggc2FtcGxlCmBgYHtyIHRyYW5zY3JpcHQtY291bnRzLXBsb3R9CiMgQ2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2YgdHJhbnNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlCnRvdGFsX3RyYW5zY3JpcHRzIDwtIGNvbFN1bXMoUHR1aF9jb3VudHNfc1JOQSkKCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgcGxvdHRpbmcKdG90YWxfdHJhbnNjcmlwdHNfZGYgPC0gZGF0YS5mcmFtZShzYW1wbGUgPSBuYW1lcyh0b3RhbF90cmFuc2NyaXB0cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxzID0gdG90YWxfdHJhbnNjcmlwdHMpCgojIFBsb3QgdGhlIHRvdGFsIG51bWJlciBvZiB0cmFuc2NyaXB0cyBmb3IgZWFjaCBzYW1wbGUKZ2dwbG90KHRvdGFsX3RyYW5zY3JpcHRzX2RmLCBhZXMoeCA9IHNhbXBsZSwgeSA9IHRvdGFscykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICIjN0EyMDQ4IiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBOdW1iZXIgb2YgVHJhbnNjcmlwdHMgcGVyIFNhbXBsZSIsCiAgICAgICB4ID0gIlNhbXBsZSIsCiAgICAgICB5ID0gIlRvdGFsIFRyYW5zY3JpcHRzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIHJlYWRhYmlsaXR5CmBgYAoKTm93IGxldCdzIGNoZWNrIHRoZSBudW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIGluIGVhY2ggc2FtcGxlIC0tIHRoYXQgaXMsIGhvdyBtYW55IHVuaXF1ZSBzUk5BcyBhcmUgZXhwcmVzc2VkIGluIGVhY2ggc2FtcGxlPyBUaGlzIHNob3VsZCBiZSBwcmV0dHkgbXVjaCB0aGUgc2FtZSBhY3Jvc3Mgc2FtcGxlcywgZXZlbiB3aXRob3V0IG5vcm1hbGl6YXRpb24uCgpgYGB7ciB0b3RhbC11bmlxdWUtdHJhbnNjcmlwdHMtcGxvdH0KIyBDYWxjdWxhdGUgdGhlIG51bWJlciBvZiB1bmlxdWUgdHJhbnNjcmlwdHMgKG5vbi16ZXJvIGNvdW50cykgZm9yIGVhY2ggc2FtcGxlCnVuaXF1ZV90cmFuc2NyaXB0cyA8LSBjb2xTdW1zKFB0dWhfY291bnRzX3NSTkEgPiAwKQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBwbG90dGluZwp1bmlxdWVfdHJhbnNjcmlwdHNfZGYgPC0gZGF0YS5mcmFtZShzYW1wbGUgPSBuYW1lcyh1bmlxdWVfdHJhbnNjcmlwdHMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmlxdWVzID0gdW5pcXVlX3RyYW5zY3JpcHRzKQoKIyBQbG90IHRoZSB0b3RhbCBudW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIGZvciBlYWNoIHNhbXBsZQpnZ3Bsb3QodW5pcXVlX3RyYW5zY3JpcHRzX2RmLCBhZXMoeCA9IHNhbXBsZSwgeSA9IHVuaXF1ZXMpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiIzdBMjA0OCIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnModGl0bGUgPSAiVG90YWwgTnVtYmVyIG9mIFVuaXF1ZSBFeHByZXNzZWQgVHJhbnNjcmlwdHMgcGVyIFNhbXBsZSIsCiAgICAgICB4ID0gIlNhbXBsZSIsCiAgICAgICB5ID0gIlVuaXF1ZSBUcmFuc2NyaXB0cyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciByZWFkYWJpbGl0eQpgYGAKICAgCgojIG1pUk5BCgojIyBMb2FkIG1pUk5BIG1ldGFkYXRhCgpUaGUgU2hvcnRTdGFjayBvdXRwdXQgUmVzdWx0cy50eHQgaW5jbHVkZXMgYWxsIGNsdXN0ZXJzIG9mIHNSTkEgcmVhZHMsIGluY2x1ZGluZyB0aG9zZSBub3QgYW5ub3RhdGVkIGFzIHZhbGlkIG1pUk5Bcy4gTm93IHRoYXQgd2UndmUgbG9va2VkIGF0IGFsbCB0aGUgc1JOQXMgYSBiaXQsIGxldCdzIGZvY3VzIGluIG9uIHRob3NlIGNsYXNzaWZpZWQgYXMgbWlSTkFzLgoKYGBge3IgbWlSTkEtY291bnQtZGF0YS1tdW5naW5nfQoKIyBKb2luIHdpdGggZnVsbCBtZXRhZGF0YSBzaGVldCwgd2hpY2ggb25seSBjb250YWlucyB2YWxpZCBtaVJOQXMKUHR1aF9tZXRhZGF0YV9taVJOQSA8LSByZWFkX2NzdigiLi4vLi4vLi4vZGVlcC1kaXZlL0RFRi1jcm9zcy1zcGVjaWVzL291dHB1dC8xMC1zaG9ydFJOQS1TaG9ydFN0YWNrLWNvbXBhcmlzb24vUHR1aF9yZXN1bHRzX21hdHVyZV9uYW1lZC5jc3YiKSAKClB0dWhfY291bnRzX3NSTkEgPC0gcm93bmFtZXNfdG9fY29sdW1uKFB0dWhfY291bnRzX3NSTkEsIHZhciA9ICJOYW1lIikKClB0dWhfY291bnRzX21pUk5BIDwtIGxlZnRfam9pbihQdHVoX21ldGFkYXRhX21pUk5BLCBQdHVoX2NvdW50c19zUk5BLCBieSA9IGMoIk5hbWUiID0gIk5hbWUiKSkKCiMgS2VlcCBqdXN0IHRoZSBjb3VudHMgYW5kIGdpdmVuIG1pUk5BIG5hbWVzIChlLmcuLCBiYXNlZCBvbiBtYXRjaCB0byBwcmV2aW91c2x5IGRlc2NyaWJlZCBtaVJOQSkKUHR1aF9jb3VudHNfbWlSTkEgPC0gUHR1aF9jb3VudHNfbWlSTkEgJT4lIHNlbGVjdCgic2FtcGxlNDciLCAic2FtcGxlNDgiLCAic2FtcGxlNTAiLCAic2FtcGxlNTMiLCAic2FtcGxlNTciLCJnaXZlbl9taVJOQV9uYW1lIikKCiMgTWFrZSB0aGUgbWlSTkEgbmFtZXMgb3VyIG5ldyByb3cgbmFtZXMKUHR1aF9jb3VudHNfbWlSTkEgPC0gUHR1aF9jb3VudHNfbWlSTkEgJT4lIGNvbHVtbl90b19yb3duYW1lcyh2YXIgPSAiZ2l2ZW5fbWlSTkFfbmFtZSIpCgpoZWFkKFB0dWhfY291bnRzX21pUk5BKQpgYGAKCiMjIEV4cHJlc3Npb24gbGV2ZWxzCgpQbG90IGhpc3RvZ3JhbXMgb2YgdGhlIG1pUk5BIGV4cHJlc3Npb24gbGV2ZWxzIGluIGVhY2ggc2FtcGxlCgpgYGB7ciBtaVJOQS1leHByZXNzaW9uLWxldmVsLWhpc3RvZ3JhbXN9CiMgTWVsdCB0aGUgY291bnQgbWF0cml4IGludG8gbG9uZyBmb3JtYXQKUHR1aF9jb3VudHNfbWlSTkFfbWVsdGVkIDwtIG1lbHQoUHR1aF9jb3VudHNfbWlSTkEsIHZhcmlhYmxlLm5hbWUgPSAic2FtcGxlIiwgdmFsdWUubmFtZSA9ICJjb3VudHMiKQoKIyBQbG90IHRoZSBleHByZXNzaW9uIGxldmVsIGhpc3RvZ3JhbXMgZm9yIGVhY2ggc2FtcGxlCmdncGxvdChQdHVoX2NvdW50c19taVJOQV9tZWx0ZWQsIGFlcyh4ID0gY291bnRzKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSwgZmlsbCA9ICIjN0EyMDQ4IiwgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfeF9sb2cxMCgpICsgICMgT3B0aW9uYWw6IExvZy10cmFuc2Zvcm0gdGhlIHgtYXhpcyBmb3IgYmV0dGVyIHZpc3VhbGl6YXRpb24KICBmYWNldF93cmFwKH5zYW1wbGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh0aXRsZSA9ICJtaVJOQSBFeHByZXNzaW9uIExldmVsIEhpc3RvZ3JhbSBmb3IgRWFjaCBTYW1wbGUiLAogICAgICAgeCA9ICJFeHByZXNzaW9uIExldmVsIChDb3VudHMpIiwKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIG1pUk5BIGNvdW50cwoKRmlyc3QgbGV0J3MgY2hlY2sgdGhlIHRvdGFsIG51bWJlciBvZiBtaVJOQXMgaW4gZWFjaCBzYW1wbGUgLS0ga2VlcCBpbiBtaW5kIHRoaXMgZXhwcmVzc2lvbiBkYXRhIGhhcyAqbm90KiBiZWVuIG5vcm1hbGl6ZWQgeWV0LCBzbyB0aGVyZSBtYXkgYmUgZGlmZmVyZW50IHRvdGFscyBmb3IgZWFjaCBzYW1wbGUKYGBge3IgbWlSTkEtY291bnRzLXBsb3R9CiMgQ2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2YgdHJhbnNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlCnRvdGFsX21pUk5BIDwtIGNvbFN1bXMoUHR1aF9jb3VudHNfbWlSTkEpCgojIENyZWF0ZSBhIGRhdGEgZnJhbWUgZm9yIHBsb3R0aW5nCnRvdGFsX21pUk5BX2RmIDwtIGRhdGEuZnJhbWUoc2FtcGxlID0gbmFtZXModG90YWxfbWlSTkEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFscyA9IHRvdGFsX21pUk5BKQoKIyBQbG90IHRoZSB0b3RhbCBudW1iZXIgb2YgdHJhbnNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlCmdncGxvdCh0b3RhbF9taVJOQV9kZiwgYWVzKHggPSBzYW1wbGUsIHkgPSB0b3RhbHMpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiIzdBMjA0OCIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnModGl0bGUgPSAiVG90YWwgTnVtYmVyIG9mIG1pUk5BcyBwZXIgU2FtcGxlIiwKICAgICAgIHggPSAiU2FtcGxlIiwKICAgICAgIHkgPSAiVG90YWwgbWlSTkFzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIHJlYWRhYmlsaXR5CmBgYApIdWgsIGl0J3MgaW50ZXJlc3RpbmcgdGhhdCBzYW1wbGVzIDQ3LCA0OCwgYW5kIDUwIGhhZCBsb3dlciB0b3RhbCBzUk5BIHRyYW5zY3JpcHQgY291bnRzIGJ1dCBoaWdoZXIgdG90YWwgbWlSTkEgY291bnRzLgoKCk5vdyBsZXQncyBjaGVjayB0aGUgbnVtYmVyIG9mIHVuaXF1ZSBtaVJOQXMgaW4gZWFjaCBzYW1wbGUgLS0gVGhpcyBzaG91bGQgYmUgcHJldHR5IG11Y2ggdGhlIHNhbWUgYWNyb3NzIHNhbXBsZXMsIGV2ZW4gd2l0aG91dCBub3JtYWxpemF0aW9uLgoKYGBge3IgdG90YWwtdW5pcXVlLW1pUk5BLXBsb3R9CiMgQ2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIChub24temVybyBjb3VudHMpIGZvciBlYWNoIHNhbXBsZQp1bmlxdWVfbWlSTkEgPC0gY29sU3VtcyhQdHVoX2NvdW50c19taVJOQSA+IDApCgojIENyZWF0ZSBhIGRhdGEgZnJhbWUgZm9yIHBsb3R0aW5nCnVuaXF1ZV9taVJOQV9kZiA8LSBkYXRhLmZyYW1lKHNhbXBsZSA9IG5hbWVzKHVuaXF1ZV9taVJOQSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXF1ZXMgPSB1bmlxdWVfbWlSTkEpCgojIFBsb3QgdGhlIHRvdGFsIG51bWJlciBvZiB1bmlxdWUgdHJhbnNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlCmdncGxvdCh1bmlxdWVfbWlSTkFfZGYsIGFlcyh4ID0gc2FtcGxlLCB5ID0gdW5pcXVlcykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICIjN0EyMDQ4IiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBOdW1iZXIgb2YgVW5pcXVlIEV4cHJlc3NlZCBtaVJOQXMgcGVyIFNhbXBsZSIsCiAgICAgICB4ID0gIlNhbXBsZSIsCiAgICAgICB5ID0gIlVuaXF1ZSBtaVJOQSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciByZWFkYWJpbGl0eQpgYGAKCiMjIEhlYXRtYXAKCmBgYHtyIG1pUk5BLWhlYXRtYXB9CmhlYXRfY29sb3JzIDwtIHJldihicmV3ZXIucGFsKDEyLCAiUmRZbEJ1IikpCgpwaGVhdG1hcChQdHVoX2NvdW50c19taVJOQSwKICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVFJVRSwKICAgICAgICAgc2hvd19yb3duYW1lcyA9IFRSVUUsCiAgICAgICAgIHNob3dfY29sbmFtZXMgPSBUUlVFLAogICAgICAgICBjb2xvciA9IGhlYXRfY29sb3JzLAogICAgICAgICBmb250c2l6ZV9yb3cgPSA4LAogICAgICAgICBmb250c2l6ZV9jb2wgPSA4KQpgYGAKV2VsbC4uLiB0aGVyZSdzIGxpa2UgMiBtaVJOQXMgd2l0aCBtdWNoIGhpZ2hlciBleHByZXNzaW9uIHRoYW4gdGhlIG90aGVycywgd2hpY2ggaXMgbWFraW5nIHZpc3VhbGl6aW5nIHJlbGF0aXZlIGRpZmZlcmVuY2VzIGRpZmZpY3VsdC4gTGV0J3MgcmVkbyB0aGUgaGVhdG1hcCwgbm9ybWFsaXppbmcgZWFjaCByb3cgdG8gdmlldyByZWxhdGl2ZSBkaWZmZXJlbmNlIGluIGV4cHJlc3Npb24gYmV0d2VlbiBzYW1wbGVzIChgc2NhbGU9J3JvdydgKQoKYGBge3IgbWlSTkEtaGVhdG1hcC1yb3dzY2FsZX0KcGhlYXRtYXAoUHR1aF9jb3VudHNfbWlSTkEsCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsCiAgICAgICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsCiAgICAgICAgIHNob3dfcm93bmFtZXMgPSBUUlVFLAogICAgICAgICBzaG93X2NvbG5hbWVzID0gVFJVRSwKICAgICAgICAgc2NhbGUgPSAncm93JywKICAgICAgICAgY29sb3IgPSBoZWF0X2NvbG9ycywKICAgICAgICAgZm9udHNpemVfcm93ID0gOCwKICAgICAgICAgZm9udHNpemVfY29sID0gOCkKYGBg