sRNA
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
Peve_counts_sRNA_data_OG <- read_delim("../../../deep-dive/E-Peve/output/08.2-Peve-sRNAseq-ShortStack-31bp-fastp-merged/ShortStack_out/Counts.txt", delim="\t")
head(Peve_counts_sRNA_data_OG)
# A tibble: 6 × 6
Coords Name MIRNA POR-73-S1-TP2-fastp-…¹ POR-79-S1-TP2-fastp-…²
<chr> <chr> <chr> <dbl> <dbl>
1 Porites_evermani_sc… Clus… N 0 71
2 Porites_evermani_sc… Clus… N 58 0
3 Porites_evermani_sc… Clus… N 12 12
4 Porites_evermani_sc… Clus… N 135 30
5 Porites_evermani_sc… Clus… N 113 35
6 Porites_evermani_sc… Clus… N 5 35
# ℹ abbreviated names: ¹​`POR-73-S1-TP2-fastp-adapters-polyG-31bp-merged`,
# ²​`POR-79-S1-TP2-fastp-adapters-polyG-31bp-merged`
# ℹ 1 more variable: `POR-82-S1-TP2-fastp-adapters-polyG-31bp-merged` <dbl>
Count data munging
Peve_counts_sRNA <- Peve_counts_sRNA_data_OG
# Remove excess portions of sample column names to just "sample###"
colnames(Peve_counts_sRNA) <- sub("-S1-TP2-fastp-adapters-polyG-31bp-merged", "", colnames(Peve_counts_sRNA))
colnames(Peve_counts_sRNA) <- sub("POR-", "sample", colnames(Peve_counts_sRNA))
# Keep just the counts and cluster names
Peve_counts_sRNA <- Peve_counts_sRNA %>% select("sample73", "sample79", "sample82", "Name")
# I'm not going to be doing any removal of low-count sRNAs for now
# Make the cluster names our new row names
Peve_counts_sRNA <- Peve_counts_sRNA %>% column_to_rownames(var = "Name")
head(Peve_counts_sRNA)
sample73 sample79 sample82
Cluster_1 0 71 17
Cluster_2 58 0 0
Cluster_3 12 12 26
Cluster_4 135 30 10
Cluster_5 113 35 21
Cluster_6 5 35 129
Expression levels
Plot histograms of the expression levels in each sample
# Melt the count matrix into long format
Peve_counts_sRNA_melted <- melt(Peve_counts_sRNA, variable.name = "sample", value.name = "counts")
# Plot the expression level histograms for each sample
ggplot(Peve_counts_sRNA_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()
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_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 = "#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 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(Peve_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 = "#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
miRNA
Expression levels
Plot histograms of the miRNA expression levels in each sample
# Melt the count matrix into long format
Peve_counts_miRNA_melted <- melt(Peve_counts_miRNA, variable.name = "sample", value.name = "counts")
# Plot the expression level histograms for each sample
ggplot(Peve_counts_miRNA_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()
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(Peve_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 = "#1E2761", 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
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(Peve_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 = "#1E2761", 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
Heatmap
heat_colors <- rev(brewer.pal(12, "RdYlBu"))
pheatmap(Peve_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 3 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(Peve_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)
LS0tCnRpdGxlOiAiMDMuMS1QZXZlLXNSTkEtc3VtbWFyeSIKYXV0aG9yOiAiS2F0aGxlZW4gRHVya2luIgpkYXRlOiAiMjAyNC0wOS0wNSIKYWx3YXlzX2FsbG93X2h0bWw6IHRydWUKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGh0bWxfcHJldmlldzogdHJ1ZSAKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBUUlVFLCAgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKR2VuZSBleHByZXNzaW9uIHN1bW1hcnkgZm9yICpQb3JpdGVzIGV2ZXJtYW5uaSogc1JOQS1zZXEgZGF0YS4KCi0gICB0cmltbWVkIHJlYWRzIGdlbmVyYXRlZCBpbiBgZGVlcC1kaXZlYCBwcm9qZWN0CgotICAgUmVhZHMgYWxpZ25lZCB0byAqUG9yaXRlcyBldmVybWFubmkqIHRyYW5zY3JpcHRvbWUsIGRldGFpbHMgW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS91cm9sLWU1L2RlZXAtZGl2ZS9ibG9iL21haW4vRS1QZXZlL2NvZGUvMTItUGV2ZS1STkFzZXEta2FsbGlzdG8ubWQpCgojIyMgSW5zdGFsbCBhbmQgbG9hZCBwYWNrYWdlcwoKYGBge3IgbG9hZF9saWJyYXJpZXMsIGlubGN1ZGUgPSBUUlVFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKYGBgCgoKIyBzUk5BCgojIyBMb2FkIGNvdW50IGRhdGEKCkxvYWQgaW4gdGhlIHNSTkEgY291bnQgbWF0cml4IGdlbmVyYXRlZCB1c2luZyBTaG9ydFN0YWNrLiBLZWVwIGluIG1pbmQgdGhpcyBkYXRhIGluY2x1ZGVzIGNvdW50cyBvZiBhbGwgc1JOQXMsIG5vdCBqdXN0IG1pUk5Bcy4gQWxzbyBub3RlLCB3aGlsZSB3ZSBoYXZlIDUgc2FtcGxlcyBmcm9tIHdoaWNoIFJOQSB3YXMgc2VxdWVuY2VkLCBvbmx5IDMgb2YgdGhvc2Ugd2VyZSBzZXF1ZW5jZWQgZm9yIHNSTkEgaW4gUC4gZXZlcm1hbm5pLgoKYGBge3IgbG9hZC1zUk5BLWNvdW50c30KIyBSZWFkIGluIHNSTkEgY291bnRzIGRhdGEKUGV2ZV9jb3VudHNfc1JOQV9kYXRhX09HIDwtIHJlYWRfZGVsaW0oIi4uLy4uLy4uL2RlZXAtZGl2ZS9FLVBldmUvb3V0cHV0LzA4LjItUGV2ZS1zUk5Bc2VxLVNob3J0U3RhY2stMzFicC1mYXN0cC1tZXJnZWQvU2hvcnRTdGFja19vdXQvQ291bnRzLnR4dCIsIGRlbGltPSJcdCIpIApoZWFkKFBldmVfY291bnRzX3NSTkFfZGF0YV9PRykKYGBgCgojIyBDb3VudCBkYXRhIG11bmdpbmcKCmBgYHtyIHNSTkEtY291bnQtZGF0YS1tdW5naW5nfQpQZXZlX2NvdW50c19zUk5BIDwtIFBldmVfY291bnRzX3NSTkFfZGF0YV9PRwoKIyBSZW1vdmUgZXhjZXNzIHBvcnRpb25zIG9mIHNhbXBsZSBjb2x1bW4gbmFtZXMgdG8ganVzdCAic2FtcGxlIyMjIgpjb2xuYW1lcyhQZXZlX2NvdW50c19zUk5BKSA8LSBzdWIoIi1TMS1UUDItZmFzdHAtYWRhcHRlcnMtcG9seUctMzFicC1tZXJnZWQiLCAiIiwgY29sbmFtZXMoUGV2ZV9jb3VudHNfc1JOQSkpCmNvbG5hbWVzKFBldmVfY291bnRzX3NSTkEpIDwtIHN1YigiUE9SLSIsICJzYW1wbGUiLCBjb2xuYW1lcyhQZXZlX2NvdW50c19zUk5BKSkKCiMgS2VlcCBqdXN0IHRoZSBjb3VudHMgYW5kIGNsdXN0ZXIgbmFtZXMKUGV2ZV9jb3VudHNfc1JOQSA8LSBQZXZlX2NvdW50c19zUk5BICU+JSBzZWxlY3QoInNhbXBsZTczIiwgInNhbXBsZTc5IiwgInNhbXBsZTgyIiwgIk5hbWUiKQoKIyBJJ20gbm90IGdvaW5nIHRvIGJlIGRvaW5nIGFueSByZW1vdmFsIG9mIGxvdy1jb3VudCBzUk5BcyBmb3Igbm93CgojIE1ha2UgdGhlIGNsdXN0ZXIgbmFtZXMgb3VyIG5ldyByb3cgbmFtZXMKUGV2ZV9jb3VudHNfc1JOQSA8LSBQZXZlX2NvdW50c19zUk5BICU+JSBjb2x1bW5fdG9fcm93bmFtZXModmFyID0gIk5hbWUiKQoKaGVhZChQZXZlX2NvdW50c19zUk5BKQpgYGAKCgojIyBFeHByZXNzaW9uIGxldmVscwoKUGxvdCBoaXN0b2dyYW1zIG9mIHRoZSBleHByZXNzaW9uIGxldmVscyBpbiBlYWNoIHNhbXBsZQoKYGBge3IgZXhwcmVzc2lvbi1sZXZlbC1oaXN0b2dyYW1zfQojIE1lbHQgdGhlIGNvdW50IG1hdHJpeCBpbnRvIGxvbmcgZm9ybWF0ClBldmVfY291bnRzX3NSTkFfbWVsdGVkIDwtIG1lbHQoUGV2ZV9jb3VudHNfc1JOQSwgdmFyaWFibGUubmFtZSA9ICJzYW1wbGUiLCB2YWx1ZS5uYW1lID0gImNvdW50cyIpCgojIFBsb3QgdGhlIGV4cHJlc3Npb24gbGV2ZWwgaGlzdG9ncmFtcyBmb3IgZWFjaCBzYW1wbGUKZ2dwbG90KFBldmVfY291bnRzX3NSTkFfbWVsdGVkLCBhZXMoeCA9IGNvdW50cykpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAiIzFFMjc2MSIsIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfbG9nMTAoKSArICAjIE9wdGlvbmFsOiBMb2ctdHJhbnNmb3JtIHRoZSB4LWF4aXMgZm9yIGJldHRlciB2aXN1YWxpemF0aW9uCiAgZmFjZXRfd3JhcCh+c2FtcGxlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnModGl0bGUgPSAiR2VuZSBFeHByZXNzaW9uIExldmVsIEhpc3RvZ3JhbSBmb3IgRWFjaCBTYW1wbGUiLAogICAgICAgeCA9ICJFeHByZXNzaW9uIExldmVsIChDb3VudHMpIiwKICAgICAgIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIFRyYW5zY3JpcHQgY291bnRzCgpGaXJzdCBsZXQncyBjaGVjayB0aGUgdG90YWwgbnVtYmVyIG9mIHRyYW5zY3JpcHRzIGluIGVhY2ggc2FtcGxlIC0tIGtlZXAgaW4gbWluZCB0aGlzIGV4cHJlc3Npb24gZGF0YSBoYXMgKm5vdCogYmVlbiBub3JtYWxpemVkIHlldCwgc28gdGhlcmUgbWF5IGJlIGRpZmZlcmVudCB0b3RhbHMgZm9yIGVhY2ggc2FtcGxlCmBgYHtyIHRyYW5zY3JpcHQtY291bnRzLXBsb3R9CiMgQ2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2YgdHJhbnNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlCnRvdGFsX3RyYW5zY3JpcHRzIDwtIGNvbFN1bXMoUGV2ZV9jb3VudHNfc1JOQSkKCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgcGxvdHRpbmcKdG90YWxfdHJhbnNjcmlwdHNfZGYgPC0gZGF0YS5mcmFtZShzYW1wbGUgPSBuYW1lcyh0b3RhbF90cmFuc2NyaXB0cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxzID0gdG90YWxfdHJhbnNjcmlwdHMpCgojIFBsb3QgdGhlIHRvdGFsIG51bWJlciBvZiB0cmFuc2NyaXB0cyBmb3IgZWFjaCBzYW1wbGUKZ2dwbG90KHRvdGFsX3RyYW5zY3JpcHRzX2RmLCBhZXMoeCA9IHNhbXBsZSwgeSA9IHRvdGFscykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICIjMUUyNzYxIiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBOdW1iZXIgb2YgVHJhbnNjcmlwdHMgcGVyIFNhbXBsZSIsCiAgICAgICB4ID0gIlNhbXBsZSIsCiAgICAgICB5ID0gIlRvdGFsIFRyYW5zY3JpcHRzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIHJlYWRhYmlsaXR5CmBgYAoKTm93IGxldCdzIGNoZWNrIHRoZSBudW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIGluIGVhY2ggc2FtcGxlIC0tIHRoYXQgaXMsIGhvdyBtYW55IHVuaXF1ZSBzUk5BcyBhcmUgZXhwcmVzc2VkIGluIGVhY2ggc2FtcGxlPyBUaGlzIHNob3VsZCBiZSBwcmV0dHkgbXVjaCB0aGUgc2FtZSBhY3Jvc3Mgc2FtcGxlcywgZXZlbiB3aXRob3V0IG5vcm1hbGl6YXRpb24uCgpgYGB7ciB0b3RhbC11bmlxdWUtdHJhbnNjcmlwdHMtcGxvdH0KIyBDYWxjdWxhdGUgdGhlIG51bWJlciBvZiB1bmlxdWUgdHJhbnNjcmlwdHMgKG5vbi16ZXJvIGNvdW50cykgZm9yIGVhY2ggc2FtcGxlCnVuaXF1ZV90cmFuc2NyaXB0cyA8LSBjb2xTdW1zKFBldmVfY291bnRzX3NSTkEgPiAwKQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBwbG90dGluZwp1bmlxdWVfdHJhbnNjcmlwdHNfZGYgPC0gZGF0YS5mcmFtZShzYW1wbGUgPSBuYW1lcyh1bmlxdWVfdHJhbnNjcmlwdHMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmlxdWVzID0gdW5pcXVlX3RyYW5zY3JpcHRzKQoKIyBQbG90IHRoZSB0b3RhbCBudW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIGZvciBlYWNoIHNhbXBsZQpnZ3Bsb3QodW5pcXVlX3RyYW5zY3JpcHRzX2RmLCBhZXMoeCA9IHNhbXBsZSwgeSA9IHVuaXF1ZXMpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAiIzFFMjc2MSIsIGNvbG9yID0gImJsYWNrIikgKwogIGxhYnModGl0bGUgPSAiVG90YWwgTnVtYmVyIG9mIFVuaXF1ZSBFeHByZXNzZWQgVHJhbnNjcmlwdHMgcGVyIFNhbXBsZSIsCiAgICAgICB4ID0gIlNhbXBsZSIsCiAgICAgICB5ID0gIlVuaXF1ZSBUcmFuc2NyaXB0cyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciByZWFkYWJpbGl0eQpgYGAKICAgCgojIG1pUk5BCgojIyBMb2FkIG1pUk5BIG1ldGFkYXRhCgpUaGUgU2hvcnRTdGFjayBvdXRwdXQgUmVzdWx0cy50eHQgaW5jbHVkZXMgYWxsIGNsdXN0ZXJzIG9mIHNSTkEgcmVhZHMsIGluY2x1ZGluZyB0aG9zZSBub3QgYW5ub3RhdGVkIGFzIHZhbGlkIG1pUk5Bcy4gTm93IHRoYXQgd2UndmUgbG9va2VkIGF0IGFsbCB0aGUgc1JOQXMgYSBiaXQsIGxldCdzIGZvY3VzIGluIG9uIHRob3NlIGNsYXNzaWZpZWQgYXMgbWlSTkFzLgoKYGBge3IgbWlSTkEtY291bnQtZGF0YS1tdW5naW5nfQoKIyBKb2luIHdpdGggZnVsbCBtZXRhZGF0YSBzaGVldCwgd2hpY2ggb25seSBjb250YWlucyB2YWxpZCBtaVJOQXMKUGV2ZV9tZXRhZGF0YV9taVJOQSA8LSByZWFkX2NzdigiLi4vLi4vLi4vZGVlcC1kaXZlL0RFRi1jcm9zcy1zcGVjaWVzL291dHB1dC8xMC1zaG9ydFJOQS1TaG9ydFN0YWNrLWNvbXBhcmlzb24vUGV2ZV9yZXN1bHRzX21hdHVyZV9uYW1lZC5jc3YiKSAKClBldmVfY291bnRzX3NSTkEgPC0gcm93bmFtZXNfdG9fY29sdW1uKFBldmVfY291bnRzX3NSTkEsIHZhciA9ICJOYW1lIikKClBldmVfY291bnRzX21pUk5BIDwtIGxlZnRfam9pbihQZXZlX21ldGFkYXRhX21pUk5BLCBQZXZlX2NvdW50c19zUk5BLCBieSA9IGMoIk5hbWUiID0gIk5hbWUiKSkKCiMgS2VlcCBqdXN0IHRoZSBjb3VudHMgYW5kIGdpdmVuIG1pUk5BIG5hbWVzIChlLmcuLCBiYXNlZCBvbiBtYXRjaCB0byBwcmV2aW91c2x5IGRlc2NyaWJlZCBtaVJOQSkKUGV2ZV9jb3VudHNfbWlSTkEgPC0gUGV2ZV9jb3VudHNfbWlSTkEgJT4lIHNlbGVjdCgic2FtcGxlNzMiLCAic2FtcGxlNzkiLCAic2FtcGxlODIiLCAiZ2l2ZW5fbWlSTkFfbmFtZSIpCgojIFdlIHNlZW0gdG8gaGF2ZSBhIGR1cGxpY2F0ZSBtaVJOQSBuYW1lLCAicGV2ZS1taXItbm92ZWwtNCIsIHdoaWNoIHdvdWxkIHByZXZlbnQgdXMgZnJvbSBtYWtpbmcgdGhlIG1pUk5BIG5hbWVzIG91ciBuZXcgcm93IG5hbWVzLiBXZSBuZWVkIHRvIGZpcnN0IG1ha2UgdGhhdCBjb2x1bW4gdW5pcXVlClBldmVfY291bnRzX21pUk5BJGdpdmVuX21pUk5BX25hbWUgPC0gbWFrZS51bmlxdWUoYXMuY2hhcmFjdGVyKFBldmVfY291bnRzX21pUk5BJGdpdmVuX21pUk5BX25hbWUpKQoKIyBNYWtlIHRoZSBtaVJOQSBuYW1lcyBvdXIgbmV3IHJvdyBuYW1lcwpQZXZlX2NvdW50c19taVJOQSA8LSBQZXZlX2NvdW50c19taVJOQSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICJnaXZlbl9taVJOQV9uYW1lIikKCmhlYWQoUGV2ZV9jb3VudHNfbWlSTkEpCmBgYAoKIyMgRXhwcmVzc2lvbiBsZXZlbHMKClBsb3QgaGlzdG9ncmFtcyBvZiB0aGUgbWlSTkEgZXhwcmVzc2lvbiBsZXZlbHMgaW4gZWFjaCBzYW1wbGUKCmBgYHtyIG1pUk5BLWV4cHJlc3Npb24tbGV2ZWwtaGlzdG9ncmFtc30KIyBNZWx0IHRoZSBjb3VudCBtYXRyaXggaW50byBsb25nIGZvcm1hdApQZXZlX2NvdW50c19taVJOQV9tZWx0ZWQgPC0gbWVsdChQZXZlX2NvdW50c19taVJOQSwgdmFyaWFibGUubmFtZSA9ICJzYW1wbGUiLCB2YWx1ZS5uYW1lID0gImNvdW50cyIpCgojIFBsb3QgdGhlIGV4cHJlc3Npb24gbGV2ZWwgaGlzdG9ncmFtcyBmb3IgZWFjaCBzYW1wbGUKZ2dwbG90KFBldmVfY291bnRzX21pUk5BX21lbHRlZCwgYWVzKHggPSBjb3VudHMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gIiMxRTI3NjEiLCBjb2xvciA9ICJibGFjayIpICsKICBzY2FsZV94X2xvZzEwKCkgKyAgIyBPcHRpb25hbDogTG9nLXRyYW5zZm9ybSB0aGUgeC1heGlzIGZvciBiZXR0ZXIgdmlzdWFsaXphdGlvbgogIGZhY2V0X3dyYXAofnNhbXBsZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHRpdGxlID0gIkdlbmUgRXhwcmVzc2lvbiBMZXZlbCBIaXN0b2dyYW0gZm9yIEVhY2ggU2FtcGxlIiwKICAgICAgIHggPSAiRXhwcmVzc2lvbiBMZXZlbCAoQ291bnRzKSIsCiAgICAgICB5ID0gIkZyZXF1ZW5jeSIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyBtaVJOQSBjb3VudHMKCkZpcnN0IGxldCdzIGNoZWNrIHRoZSB0b3RhbCBudW1iZXIgb2YgbWlSTkFzIGluIGVhY2ggc2FtcGxlIC0tIGtlZXAgaW4gbWluZCB0aGlzIGV4cHJlc3Npb24gZGF0YSBoYXMgKm5vdCogYmVlbiBub3JtYWxpemVkIHlldCwgc28gdGhlcmUgbWF5IGJlIGRpZmZlcmVudCB0b3RhbHMgZm9yIGVhY2ggc2FtcGxlCmBgYHtyIG1pUk5BLWNvdW50cy1wbG90fQojIENhbGN1bGF0ZSB0aGUgdG90YWwgbnVtYmVyIG9mIHRyYW5zY3JpcHRzIGZvciBlYWNoIHNhbXBsZQp0b3RhbF9taVJOQSA8LSBjb2xTdW1zKFBldmVfY291bnRzX21pUk5BKQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBwbG90dGluZwp0b3RhbF9taVJOQV9kZiA8LSBkYXRhLmZyYW1lKHNhbXBsZSA9IG5hbWVzKHRvdGFsX21pUk5BKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbHMgPSB0b3RhbF9taVJOQSkKCiMgUGxvdCB0aGUgdG90YWwgbnVtYmVyIG9mIHRyYW5zY3JpcHRzIGZvciBlYWNoIHNhbXBsZQpnZ3Bsb3QodG90YWxfbWlSTkFfZGYsIGFlcyh4ID0gc2FtcGxlLCB5ID0gdG90YWxzKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gIiMxRTI3NjEiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIlRvdGFsIE51bWJlciBvZiBtaVJOQXMgcGVyIFNhbXBsZSIsCiAgICAgICB4ID0gIlNhbXBsZSIsCiAgICAgICB5ID0gIlRvdGFsIG1pUk5BcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciByZWFkYWJpbGl0eQpgYGAKCk5vdyBsZXQncyBjaGVjayB0aGUgbnVtYmVyIG9mIHVuaXF1ZSBtaVJOQXMgaW4gZWFjaCBzYW1wbGUgLS0gVGhpcyBzaG91bGQgYmUgcHJldHR5IG11Y2ggdGhlIHNhbWUgYWNyb3NzIHNhbXBsZXMsIGV2ZW4gd2l0aG91dCBub3JtYWxpemF0aW9uLgoKYGBge3IgdG90YWwtdW5pcXVlLW1pUk5BLXBsb3R9CiMgQ2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgdW5pcXVlIHRyYW5zY3JpcHRzIChub24temVybyBjb3VudHMpIGZvciBlYWNoIHNhbXBsZQp1bmlxdWVfbWlSTkEgPC0gY29sU3VtcyhQZXZlX2NvdW50c19taVJOQSA+IDApCgojIENyZWF0ZSBhIGRhdGEgZnJhbWUgZm9yIHBsb3R0aW5nCnVuaXF1ZV9taVJOQV9kZiA8LSBkYXRhLmZyYW1lKHNhbXBsZSA9IG5hbWVzKHVuaXF1ZV9taVJOQSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXF1ZXMgPSB1bmlxdWVfbWlSTkEpCgojIFBsb3QgdGhlIHRvdGFsIG51bWJlciBvZiB1bmlxdWUgdHJhbnNjcmlwdHMgZm9yIGVhY2ggc2FtcGxlCmdncGxvdCh1bmlxdWVfbWlSTkFfZGYsIGFlcyh4ID0gc2FtcGxlLCB5ID0gdW5pcXVlcykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICIjMUUyNzYxIiwgY29sb3IgPSAiYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBOdW1iZXIgb2YgVW5pcXVlIEV4cHJlc3NlZCBtaVJOQXMgcGVyIFNhbXBsZSIsCiAgICAgICB4ID0gIlNhbXBsZSIsCiAgICAgICB5ID0gIlVuaXF1ZSBtaVJOQSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciByZWFkYWJpbGl0eQpgYGAKCiMjIEhlYXRtYXAKCmBgYHtyIG1pUk5BLWhlYXRtYXB9CmhlYXRfY29sb3JzIDwtIHJldihicmV3ZXIucGFsKDEyLCAiUmRZbEJ1IikpCgpwaGVhdG1hcChQZXZlX2NvdW50c19taVJOQSwKICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVFJVRSwKICAgICAgICAgc2hvd19yb3duYW1lcyA9IFRSVUUsCiAgICAgICAgIHNob3dfY29sbmFtZXMgPSBUUlVFLAogICAgICAgICBjb2xvciA9IGhlYXRfY29sb3JzLAogICAgICAgICBmb250c2l6ZV9yb3cgPSA4LAogICAgICAgICBmb250c2l6ZV9jb2wgPSA4KQpgYGAKV2VsbC4uLiB0aGVyZSdzIGxpa2UgMyBtaVJOQXMgd2l0aCBtdWNoIGhpZ2hlciBleHByZXNzaW9uIHRoYW4gdGhlIG90aGVycywgd2hpY2ggaXMgbWFraW5nIHZpc3VhbGl6aW5nIHJlbGF0aXZlIGRpZmZlcmVuY2VzIGRpZmZpY3VsdC4gTGV0J3MgcmVkbyB0aGUgaGVhdG1hcCwgbm9ybWFsaXppbmcgZWFjaCByb3cgdG8gdmlldyByZWxhdGl2ZSBkaWZmZXJlbmNlIGluIGV4cHJlc3Npb24gYmV0d2VlbiBzYW1wbGVzIChgc2NhbGU9J3JvdydgKQoKYGBge3IgbWlSTkEtaGVhdG1hcC1yb3dzY2FsZX0KcGhlYXRtYXAoUGV2ZV9jb3VudHNfbWlSTkEsCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsCiAgICAgICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsCiAgICAgICAgIHNob3dfcm93bmFtZXMgPSBUUlVFLAogICAgICAgICBzaG93X2NvbG5hbWVzID0gVFJVRSwKICAgICAgICAgc2NhbGUgPSAncm93JywKICAgICAgICAgY29sb3IgPSBoZWF0X2NvbG9ycywKICAgICAgICAgZm9udHNpemVfcm93ID0gOCwKICAgICAgICAgZm9udHNpemVfY29sID0gOCkKYGBg