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.

1 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}"
)

2 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

3 Run miRTrace

# 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

4 Results

4.1 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

4.2 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"

4.3 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"

4.4 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"

4.5 miRTrace table

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