Use miRTrace (Kang et al. 2018) to identify taxonomic origins of miRNA sequencing data.
NOTE: This requires you to have previously run 06.2-Peve-sRNAseq-trimming-31bp-fastp-merged.Rmd
, as the code relies on the trimmed and merged 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_02/shedurkin/deep-dive'
echo 'export output_dir_top=${deep_dive_dir}/E-Peve/output/09.2-Peve-sRNAseq-miRTrace-31bp-fastp-merged'
echo 'export trimmed_reads_dir=${deep_dive_dir}/E-Peve/output/06.2-Peve-sRNAseq-trimming-31bp-fastp-merged/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='*-31bp-merged.fq.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_02/shedurkin/deep-dive
export output_dir_top=${deep_dive_dir}/E-Peve/output/09.2-Peve-sRNAseq-miRTrace-31bp-fastp-merged
export trimmed_reads_dir=${deep_dive_dir}/E-Peve/output/06.2-Peve-sRNAseq-trimming-31bp-fastp-merged/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='*-31bp-merged.fq.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"
mirtrace.config already exists. Nothing to do.
/home/shared/8TB_HDD_02/shedurkin/deep-dive/E-Peve/output/06.2-Peve-sRNAseq-trimming-31bp-fastp-merged/trimmed-reads/sRNA-POR-73-S1-TP2-fastp-adapters-polyG-31bp-merged.fq.gz,sRNA-POR-73_1
/home/shared/8TB_HDD_02/shedurkin/deep-dive/E-Peve/output/06.2-Peve-sRNAseq-trimming-31bp-fastp-merged/trimmed-reads/sRNA-POR-79-S1-TP2-fastp-adapters-polyG-31bp-merged.fq.gz,sRNA-POR-79_2
/home/shared/8TB_HDD_02/shedurkin/deep-dive/E-Peve/output/06.2-Peve-sRNAseq-trimming-31bp-fastp-merged/trimmed-reads/sRNA-POR-82-S1-TP2-fastp-adapters-polyG-31bp-merged.fq.gz,sRNA-POR-82_1
,--_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 3 sample(s).
NOTE: reusing existing output directory, outdated files may be present.
Run complete. Processed 3 sample(s) in 23 s.
Reports written to /home/shared/8TB_HDD_02/shedurkin/deep-dive/E-Peve/output/09.2-Peve-sRNAseq-miRTrace-31bp-fastp-merged/
For information about citing our paper, run miRTrace in mode "cite".
real 0m23.795s
user 1m5.348s
sys 0m2.158s
/home/shared/8TB_HDD_02/shedurkin/deep-dive/E-Peve/output/09.2-Peve-sRNAseq-miRTrace-31bp-fastp-merged
├── [ 573] mirtrace.config
├── [298K] mirtrace-report.html
├── [ 269] mirtrace-stats-contamination_basic.tsv
├── [ 365] mirtrace-stats-contamination_detailed.tsv
└── [4.0K] qc_passed_reads.all.collapsed
├── [ 68M] sRNA-POR-73-S1-TP2-fastp-adapters-polyG-31bp-merged.fasta
├── [108M] sRNA-POR-79-S1-TP2-fastp-adapters-polyG-31bp-merged.fasta
└── [129M] sRNA-POR-82-S1-TP2-fastp-adapters-polyG-31bp-merged.fasta
1 directory, 7 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: Table 4.2: 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
|
<span style=” border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: white !important;” >0</span>
|
<span style=” border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: white !important;” >0</span>
|
<span style=” border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: white !important;” >0</span>
|
<span style=” border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: white !important;” >0</span>
|
<span style=” border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;” >1</span>
|
<span style=” border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: white !important;” >0</span>
|
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.
LS0tCnRpdGxlOiAiMDkuMi1QZXZlLXNSTkFzZXEtbWlSVHJhY2UtMzFicC1mYXN0cC1tZXJnZWQiCmF1dGhvcjogIkthdGhsZWVuIER1cmtpbiIKZGF0ZTogIjIwMjQtMDQtMTEiCm91dHB1dDogCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICBnaXRodWJfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQphbHdheXNfYWxsb3dfaHRtbDogdHJ1ZQpiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliCmxpbmstY2l0YXRpb25zOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShkcGx5cikKbGlicmFyeShyZXRpY3VsYXRlKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsICAgICAgICAgIyBEaXNwbGF5IGNvZGUgY2h1bmtzCiAgZXZhbCA9IEZBTFNFLCAgICAgICAgIyBFdmFsdWF0ZSBjb2RlIGNodW5rcwogIHdhcm5pbmcgPSBGQUxTRSwgICAgICMgSGlkZSB3YXJuaW5ncwogIG1lc3NhZ2UgPSBGQUxTRSwgICAgICMgSGlkZSBtZXNzYWdlcwogIGNvbW1lbnQgPSAiIiAgICAgICAgICMgUHJldmVudHMgYXBwZW5kaW5nICcjIycgdG8gYmVnaW5uaW5nIG9mIGxpbmVzIGluIGNvZGUgb3V0cHV0CikKYGBgCgpVc2UgW21pUlRyYWNlXShodHRwczovL2dpdGh1Yi5jb20vZnJpZWRsYW5kZXJsYWIvbWlydHJhY2UpIFtAa2FuZzIwMThdIHRvIGlkZW50aWZ5IHRheG9ub21pYyBvcmlnaW5zIG9mIG1pUk5BIHNlcXVlbmNpbmcgZGF0YS4KCk5PVEU6IFRoaXMgcmVxdWlyZXMgeW91IHRvIGhhdmUgcHJldmlvdXNseSBydW4gW2AwNi4yLVBldmUtc1JOQXNlcS10cmltbWluZy0zMWJwLWZhc3RwLW1lcmdlZC5SbWRgXShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL0UtUGV2ZS9jb2RlLzA2LjItUGV2ZS1zUk5Bc2VxLXRyaW1taW5nLTMxYnAtZmFzdHAtbWVyZ2VkLlJtZCksIGFzIHRoZSBjb2RlIHJlbGllcyBvbiB0aGUgdHJpbW1lZCBhbmQgbWVyZ2VkIHJlYWRzIG91dHB1dCBmcm9tIHRoYXQgY29kZS4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKSW5wdXRzOgoKLSAgIFRyaW1tZWQgc1JOQXNlcSBGYXN0UXMgZ2VuZXJhdGVkIGJ5IFtgMDYuMi1QZXZlLXNSTkFzZXEtdHJpbW1pbmctMzFicC1mYXN0cC1tZXJnZWQuUm1kYF0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9FLVBldmUvY29kZS8wNi4yLVBldmUtc1JOQXNlcS10cmltbWluZy0zMWJwLWZhc3RwLW1lcmdlZC5SbWQpCgogICAgLSAgIEZpbGVuYW1lcyBmb3JtYXR0ZWQ6IGAqLTMxYnAtbWVyZ2VkLmZxLmd6YAoKT3V0cHV0czoKCi0gICBgbWlydHJhY2UuY29uZmlnYDogQSBbbWlSVHJhY2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9mcmllZGxhbmRlcmxhYi9taXJ0cmFjZSkgY29uZmlnIGZpbGUuIEEgY29tbWEtc2VwYXJhdGVkIGZpbGUgd2l0aCB0aGlzIGxheW91dCAob25lIEZhc3RRIHBlciBsaW5lKTogYC9wYXRoL3RvL2Zhc3RxLGN1c3RvbV9zYW1wbGVfbmFtZWAKCi0gICAiQ29sbGFwc2VkIiAoaS5lLiB1bmlxdWUgc2VxdWVuY2VzIG9ubHkpIEZhc3RBIGZvciBlYWNoIGNvcnJlc3BvbmRpbmcgaW5wdXQgRmFzdFEuCgotICAgYG1pcnRyYWNlLXJlcG9ydC5odG1sYDogSFRNTC1mb3JtYXR0ZWQgcmVwb3J0IGdlbmVyYXRlZCBieSBbbWlSVHJhY2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9mcmllZGxhbmRlcmxhYi9taXJ0cmFjZSkuCgotICAgYG1pcnRyYWNlLXN0YXRzLWNvbnRhbWluYXRpb25fYmFzaWMudHN2YDogVGFiLWRlbGltaXRlZCByZXBvcnQgd2l0aCBjb3VudHMgb2Ygc2VxdWVuY2VzIGZyb20gZWFjaCBjb2xsYXBzZWQgRmFzdEFzIGhhdmluZyBtYXRjaGVzIHRvIGtub3duIG1pUk5BcyB3aXRoaW4gZWFjaCBvZiB0aGUgW21pUlRyYWNlXShodHRwczovL2dpdGh1Yi5jb20vZnJpZWRsYW5kZXJsYWIvbWlydHJhY2UpIENsYWRlcy4KCi0gICBgbWlydHJhY2Utc3RhdHMtY29udGFtaW5hdGlvbl9kZXRhaWxlZC5jc3ZgOiBUYWItZGVsaW1pdGVkIHJlcG9ydCBvZiAqb25seSogQ2xhZGVzIHdpdGggd2hpY2ggc2VxdWVuY2VzIHdlcmUgbWF0Y2hlZCwgYWxvbmcgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBtaVJOQSBmYW1pbGllcyBpbiBlYWNoIGNsYWRlLCBhbmQgdGhlIHNlcXVlbmNlIGNvdW50cy4KCiMgQ3JlYXRlIGEgQmFzaCB2YXJpYWJsZXMgZmlsZQoKVGhpcyBhbGxvd3MgdXNhZ2Ugb2YgQmFzaCB2YXJpYWJsZXMgYWNyb3NzIFIgTWFya2Rvd24gY2h1bmtzLgoKYGBge3Igc2F2ZS1iYXNoLXZhcmlhYmxlcy10by1ydmFycy1maWxlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CnsKZWNobyAiIyMjIyBBc3NpZ24gVmFyaWFibGVzICMjIyMiCmVjaG8gIiIKCmVjaG8gIiMgRGF0YSBkaXJlY3RvcmllcyIKZWNobyAnZXhwb3J0IGRlZXBfZGl2ZV9kaXI9L2hvbWUvc2hhcmVkLzhUQl9IRERfMDIvc2hlZHVya2luL2RlZXAtZGl2ZScKZWNobyAnZXhwb3J0IG91dHB1dF9kaXJfdG9wPSR7ZGVlcF9kaXZlX2Rpcn0vRS1QZXZlL291dHB1dC8wOS4yLVBldmUtc1JOQXNlcS1taVJUcmFjZS0zMWJwLWZhc3RwLW1lcmdlZCcKZWNobyAnZXhwb3J0IHRyaW1tZWRfcmVhZHNfZGlyPSR7ZGVlcF9kaXZlX2Rpcn0vRS1QZXZlL291dHB1dC8wNi4yLVBldmUtc1JOQXNlcS10cmltbWluZy0zMWJwLWZhc3RwLW1lcmdlZC90cmltbWVkLXJlYWRzJwplY2hvICIiCgplY2hvICIjIFBhdGhzIHRvIHByb2dyYW1zIgplY2hvICdleHBvcnQgbWlydHJhY2U9L2hvbWUvc2FtL3Byb2dyYW1zL21hbWJhZm9yZ2UvZW52cy9taVJUcmFjZV9lbnYvYmluL21pcnRyYWNlJwplY2hvICIiCgplY2hvICIjIFNldCBudW1iZXIgb2YgQ1BVcyB0byB1c2UiCmVjaG8gJ2V4cG9ydCB0aHJlYWRzPTQwJwplY2hvICIiCgplY2hvICJleHBvcnQgZmFzdHFfcGF0dGVybj0nKi0zMWJwLW1lcmdlZC5mcS5neiciCgplY2hvICIjIFByb2dyYW1zIGFzc29jaWF0aXZlIGFycmF5IgplY2hvICJkZWNsYXJlIC1BIHByb2dyYW1zX2FycmF5IgplY2hvICJwcm9ncmFtc19hcnJheT0oIgplY2hvICdbbWlydHJhY2VdPSIke21pcnRyYWNlfSInCmVjaG8gIikiCn0gPiAuYmFzaHZhcnMKCmNhdCAuYmFzaHZhcnMKYGBgCgojIENyZWF0ZSBbbWlSVHJhY2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9mcmllZGxhbmRlcmxhYi9taXJ0cmFjZSkgY29uZmlnIGZpbGUKCmBgYHtyIGNyZWF0ZS1jb25maWctZmlsZSwgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyBEZWNsYXJlIGFycmF5CmZhc3RxX2FycmF5PSgpCgojIFBvcHVsYXRlIGFycmF5CmZhc3RxX2FycmF5PSgke3RyaW1tZWRfcmVhZHNfZGlyfS8ke2Zhc3RxX3BhdHRlcm59KQoKIyBMb29wIHRocm91Z2ggcmVhZCBwYWlycwojIEluY3JlbWVudCBieSAyIHRvIHByb2Nlc3MgbmV4dCBwYWlyIG9mIEZhc3RRIGZpbGVzCmlmIFsgLWYgIiR7b3V0cHV0X2Rpcl90b3B9L21pcnRyYWNlLmNvbmZpZyIgXTsgdGhlbgogIGVjaG8gIm1pcnRyYWNlLmNvbmZpZyBhbHJlYWR5IGV4aXN0cy4gTm90aGluZyB0byBkby4iCiAgCmVsc2UKCiAgZm9yICgoIGk9MDsgaTwkeyNmYXN0cV9hcnJheVtAXX0gOyBpKz0yICkpCiAgZG8KICAgICMgVXNlIGZpcnN0IHRocmVlIHBhcnRzIG9mIGZpbGVuYW1lIHRvIGNyZWF0ZSBzaG9ydCBzYW1wbGUgbmFtZQogICAgUjFfbmFtZT0kKGVjaG8gIiR7ZmFzdHFfYXJyYXlbaV0jIyovfSIgfCBhd2sgLUYgIi0iICd7cHJpbnQgJDEiLSIkMiItIiQzfScpCiAgICBSMl9uYW1lPSQoZWNobyAiJHtmYXN0cV9hcnJheVtpKzFdIyMqL30iIHwgYXdrIC1GICItIiAne3ByaW50ICQxIi0iJDIiLSIkM30nKQogICAgZWNobyAiJHtmYXN0cV9hcnJheVtpXX0sJHtSMV9uYW1lfV8xIgogICAgZWNobyAiJHtmYXN0cV9hcnJheVtpKzFdfSwke1IyX25hbWV9XzIiCiAgZG9uZSA+PiAiJHtvdXRwdXRfZGlyX3RvcH0vbWlydHJhY2UuY29uZmlnIgoKZmkKCmNhdCAiJHtvdXRwdXRfZGlyX3RvcH0vbWlydHJhY2UuY29uZmlnIgpgYGAKCiMgUnVuIFttaVJUcmFjZV0oaHR0cHM6Ly9naXRodWIuY29tL2ZyaWVkbGFuZGVybGFiL21pcnRyYWNlKQoKYGBge3IgcnVuLW1pcnRyYWNlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgp0aW1lIFwKJHtwcm9ncmFtc19hcnJheVttaXJ0cmFjZV19IHRyYWNlIFwKLS1jb25maWcgJHtvdXRwdXRfZGlyX3RvcH0vbWlydHJhY2UuY29uZmlnIFwKLS13cml0ZS1mYXN0YSBcCi0tbnVtLXRocmVhZHMgJHt0aHJlYWRzfSBcCi0tb3V0cHV0LWRpciAke291dHB1dF9kaXJfdG9wfSBcCi0tZm9yY2UKCnRyZWUgLWggJHtvdXRwdXRfZGlyX3RvcH0KYGBgCgojIFJlc3VsdHMKCiMjIFJlYWQgaW4gdGFibGUgYXMgZGF0YSBmcmFtZQoKYGBge3IgcmVhZC10YWJsZSwgZXZhbD1UUlVFfQptaXJ0cmFjZS5kZXRhaWxlZC5kZiA8LSByZWFkLmNzdigiLi4vb3V0cHV0LzA5LVBldmUtc1JOQXNlcS1taVJUcmFjZS9taXJ0cmFjZS1zdGF0cy1jb250YW1pbmF0aW9uX2RldGFpbGVkLnRzdiIsIHNlcCA9ICJcdCIsIGhlYWRlciA9IFRSVUUpCgpzdHIobWlydHJhY2UuZGV0YWlsZWQuZGYpCmBgYAoKIyMgTnVtYmVyIG9mIHNhbXBsZXMgd2l0aCBtYXRjaGVzCgpJTVBPUlRBTlQ6IENoYW5nZSBgc3RhcnRzX3dpdGgoKWAgdG8gbWF0Y2ggcHJlZml4IG9mIGlucHV0IHNSTkFzZXEgcmVhZHMhCgpgYGB7ciBjb3VudHMtc2FtcGxlcy13aXRoLW1hdGNoZXMsIGV2YWw9VFJVRX0KIyBTZWxlY3QgY29sdW1ucyBjb3JyZXNwb25kaW5nIHRvIHNhbXBsZSBuYW1lcwpzYW1wbGVfY29sdW1ucyA8LSBtaXJ0cmFjZS5kZXRhaWxlZC5kZiAlPiUKICBzZWxlY3Qoc3RhcnRzX3dpdGgoInNSTkEuUE9SLiIpKQoKIyBDYWxjdWxhdGUgdGhlIHN1bSBmb3IgZWFjaCBjb2x1bW4Kc2FtcGxlX3N1bXMgPC0gY29sU3VtcyhzYW1wbGVfY29sdW1ucykKCiMgQ291bnQgdGhlIG51bWJlciBvZiBjb2x1bW5zIHdpdGggYSBzdW0gZ3JlYXRlciB0aGFuIDAKc2FtcGxlc193aXRoX3N1bV9ndF8wIDwtIHN1bShzYW1wbGVfc3VtcyA+IDApCgpwYXN0ZSgiTnVtYmVyIG9mIHNhbXBsZXMgd2l0aCBtYXRjaGVzOiAiLCBzYW1wbGVzX3dpdGhfc3VtX2d0XzApCmBgYAoKIyMgUGVyY2VudGFnZSBvZiBzYW1wbGVzIHdpdGggbWF0Y2hlcwoKYGBge3IgcGVyY2VudGFnZS1zYW1wbGVzLXdpdGgtbWF0Y2hlcywgZXZhbD1UUlVFfQojIFRvdGFsIG51bWJlciBvZiBzYW1wbGVzIChjb2x1bW5zKQp0b3RhbF9zYW1wbGVzIDwtIG5jb2woc2FtcGxlX2NvbHVtbnMpCgojIFBlcmNlbnRhZ2Ugb2Ygc2FtcGxlcyB3aXRoIHN1bXMgZ3JlYXRlciB0aGFuIDAKcGVyY2VudGFnZV9zYW1wbGVzX2d0XzAgPC0gKHNhbXBsZXNfd2l0aF9zdW1fZ3RfMCAvIHRvdGFsX3NhbXBsZXMpICogMTAwCgpwYXN0ZSgiUGVyY2VudGFnZSBvZiBzYW1wbGVzIHdpdGggbWF0Y2hlczogIiwgcGVyY2VudGFnZV9zYW1wbGVzX2d0XzApCmBgYAoKIyMgTnVtYmVyIG9mIGNsYWRlcyB3aXRoIG1hdGNoZXMKCmBgYHtyIGRpc3RpbmN0LWNsYWRlcywgZXZhbD1UUlVFLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1oaWRlJ30KCnVuaXF1ZV9jbGFkZV9jb3VudCA8LSBtaXJ0cmFjZS5kZXRhaWxlZC5kZiAlPiUKICBkaXN0aW5jdChDTEFERSkgJT4lICAgICMgR2V0IHVuaXF1ZSBlbnRyaWVzIGluIENMQURFIGNvbHVtbgogIGNvdW50KCkgICAgICAgICAgICAgICAjIENvdW50IHRoZSBudW1iZXIgb2YgdW5pcXVlIGVudHJpZXMKCgoKcGFzdGUoIk51bWJlciBvZiBjbGFkZXMgd2l0aCBtYXRjaGVzOiIsIHVuaXF1ZV9jbGFkZV9jb3VudCkKCgpgYGAKCiMjIFttaVJUcmFjZV0oaHR0cHM6Ly9naXRodWIuY29tL2ZyaWVkbGFuZGVybGFiL21pcnRyYWNlKSB0YWJsZQoKVG8gbWFrZSB0aGVtIGVhc2llciB0byBzZWUsIGNvdW50cyBcPiAwIGFyZSBoaWdobGlnaHRlZCBpbiBncmVlbi4KCmBgYHtyIG1pcnRyYWNlLW91dHB1dC10YWJsZSwgZXZhbD1UUlVFLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1oaWRlJ30KCm1pcnRyYWNlLmRldGFpbGVkLmRmICU+JQogIG11dGF0ZSgKICAgIGFjcm9zcygKICAgICAgc3RhcnRzX3dpdGgoInNSTkEiKSwKICAgICAgfmNlbGxfc3BlYygKICAgICAgICAuLAogICAgICAgIGJhY2tncm91bmQgPSBpZmVsc2UoCiAgICAgICAgICAuID4gMCwKICAgICAgICAgICJsaWdodGdyZWVuIiwKICAgICAgICAgICJ3aGl0ZSIKICAgICAgICAgICkKICAgICAgICApCiAgICAgICkKICAgICkgJT4lCiAga2FibGUoZXNjYXBlID0gRiwgY2FwdGlvbiA9ICJDbGFkZXMgaWRlbnRpZmllZCBhcyBoYXZpbmcgc1JOQXNlcSBtYXRjaGVzLiIpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiKSAlPiUgCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjUwMHB4IikKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgQ2l0YXRpb25z