Use miRTrace (Kang et al. 2018) to identify taxonomic origins of miRNA sequencing data.
NOTE: This requires you to have previously run 06-Peve-sRNAseq-trimming.Rmd
, as the code relies on the trimmed reads output from that code.
Inputs:
Outputs:
mirtrace.config
: A miRTrace config file. A comma-separated file with this layout (one FastQ per line): /path/to/fastq,custom_sample_name
“Collapsed” (i.e. unique sequences only) FastA for each corresponding input FastQ.
mirtrace-report.html
: HTML-formatted report generated by miRTrace.
mirtrace-stats-contamination_basic.tsv
: Tab-delimited report with counts of sequences from each collapsed FastAs having matches to known miRNAs within each of the miRTrace Clades.
mirtrace-stats-contamination_detailed.csv
: Tab-delimited report of only Clades with which sequences were matched, along with the corresponding miRNA families in each clade, and the sequence counts.
Create a Bash variables file
This allows usage of Bash variables across R Markdown chunks.
{
echo "#### Assign Variables ####"
echo ""
echo "# Data directories"
echo 'export deep_dive_dir=/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive'
echo 'export output_dir_top=${deep_dive_dir}/E-Peve/output/09-Peve-sRNAseq-miRTrace'
echo 'export trimmed_reads_dir=${deep_dive_dir}/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads'
echo ""
echo "# Paths to programs"
echo 'export mirtrace=/home/sam/programs/mambaforge/envs/miRTrace_env/bin/mirtrace'
echo ""
echo "# Set number of CPUs to use"
echo 'export threads=40'
echo ""
echo "export fastq_pattern='*flexbar_trim.25bp*.gz'"
echo "# Programs associative array"
echo "declare -A programs_array"
echo "programs_array=("
echo '[mirtrace]="${mirtrace}"'
echo ")"
} > .bashvars
cat .bashvars
#### Assign Variables ####
# Data directories
export deep_dive_dir=/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive
export output_dir_top=${deep_dive_dir}/E-Peve/output/09-Peve-sRNAseq-miRTrace
export trimmed_reads_dir=${deep_dive_dir}/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads
# Paths to programs
export mirtrace=/home/sam/programs/mambaforge/envs/miRTrace_env/bin/mirtrace
# Set number of CPUs to use
export threads=40
export fastq_pattern='*flexbar_trim.25bp*.gz'
# Programs associative array
declare -A programs_array
programs_array=(
[mirtrace]="${mirtrace}"
)
Create miRTrace config file
# Load bash variables into memory
source .bashvars
# Declare array
fastq_array=()
# Populate array
fastq_array=(${trimmed_reads_dir}/${fastq_pattern})
# Loop through read pairs
# Increment by 2 to process next pair of FastQ files
if [ -f "${output_dir_top}/mirtrace.config" ]; then
echo "mirtrace.config already exists. Nothing to do."
else
for (( i=0; i<${#fastq_array[@]} ; i+=2 ))
do
# Use first three parts of filename to create short sample name
R1_name=$(echo "${fastq_array[i]##*/}" | awk -F "-" '{print $1"-"$2"-"$3}')
R2_name=$(echo "${fastq_array[i+1]##*/}" | awk -F "-" '{print $1"-"$2"-"$3}')
echo "${fastq_array[i]},${R1_name}_1"
echo "${fastq_array[i+1]},${R2_name}_2"
done >> "${output_dir_top}/mirtrace.config"
fi
cat "${output_dir_top}/mirtrace.config"
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads/sRNA-POR-73-S1-TP2.flexbar_trim.25bp_1.fastq.gz,sRNA-POR-73_1
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads/sRNA-POR-73-S1-TP2.flexbar_trim.25bp_2.fastq.gz,sRNA-POR-73_2
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads/sRNA-POR-79-S1-TP2.flexbar_trim.25bp_1.fastq.gz,sRNA-POR-79_1
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads/sRNA-POR-79-S1-TP2.flexbar_trim.25bp_2.fastq.gz,sRNA-POR-79_2
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads/sRNA-POR-82-S1-TP2.flexbar_trim.25bp_1.fastq.gz,sRNA-POR-82_1
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/06-Peve-sRNAseq-trimming/trimmed-reads/sRNA-POR-82-S1-TP2.flexbar_trim.25bp_2.fastq.gz,sRNA-POR-82_2
# Load bash variables into memory
source .bashvars
time \
${programs_array[mirtrace]} trace \
--config ${output_dir_top}/mirtrace.config \
--write-fasta \
--num-threads ${threads} \
--output-dir ${output_dir_top} \
--force
tree -h ${output_dir_top}
miRTrace version 1.0.1 starting. Processing 6 sample(s).
NOTE: reusing existing output directory, outdated files may be present.
Run complete. Processed 6 sample(s) in 38 s.
Reports written to /home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/09-Peve-sRNAseq-miRTrace/
For information about citing our paper, run miRTrace in mode "cite".
real 0m39.313s
user 2m46.272s
sys 0m4.148s
/home/shared/8TB_HDD_01/sam/gitrepos/deep-dive/E-Peve/output/09-Peve-sRNAseq-miRTrace
├── [ 972] mirtrace.config
├── [299K] mirtrace-report.html
├── [ 395] mirtrace-stats-contamination_basic.tsv
├── [ 413] mirtrace-stats-contamination_detailed.tsv
└── [4.0K] qc_passed_reads.all.collapsed
├── [ 63M] sRNA-POR-73-S1-TP2.flexbar_trim.25bp_1.fasta
├── [ 74M] sRNA-POR-73-S1-TP2.flexbar_trim.25bp_2.fasta
├── [ 94M] sRNA-POR-79-S1-TP2.flexbar_trim.25bp_1.fasta
├── [109M] sRNA-POR-79-S1-TP2.flexbar_trim.25bp_2.fasta
├── [112M] sRNA-POR-82-S1-TP2.flexbar_trim.25bp_1.fasta
└── [128M] sRNA-POR-82-S1-TP2.flexbar_trim.25bp_2.fasta
1 directory, 10 files
Results
Read in table as data frame
mirtrace.detailed.df <- read.csv("../output/09-Peve-sRNAseq-miRTrace/mirtrace-stats-contamination_detailed.tsv", sep = "\t", header = TRUE)
str(mirtrace.detailed.df)
'data.frame': 1 obs. of 10 variables:
$ CLADE : chr "insects"
$ FAMILY_ID : int 14
$ MIRBASE_IDS : chr "aae-miR-14,aga-miR-14,ame-miR-14,api-miR-14,bmo-miR-14,cqu-miR-14,dan-miR-14,der-miR-14,dgr-miR-14,dme-miR-14,d"| __truncated__
$ SEQ : chr "TCAGTCTTTTTCTCTCTCCT"
$ sRNA.POR.73_1: int 0
$ sRNA.POR.73_2: int 0
$ sRNA.POR.79_1: int 0
$ sRNA.POR.79_2: int 0
$ sRNA.POR.82_1: int 1
$ sRNA.POR.82_2: int 0
Number of samples with matches
IMPORTANT: Change starts_with()
to match prefix of input sRNAseq reads!
# Select columns corresponding to sample names
sample_columns <- mirtrace.detailed.df %>%
select(starts_with("sRNA.POR."))
# Calculate the sum for each column
sample_sums <- colSums(sample_columns)
# Count the number of columns with a sum greater than 0
samples_with_sum_gt_0 <- sum(sample_sums > 0)
paste("Number of samples with matches: ", samples_with_sum_gt_0)
[1] "Number of samples with matches: 1"
Percentage of samples with matches
# Total number of samples (columns)
total_samples <- ncol(sample_columns)
# Percentage of samples with sums greater than 0
percentage_samples_gt_0 <- (samples_with_sum_gt_0 / total_samples) * 100
paste("Percentage of samples with matches: ", percentage_samples_gt_0)
[1] "Percentage of samples with matches: 16.6666666666667"
Number of clades with matches
unique_clade_count <- mirtrace.detailed.df %>%
distinct(CLADE) %>% # Get unique entries in CLADE column
count() # Count the number of unique entries
paste("Number of clades with matches:", unique_clade_count)
[1] "Number of clades with matches: 1"
To make them easier to see, counts > 0 are highlighted in green.
mirtrace.detailed.df %>%
mutate(
across(
starts_with("sRNA"),
~cell_spec(
.,
background = ifelse(
. > 0,
"lightgreen",
"white"
)
)
)
) %>%
kable(escape = F, caption = "Clades identified as having sRNAseq matches.") %>%
kable_styling("striped") %>%
scroll_box(width = "100%", height = "500px")
Table 4.1: Clades identified as having sRNAseq matches.
CLADE
|
FAMILY_ID
|
MIRBASE_IDS
|
SEQ
|
sRNA.POR.73_1
|
sRNA.POR.73_2
|
sRNA.POR.79_1
|
sRNA.POR.79_2
|
sRNA.POR.82_1
|
sRNA.POR.82_2
|
insects
|
14
|
aae-miR-14,aga-miR-14,ame-miR-14,api-miR-14,bmo-miR-14,cqu-miR-14,dan-miR-14,der-miR-14,dgr-miR-14,dme-miR-14,dmo-miR-14,dpe-miR-14,dps-miR-14,dse-miR-14,dsi-miR-14,dvi-miR-14,dwi-miR-14,dya-miR-14,hme-miR-14,mse-miR-14,ngi-miR-14,nvi-miR-14,tca-miR-14
|
TCAGTCTTTTTCTCTCTCCT
|
0
|
0
|
0
|
0
|
1
|
0
|
Citations
Kang, Wenjing, Yrin Eldfjell, Bastian Fromm, Xavier Estivill, Inna Biryukova, and Marc R. Friedländer. 2018.
“miRTrace Reveals the Organismal Origins of microRNA Sequencing Data.” Genome Biology 19 (1).
https://doi.org/10.1186/s13059-018-1588-9.
LS0tCnRpdGxlOiAiMDktUGV2ZS1zUk5Bc2VxLW1pUlRyYWNlIgphdXRob3I6ICJTYW0gV2hpdGUiCmRhdGU6ICIyMDIzLTExLTE2IgpvdXRwdXQ6IAogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgZ2l0aHViX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYgpsaW5rLWNpdGF0aW9uczogdHJ1ZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmV0aWN1bGF0ZSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBGQUxTRSwgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKVXNlIFttaVJUcmFjZV0oaHR0cHM6Ly9naXRodWIuY29tL2ZyaWVkbGFuZGVybGFiL21pcnRyYWNlKSBbQGthbmcyMDE4XSB0byBpZGVudGlmeSB0YXhvbm9taWMgb3JpZ2lucyBvZiBtaVJOQSBzZXF1ZW5jaW5nIGRhdGEuCgpOT1RFOiBUaGlzIHJlcXVpcmVzIHlvdSB0byBoYXZlIHByZXZpb3VzbHkgcnVuIFtgMDYtUGV2ZS1zUk5Bc2VxLXRyaW1taW5nLlJtZGBdKGh0dHBzOi8vZ2l0aHViLmNvbS91cm9sLWU1L2RlZXAtZGl2ZS9ibG9iL21haW4vRS1QZXZlL2NvZGUvMDYtUGV2ZS1zUk5Bc2VxLXRyaW1taW5nLlJtZCksIGFzIHRoZSBjb2RlIHJlbGllcyBvbiB0aGUgdHJpbW1lZCByZWFkcyBvdXRwdXQgZnJvbSB0aGF0IGNvZGUuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCklucHV0czoKCi0gICBUcmltbWVkIHNSTkFzZXEgRmFzdFFzIGdlbmVyYXRlZCBieSBbYDA2LVBldmUtc1JOQXNlcS10cmltbWluZy5SbWRgXShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9jb2RlLzA2LVBldmUtc1JOQXNlcS10cmltbWluZy5SbWQpCgogICAgLSAgIEZpbGVuYW1lcyBmb3JtYXR0ZWQ6IGAqZmxleGJhcl90cmltLjI1YnAqLmd6YAoKT3V0cHV0czoKCi0gICBgbWlydHJhY2UuY29uZmlnYDogQSBbbWlSVHJhY2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9mcmllZGxhbmRlcmxhYi9taXJ0cmFjZSkgY29uZmlnIGZpbGUuIEEgY29tbWEtc2VwYXJhdGVkIGZpbGUgd2l0aCB0aGlzIGxheW91dCAob25lIEZhc3RRIHBlciBsaW5lKTogYC9wYXRoL3RvL2Zhc3RxLGN1c3RvbV9zYW1wbGVfbmFtZWAKCi0gICAiQ29sbGFwc2VkIiAoaS5lLiB1bmlxdWUgc2VxdWVuY2VzIG9ubHkpIEZhc3RBIGZvciBlYWNoIGNvcnJlc3BvbmRpbmcgaW5wdXQgRmFzdFEuCgotICAgYG1pcnRyYWNlLXJlcG9ydC5odG1sYDogSFRNTC1mb3JtYXR0ZWQgcmVwb3J0IGdlbmVyYXRlZCBieSBbbWlSVHJhY2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9mcmllZGxhbmRlcmxhYi9taXJ0cmFjZSkuCgotICAgYG1pcnRyYWNlLXN0YXRzLWNvbnRhbWluYXRpb25fYmFzaWMudHN2YDogVGFiLWRlbGltaXRlZCByZXBvcnQgd2l0aCBjb3VudHMgb2Ygc2VxdWVuY2VzIGZyb20gZWFjaCBjb2xsYXBzZWQgRmFzdEFzIGhhdmluZyBtYXRjaGVzIHRvIGtub3duIG1pUk5BcyB3aXRoaW4gZWFjaCBvZiB0aGUgW21pUlRyYWNlXShodHRwczovL2dpdGh1Yi5jb20vZnJpZWRsYW5kZXJsYWIvbWlydHJhY2UpIENsYWRlcy4KCi0gICBgbWlydHJhY2Utc3RhdHMtY29udGFtaW5hdGlvbl9kZXRhaWxlZC5jc3ZgOiBUYWItZGVsaW1pdGVkIHJlcG9ydCBvZiAqb25seSogQ2xhZGVzIHdpdGggd2hpY2ggc2VxdWVuY2VzIHdlcmUgbWF0Y2hlZCwgYWxvbmcgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBtaVJOQSBmYW1pbGllcyBpbiBlYWNoIGNsYWRlLCBhbmQgdGhlIHNlcXVlbmNlIGNvdW50cy4KCiMgQ3JlYXRlIGEgQmFzaCB2YXJpYWJsZXMgZmlsZQoKVGhpcyBhbGxvd3MgdXNhZ2Ugb2YgQmFzaCB2YXJpYWJsZXMgYWNyb3NzIFIgTWFya2Rvd24gY2h1bmtzLgoKYGBge3Igc2F2ZS1iYXNoLXZhcmlhYmxlcy10by1ydmFycy1maWxlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CnsKZWNobyAiIyMjIyBBc3NpZ24gVmFyaWFibGVzICMjIyMiCmVjaG8gIiIKCmVjaG8gIiMgRGF0YSBkaXJlY3RvcmllcyIKZWNobyAnZXhwb3J0IGRlZXBfZGl2ZV9kaXI9L2hvbWUvc2hhcmVkLzhUQl9IRERfMDEvc2FtL2dpdHJlcG9zL2RlZXAtZGl2ZScKZWNobyAnZXhwb3J0IG91dHB1dF9kaXJfdG9wPSR7ZGVlcF9kaXZlX2Rpcn0vRS1QZXZlL291dHB1dC8wOS1QZXZlLXNSTkFzZXEtbWlSVHJhY2UnCmVjaG8gJ2V4cG9ydCB0cmltbWVkX3JlYWRzX2Rpcj0ke2RlZXBfZGl2ZV9kaXJ9L0UtUGV2ZS9vdXRwdXQvMDYtUGV2ZS1zUk5Bc2VxLXRyaW1taW5nL3RyaW1tZWQtcmVhZHMnCmVjaG8gIiIKCmVjaG8gIiMgUGF0aHMgdG8gcHJvZ3JhbXMiCmVjaG8gJ2V4cG9ydCBtaXJ0cmFjZT0vaG9tZS9zYW0vcHJvZ3JhbXMvbWFtYmFmb3JnZS9lbnZzL21pUlRyYWNlX2Vudi9iaW4vbWlydHJhY2UnCmVjaG8gIiIKCmVjaG8gIiMgU2V0IG51bWJlciBvZiBDUFVzIHRvIHVzZSIKZWNobyAnZXhwb3J0IHRocmVhZHM9NDAnCmVjaG8gIiIKCmVjaG8gImV4cG9ydCBmYXN0cV9wYXR0ZXJuPScqZmxleGJhcl90cmltLjI1YnAqLmd6JyIKCmVjaG8gIiMgUHJvZ3JhbXMgYXNzb2NpYXRpdmUgYXJyYXkiCmVjaG8gImRlY2xhcmUgLUEgcHJvZ3JhbXNfYXJyYXkiCmVjaG8gInByb2dyYW1zX2FycmF5PSgiCmVjaG8gJ1ttaXJ0cmFjZV09IiR7bWlydHJhY2V9IicKZWNobyAiKSIKfSA+IC5iYXNodmFycwoKY2F0IC5iYXNodmFycwpgYGAKCiMgQ3JlYXRlIFttaVJUcmFjZV0oaHR0cHM6Ly9naXRodWIuY29tL2ZyaWVkbGFuZGVybGFiL21pcnRyYWNlKSBjb25maWcgZmlsZQoKYGBge3IgY3JlYXRlLWNvbmZpZy1maWxlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIERlY2xhcmUgYXJyYXkKZmFzdHFfYXJyYXk9KCkKCiMgUG9wdWxhdGUgYXJyYXkKZmFzdHFfYXJyYXk9KCR7dHJpbW1lZF9yZWFkc19kaXJ9LyR7ZmFzdHFfcGF0dGVybn0pCgojIExvb3AgdGhyb3VnaCByZWFkIHBhaXJzCiMgSW5jcmVtZW50IGJ5IDIgdG8gcHJvY2VzcyBuZXh0IHBhaXIgb2YgRmFzdFEgZmlsZXMKaWYgWyAtZiAiJHtvdXRwdXRfZGlyX3RvcH0vbWlydHJhY2UuY29uZmlnIiBdOyB0aGVuCiAgZWNobyAibWlydHJhY2UuY29uZmlnIGFscmVhZHkgZXhpc3RzLiBOb3RoaW5nIHRvIGRvLiIKICAKZWxzZQoKICBmb3IgKCggaT0wOyBpPCR7I2Zhc3RxX2FycmF5W0BdfSA7IGkrPTIgKSkKICBkbwogICAgIyBVc2UgZmlyc3QgdGhyZWUgcGFydHMgb2YgZmlsZW5hbWUgdG8gY3JlYXRlIHNob3J0IHNhbXBsZSBuYW1lCiAgICBSMV9uYW1lPSQoZWNobyAiJHtmYXN0cV9hcnJheVtpXSMjKi99IiB8IGF3ayAtRiAiLSIgJ3twcmludCAkMSItIiQyIi0iJDN9JykKICAgIFIyX25hbWU9JChlY2hvICIke2Zhc3RxX2FycmF5W2krMV0jIyovfSIgfCBhd2sgLUYgIi0iICd7cHJpbnQgJDEiLSIkMiItIiQzfScpCiAgICBlY2hvICIke2Zhc3RxX2FycmF5W2ldfSwke1IxX25hbWV9XzEiCiAgICBlY2hvICIke2Zhc3RxX2FycmF5W2krMV19LCR7UjJfbmFtZX1fMiIKICBkb25lID4+ICIke291dHB1dF9kaXJfdG9wfS9taXJ0cmFjZS5jb25maWciCgpmaQoKY2F0ICIke291dHB1dF9kaXJfdG9wfS9taXJ0cmFjZS5jb25maWciCmBgYAoKIyBSdW4gW21pUlRyYWNlXShodHRwczovL2dpdGh1Yi5jb20vZnJpZWRsYW5kZXJsYWIvbWlydHJhY2UpCgpgYGB7ciBydW4tbWlydHJhY2UsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCnRpbWUgXAoke3Byb2dyYW1zX2FycmF5W21pcnRyYWNlXX0gdHJhY2UgXAotLWNvbmZpZyAke291dHB1dF9kaXJfdG9wfS9taXJ0cmFjZS5jb25maWcgXAotLXdyaXRlLWZhc3RhIFwKLS1udW0tdGhyZWFkcyAke3RocmVhZHN9IFwKLS1vdXRwdXQtZGlyICR7b3V0cHV0X2Rpcl90b3B9IFwKLS1mb3JjZQoKdHJlZSAtaCAke291dHB1dF9kaXJfdG9wfQpgYGAKCiMgUmVzdWx0cwoKIyMgUmVhZCBpbiB0YWJsZSBhcyBkYXRhIGZyYW1lCgpgYGB7ciByZWFkLXRhYmxlLCBldmFsPVRSVUV9Cm1pcnRyYWNlLmRldGFpbGVkLmRmIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvMDktUGV2ZS1zUk5Bc2VxLW1pUlRyYWNlL21pcnRyYWNlLXN0YXRzLWNvbnRhbWluYXRpb25fZGV0YWlsZWQudHN2Iiwgc2VwID0gIlx0IiwgaGVhZGVyID0gVFJVRSkKCnN0cihtaXJ0cmFjZS5kZXRhaWxlZC5kZikKYGBgCgojIyBOdW1iZXIgb2Ygc2FtcGxlcyB3aXRoIG1hdGNoZXMKCklNUE9SVEFOVDogQ2hhbmdlIGBzdGFydHNfd2l0aCgpYCB0byBtYXRjaCBwcmVmaXggb2YgaW5wdXQgc1JOQXNlcSByZWFkcyEKCmBgYHtyIGNvdW50cy1zYW1wbGVzLXdpdGgtbWF0Y2hlcywgZXZhbD1UUlVFfQojIFNlbGVjdCBjb2x1bW5zIGNvcnJlc3BvbmRpbmcgdG8gc2FtcGxlIG5hbWVzCnNhbXBsZV9jb2x1bW5zIDwtIG1pcnRyYWNlLmRldGFpbGVkLmRmICU+JQogIHNlbGVjdChzdGFydHNfd2l0aCgic1JOQS5QT1IuIikpCgojIENhbGN1bGF0ZSB0aGUgc3VtIGZvciBlYWNoIGNvbHVtbgpzYW1wbGVfc3VtcyA8LSBjb2xTdW1zKHNhbXBsZV9jb2x1bW5zKQoKIyBDb3VudCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgd2l0aCBhIHN1bSBncmVhdGVyIHRoYW4gMApzYW1wbGVzX3dpdGhfc3VtX2d0XzAgPC0gc3VtKHNhbXBsZV9zdW1zID4gMCkKCnBhc3RlKCJOdW1iZXIgb2Ygc2FtcGxlcyB3aXRoIG1hdGNoZXM6ICIsIHNhbXBsZXNfd2l0aF9zdW1fZ3RfMCkKYGBgCgojIyBQZXJjZW50YWdlIG9mIHNhbXBsZXMgd2l0aCBtYXRjaGVzCgpgYGB7ciBwZXJjZW50YWdlLXNhbXBsZXMtd2l0aC1tYXRjaGVzLCBldmFsPVRSVUV9CiMgVG90YWwgbnVtYmVyIG9mIHNhbXBsZXMgKGNvbHVtbnMpCnRvdGFsX3NhbXBsZXMgPC0gbmNvbChzYW1wbGVfY29sdW1ucykKCiMgUGVyY2VudGFnZSBvZiBzYW1wbGVzIHdpdGggc3VtcyBncmVhdGVyIHRoYW4gMApwZXJjZW50YWdlX3NhbXBsZXNfZ3RfMCA8LSAoc2FtcGxlc193aXRoX3N1bV9ndF8wIC8gdG90YWxfc2FtcGxlcykgKiAxMDAKCnBhc3RlKCJQZXJjZW50YWdlIG9mIHNhbXBsZXMgd2l0aCBtYXRjaGVzOiAiLCBwZXJjZW50YWdlX3NhbXBsZXNfZ3RfMCkKYGBgCgojIyBOdW1iZXIgb2YgY2xhZGVzIHdpdGggbWF0Y2hlcwoKYGBge3IgZGlzdGluY3QtY2xhZGVzLCBldmFsPVRSVUUsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLWhpZGUnfQoKdW5pcXVlX2NsYWRlX2NvdW50IDwtIG1pcnRyYWNlLmRldGFpbGVkLmRmICU+JQogIGRpc3RpbmN0KENMQURFKSAlPiUgICAgIyBHZXQgdW5pcXVlIGVudHJpZXMgaW4gQ0xBREUgY29sdW1uCiAgY291bnQoKSAgICAgICAgICAgICAgICMgQ291bnQgdGhlIG51bWJlciBvZiB1bmlxdWUgZW50cmllcwoKCgpwYXN0ZSgiTnVtYmVyIG9mIGNsYWRlcyB3aXRoIG1hdGNoZXM6IiwgdW5pcXVlX2NsYWRlX2NvdW50KQoKCmBgYAoKIyMgW21pUlRyYWNlXShodHRwczovL2dpdGh1Yi5jb20vZnJpZWRsYW5kZXJsYWIvbWlydHJhY2UpIHRhYmxlCgpUbyBtYWtlIHRoZW0gZWFzaWVyIHRvIHNlZSwgY291bnRzIFw+IDAgYXJlIGhpZ2hsaWdodGVkIGluIGdyZWVuLgoKYGBge3IgbWlydHJhY2Utb3V0cHV0LXRhYmxlLCBldmFsPVRSVUUsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLWhpZGUnfQoKbWlydHJhY2UuZGV0YWlsZWQuZGYgJT4lCiAgbXV0YXRlKAogICAgYWNyb3NzKAogICAgICBzdGFydHNfd2l0aCgic1JOQSIpLAogICAgICB+Y2VsbF9zcGVjKAogICAgICAgIC4sCiAgICAgICAgYmFja2dyb3VuZCA9IGlmZWxzZSgKICAgICAgICAgIC4gPiAwLAogICAgICAgICAgImxpZ2h0Z3JlZW4iLAogICAgICAgICAgIndoaXRlIgogICAgICAgICAgKQogICAgICAgICkKICAgICAgKQogICAgKSAlPiUKICBrYWJsZShlc2NhcGUgPSBGLCBjYXB0aW9uID0gIkNsYWRlcyBpZGVudGlmaWVkIGFzIGhhdmluZyBzUk5Bc2VxIG1hdGNoZXMuIikgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIpICU+JSAKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiNTAwcHgiKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBDaXRhdGlvbnMK