Use miRTrace [@kang2018] to identify taxonomic origins of miRNA sequencing data.

NOTE: This requires you to have previously run 08-Pmea-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_02/shedurkin/deep-dive'
echo 'export output_dir_top=${deep_dive_dir}/F-Pmea/output/09-Pmea-sRNAseq-miRTrace'
echo 'export trimmed_reads_dir=${deep_dive_dir}/F-Pmea/output/08-Pmea-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_02/shedurkin/deep-dive
export output_dir_top=${deep_dive_dir}/F-Pmea/output/09-Pmea-sRNAseq-miRTrace
export trimmed_reads_dir=${deep_dive_dir}/F-Pmea/output/08-Pmea-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"
mirtrace.config already exists. Nothing to do.
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-47-S1-TP2.flexbar_trim.25bp_1.fastq.gz,sRNA-POC-47_1
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-47-S1-TP2.flexbar_trim.25bp_2.fastq.gz,sRNA-POC-47_2
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-48-S1-TP2.flexbar_trim.25bp_1.fastq.gz,sRNA-POC-48_1
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-48-S1-TP2.flexbar_trim.25bp_2.fastq.gz,sRNA-POC-48_2
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-50-S1-TP2.flexbar_trim.25bp_1.fastq.gz,sRNA-POC-50_1
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-50-S1-TP2.flexbar_trim.25bp_2.fastq.gz,sRNA-POC-50_2
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-53-S1-TP2.flexbar_trim.25bp_1.fastq.gz,sRNA-POC-53_1
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-53-S1-TP2.flexbar_trim.25bp_2.fastq.gz,sRNA-POC-53_2
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-57-S1-TP2.flexbar_trim.25bp_1.fastq.gz,sRNA-POC-57_1
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/08-Pmea-sRNAseq-trimming/trimmed-reads/sRNA-POC-57-S1-TP2.flexbar_trim.25bp_2.fastq.gz,sRNA-POC-57_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 10 sample(s).
NOTE: reusing existing output directory, outdated files may be present.
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/09-Pmea-sRNAseq-miRTrace/qc_passed_reads.all.collapsed/sRNA-POC-50-S1-TP2.flexbar_trim.25bp_1.fasta (Permission denied)
I/O Error, aborting.

real    0m28.418s
user    4m19.668s
sys 0m7.212s
/home/shared/8TB_HDD_02/shedurkin/deep-dive/F-Pmea/output/09-Pmea-sRNAseq-miRTrace
├── [1.6K]  mirtrace.config
├── [302K]  mirtrace-report.html
├── [ 563]  mirtrace-stats-contamination_basic.tsv
├── [1.1K]  mirtrace-stats-contamination_detailed.tsv
└── [4.0K]  qc_passed_reads.all.collapsed
    ├── [ 71M]  sRNA-POC-47-S1-TP2.flexbar_trim.25bp_1.fasta
    ├── [ 89M]  sRNA-POC-47-S1-TP2.flexbar_trim.25bp_2.fasta
    ├── [ 75M]  sRNA-POC-48-S1-TP2.flexbar_trim.25bp_1.fasta
    ├── [ 84M]  sRNA-POC-48-S1-TP2.flexbar_trim.25bp_2.fasta
    ├── [ 68M]  sRNA-POC-50-S1-TP2.flexbar_trim.25bp_1.fasta
    ├── [ 83M]  sRNA-POC-50-S1-TP2.flexbar_trim.25bp_2.fasta
    ├── [ 99M]  sRNA-POC-53-S1-TP2.flexbar_trim.25bp_1.fasta
    ├── [116M]  sRNA-POC-53-S1-TP2.flexbar_trim.25bp_2.fasta
    ├── [120M]  sRNA-POC-57-S1-TP2.flexbar_trim.25bp_1.fasta
    └── [129M]  sRNA-POC-57-S1-TP2.flexbar_trim.25bp_2.fasta

1 directory, 14 files

4 Results

4.1 Read in table as data frame

mirtrace.detailed.df <- read.csv("../output/09-Pmea-sRNAseq-miRTrace/mirtrace-stats-contamination_detailed.tsv", sep = "\t", header = TRUE)

str(mirtrace.detailed.df)
'data.frame':   8 obs. of  14 variables:
 $ CLADE        : chr  "nematode" "insects" "insects" "lophotrochozoa" ...
 $ FAMILY_ID    : int  86 14 957 1996 2689 1994 1998 3122
 $ MIRBASE_IDS  : chr  "asu-miR-86,bma-miR-86,cbn-miR-86,cbr-miR-86,cel-miR-86,crm-miR-86,hco-miR-86,prd-miR-86,str-miR-86" "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__ "aae-miR-957,aga-miR-957,cqu-miR-957,dme-miR-957,dps-miR-957,dsi-miR-957,dvi-miR-957" "cte-miR-1996a" ...
 $ SEQ          : chr  "TAAGTGAATGCTTTGCCACA" "TCAGTCTTTTTCTCTCTCCT" "TGAAACCGTCCAAAACTGAG" "CTCAAGTGAGGTCAGTGCTG" ...
 $ sRNA.POC.47_1: int  0 0 0 0 2 0 1 0
 $ sRNA.POC.47_2: int  0 0 0 0 0 0 0 0
 $ sRNA.POC.48_1: int  0 2 0 0 0 0 0 0
 $ sRNA.POC.48_2: int  0 0 0 0 0 0 0 0
 $ sRNA.POC.50_1: int  0 0 0 0 0 0 0 0
 $ sRNA.POC.50_2: int  0 0 0 0 0 0 0 0
 $ sRNA.POC.53_1: int  0 0 1 1 0 0 0 1
 $ sRNA.POC.53_2: int  0 0 0 0 0 0 0 0
 $ sRNA.POC.57_1: int  3 2 0 0 0 1 0 0
 $ sRNA.POC.57_2: int  0 0 0 0 0 0 0 0

4.2 Number of samples with matches

# Select columns corresponding to sample names
sample_columns <- mirtrace.detailed.df %>%
  select(starts_with("sRNA.POC."))

# 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:  4"

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:  40"

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: 4"

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.POC.47_1 sRNA.POC.47_2 sRNA.POC.48_1 sRNA.POC.48_2 sRNA.POC.50_1 sRNA.POC.50_2 sRNA.POC.53_1 sRNA.POC.53_2 sRNA.POC.57_1 sRNA.POC.57_2
nematode 86 asu-miR-86,bma-miR-86,cbn-miR-86,cbr-miR-86,cel-miR-86,crm-miR-86,hco-miR-86,prd-miR-86,str-miR-86 TAAGTGAATGCTTTGCCACA 0 0 0 0 0 0 0 0 3 0
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 2 0 0 0 0 0 2 0
insects 957 aae-miR-957,aga-miR-957,cqu-miR-957,dme-miR-957,dps-miR-957,dsi-miR-957,dvi-miR-957 TGAAACCGTCCAAAACTGAG 0 0 0 0 0 0 1 0 0 0
lophotrochozoa 1996 cte-miR-1996a CTCAAGTGAGGTCAGTGCTG 0 0 0 0 0 0 1 0 0 0
lophotrochozoa 2689 cte-miR-2689 TATCCTGGCCTGCAAGTGCA 2 0 0 0 0 0 0 0 0 0
lophotrochozoa 1994 cla-miR-1994,cte-miR-1994,lgi-miR-1994a,lgi-miR-1994b TGAGACAGTGTGTCCTCCCT 0 0 0 0 0 0 0 0 1 0
lophotrochozoa 1998 cte-miR-1998 TTGAACGCAGAGATGTACAT 1 0 0 0 0 0 0 0 0 0
primates 3122 hsa-miR-3122 GTTGGGACAAGAGGACGGTC 0 0 0 0 0 0 1 0 0 0

5 Citations

LS0tCnRpdGxlOiAiMDktUG1lYS1zUk5Bc2VxLW1pUlRyYWNlIgphdXRob3I6ICJTYW0gV2hpdGUgKG1vZGlmaWVkIGJ5IEsgRHVya2luIGZvciBQLiBtZWFuZHJpbmEgYW5hbHlzaXMpIgpkYXRlOiAiMjAyMy0xMS0xNCIKYWx3YXlzX2FsbG93X2h0bWw6IHRydWUKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGh0bWxfcHJldmlldzogdHJ1ZSAgCiNiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShkcGx5cikKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBGQUxTRSwgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAgIyBQcmV2ZW50cyBhcHBlbmRpbmcgJyMjJyB0byBiZWdpbm5pbmcgb2YgbGluZXMgaW4gY29kZSBvdXRwdXQKKQoKYGBgCgpVc2UgW21pUlRyYWNlXShodHRwczovL2dpdGh1Yi5jb20vZnJpZWRsYW5kZXJsYWIvbWlydHJhY2UpIFtAa2FuZzIwMThdIHRvIGlkZW50aWZ5IHRheG9ub21pYyBvcmlnaW5zIG9mIG1pUk5BIHNlcXVlbmNpbmcgZGF0YS4KCk5PVEU6IFRoaXMgcmVxdWlyZXMgeW91IHRvIGhhdmUgcHJldmlvdXNseSBydW4gW2AwOC1QbWVhLXNSTkFzZXEtdHJpbW1pbmcuUm1kYF0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9GLVBtZWEvY29kZS8wOC1QbWVhLXNSTkFzZXEtdHJpbW1pbmcuUm1kKSwgYXMgdGhlIGNvZGUgcmVsaWVzIG9uIHRoZSB0cmltbWVkIHJlYWRzIG91dHB1dCBmcm9tIHRoYXQgY29kZS4KCi0tLQoKCklucHV0czoKCi0gVHJpbW1lZCBzUk5Bc2VxIEZhc3RRcyBnZW5lcmF0ZWQgYnkgW2AwOC1QbWVhLXNSTkFzZXEtdHJpbW1pbmcuUm1kYF0oaHR0cHM6Ly9naXRodWIuY29tL3Vyb2wtZTUvZGVlcC1kaXZlL2Jsb2IvbWFpbi9GLVBtZWEvY29kZS8wOC1QbWVhLXNSTkFzZXEtdHJpbW1pbmcuUm1kKQoKICAtIEZpbGVuYW1lcyBmb3JtYXR0ZWQ6IGAqZmxleGJhcl90cmltLjI1YnAqLmd6YAogIApPdXRwdXRzOgoKLSBgbWlydHJhY2UuY29uZmlnYDogQSBbbWlSVHJhY2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9mcmllZGxhbmRlcmxhYi9taXJ0cmFjZSkgY29uZmlnIGZpbGUuIEEgY29tbWEtc2VwYXJhdGVkIGZpbGUgd2l0aCB0aGlzIGxheW91dCAob25lIEZhc3RRIHBlciBsaW5lKTogYC9wYXRoL3RvL2Zhc3RxLGN1c3RvbV9zYW1wbGVfbmFtZWAKCi0gIkNvbGxhcHNlZCIgKGkuZS4gdW5pcXVlIHNlcXVlbmNlcyBvbmx5KSBGYXN0QSBmb3IgZWFjaCBjb3JyZXNwb25kaW5nIGlucHV0IEZhc3RRLgoKLSBgbWlydHJhY2UtcmVwb3J0Lmh0bWxgOiBIVE1MLWZvcm1hdHRlZCByZXBvcnQgZ2VuZXJhdGVkIGJ5IFttaVJUcmFjZV0oaHR0cHM6Ly9naXRodWIuY29tL2ZyaWVkbGFuZGVybGFiL21pcnRyYWNlKS4KCi0gYG1pcnRyYWNlLXN0YXRzLWNvbnRhbWluYXRpb25fYmFzaWMudHN2YDogVGFiLWRlbGltaXRlZCByZXBvcnQgd2l0aCBjb3VudHMgb2Ygc2VxdWVuY2VzIGZyb20gZWFjaCBjb2xsYXBzZWQgRmFzdEFzIGhhdmluZyBtYXRjaGVzIHRvIGtub3duIG1pUk5BcyB3aXRoaW4gZWFjaCBvZiB0aGUgW21pUlRyYWNlXShodHRwczovL2dpdGh1Yi5jb20vZnJpZWRsYW5kZXJsYWIvbWlydHJhY2UpIENsYWRlcy4KCi0gYG1pcnRyYWNlLXN0YXRzLWNvbnRhbWluYXRpb25fZGV0YWlsZWQuY3N2YDogVGFiLWRlbGltaXRlZCByZXBvcnQgb2YgX29ubHlfIENsYWRlcyB3aXRoIHdoaWNoIHNlcXVlbmNlcyB3ZXJlIG1hdGNoZWQsIGFsb25nIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgbWlSTkEgZmFtaWxpZXMgaW4gZWFjaCBjbGFkZSwgYW5kIHRoZSBzZXF1ZW5jZSBjb3VudHMuCgoKIyBDcmVhdGUgYSBCYXNoIHZhcmlhYmxlcyBmaWxlCgpUaGlzIGFsbG93cyB1c2FnZSBvZiBCYXNoIHZhcmlhYmxlcyBhY3Jvc3MgUiBNYXJrZG93biBjaHVua3MuCgpgYGB7ciBzYXZlLWJhc2gtdmFyaWFibGVzLXRvLXJ2YXJzLWZpbGUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KewplY2hvICIjIyMjIEFzc2lnbiBWYXJpYWJsZXMgIyMjIyIKZWNobyAiIgoKZWNobyAiIyBEYXRhIGRpcmVjdG9yaWVzIgplY2hvICdleHBvcnQgZGVlcF9kaXZlX2Rpcj0vaG9tZS9zaGFyZWQvOFRCX0hERF8wMi9zaGVkdXJraW4vZGVlcC1kaXZlJwplY2hvICdleHBvcnQgb3V0cHV0X2Rpcl90b3A9JHtkZWVwX2RpdmVfZGlyfS9GLVBtZWEvb3V0cHV0LzA5LVBtZWEtc1JOQXNlcS1taVJUcmFjZScKZWNobyAnZXhwb3J0IHRyaW1tZWRfcmVhZHNfZGlyPSR7ZGVlcF9kaXZlX2Rpcn0vRi1QbWVhL291dHB1dC8wOC1QbWVhLXNSTkFzZXEtdHJpbW1pbmcvdHJpbW1lZC1yZWFkcycKZWNobyAiIgoKZWNobyAiIyBQYXRocyB0byBwcm9ncmFtcyIKZWNobyAnZXhwb3J0IG1pcnRyYWNlPS9ob21lL3NhbS9wcm9ncmFtcy9tYW1iYWZvcmdlL2VudnMvbWlSVHJhY2VfZW52L2Jpbi9taXJ0cmFjZScKZWNobyAiIgoKZWNobyAiIyBTZXQgbnVtYmVyIG9mIENQVXMgdG8gdXNlIgplY2hvICdleHBvcnQgdGhyZWFkcz00MCcKZWNobyAiIgoKZWNobyAiZXhwb3J0IGZhc3RxX3BhdHRlcm49JypmbGV4YmFyX3RyaW0uMjVicCouZ3onIgoKZWNobyAiIyBQcm9ncmFtcyBhc3NvY2lhdGl2ZSBhcnJheSIKZWNobyAiZGVjbGFyZSAtQSBwcm9ncmFtc19hcnJheSIKZWNobyAicHJvZ3JhbXNfYXJyYXk9KCIKZWNobyAnW21pcnRyYWNlXT0iJHttaXJ0cmFjZX0iJwplY2hvICIpIgp9ID4gLmJhc2h2YXJzCgpjYXQgLmJhc2h2YXJzCmBgYAoKIyBDcmVhdGUgW21pUlRyYWNlXShodHRwczovL2dpdGh1Yi5jb20vZnJpZWRsYW5kZXJsYWIvbWlydHJhY2UpIGNvbmZpZyBmaWxlCmBgYHtyIGNyZWF0ZS1jb25maWctZmlsZSwgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyBEZWNsYXJlIGFycmF5CmZhc3RxX2FycmF5PSgpCgojIFBvcHVsYXRlIGFycmF5CmZhc3RxX2FycmF5PSgke3RyaW1tZWRfcmVhZHNfZGlyfS8ke2Zhc3RxX3BhdHRlcm59KQoKIyBMb29wIHRocm91Z2ggcmVhZCBwYWlycwojIEluY3JlbWVudCBieSAyIHRvIHByb2Nlc3MgbmV4dCBwYWlyIG9mIEZhc3RRIGZpbGVzCmlmIFsgLWYgIiR7b3V0cHV0X2Rpcl90b3B9L21pcnRyYWNlLmNvbmZpZyIgXTsgdGhlbgogIGVjaG8gIm1pcnRyYWNlLmNvbmZpZyBhbHJlYWR5IGV4aXN0cy4gTm90aGluZyB0byBkby4iCiAgCmVsc2UKCiAgZm9yICgoIGk9MDsgaTwkeyNmYXN0cV9hcnJheVtAXX0gOyBpKz0yICkpCiAgZG8KICAgICMgVXNlIGZpcnN0IHRocmVlIHBhcnRzIG9mIGZpbGVuYW1lIHRvIGNyZWF0ZSBzaG9ydCBzYW1wbGUgbmFtZQogICAgUjFfbmFtZT0kKGVjaG8gIiR7ZmFzdHFfYXJyYXlbaV0jIyovfSIgfCBhd2sgLUYgIi0iICd7cHJpbnQgJDEiLSIkMiItIiQzfScpCiAgICBSMl9uYW1lPSQoZWNobyAiJHtmYXN0cV9hcnJheVtpKzFdIyMqL30iIHwgYXdrIC1GICItIiAne3ByaW50ICQxIi0iJDIiLSIkM30nKQogICAgZWNobyAiJHtmYXN0cV9hcnJheVtpXX0sJHtSMV9uYW1lfV8xIgogICAgZWNobyAiJHtmYXN0cV9hcnJheVtpKzFdfSwke1IyX25hbWV9XzIiCiAgZG9uZSA+PiAiJHtvdXRwdXRfZGlyX3RvcH0vbWlydHJhY2UuY29uZmlnIgoKZmkKCmNhdCAiJHtvdXRwdXRfZGlyX3RvcH0vbWlydHJhY2UuY29uZmlnIgpgYGAKCiMgUnVuIFttaVJUcmFjZV0oaHR0cHM6Ly9naXRodWIuY29tL2ZyaWVkbGFuZGVybGFiL21pcnRyYWNlKQpgYGB7ciBydW4tbWlydHJhY2UsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCnRpbWUgXAoke3Byb2dyYW1zX2FycmF5W21pcnRyYWNlXX0gdHJhY2UgXAotLWNvbmZpZyAke291dHB1dF9kaXJfdG9wfS9taXJ0cmFjZS5jb25maWcgXAotLXdyaXRlLWZhc3RhIFwKLS1udW0tdGhyZWFkcyAke3RocmVhZHN9IFwKLS1vdXRwdXQtZGlyICR7b3V0cHV0X2Rpcl90b3B9IFwKLS1mb3JjZQoKdHJlZSAtaCAke291dHB1dF9kaXJfdG9wfQpgYGAKCgojIFJlc3VsdHMKCiMjIFJlYWQgaW4gdGFibGUgYXMgZGF0YSBmcmFtZQpgYGB7ciByZWFkLXRhYmxlLCBldmFsPVRSVUV9Cm1pcnRyYWNlLmRldGFpbGVkLmRmIDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvMDktUG1lYS1zUk5Bc2VxLW1pUlRyYWNlL21pcnRyYWNlLXN0YXRzLWNvbnRhbWluYXRpb25fZGV0YWlsZWQudHN2Iiwgc2VwID0gIlx0IiwgaGVhZGVyID0gVFJVRSkKCnN0cihtaXJ0cmFjZS5kZXRhaWxlZC5kZikKYGBgCgoKIyMgTnVtYmVyIG9mIHNhbXBsZXMgd2l0aCBtYXRjaGVzCmBgYHtyIGNvdW50cy1zYW1wbGVzLXdpdGgtbWF0Y2hlcywgZXZhbD1UUlVFfQojIFNlbGVjdCBjb2x1bW5zIGNvcnJlc3BvbmRpbmcgdG8gc2FtcGxlIG5hbWVzCnNhbXBsZV9jb2x1bW5zIDwtIG1pcnRyYWNlLmRldGFpbGVkLmRmICU+JQogIHNlbGVjdChzdGFydHNfd2l0aCgic1JOQS5QT0MuIikpCgojIENhbGN1bGF0ZSB0aGUgc3VtIGZvciBlYWNoIGNvbHVtbgpzYW1wbGVfc3VtcyA8LSBjb2xTdW1zKHNhbXBsZV9jb2x1bW5zKQoKIyBDb3VudCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgd2l0aCBhIHN1bSBncmVhdGVyIHRoYW4gMApzYW1wbGVzX3dpdGhfc3VtX2d0XzAgPC0gc3VtKHNhbXBsZV9zdW1zID4gMCkKCnBhc3RlKCJOdW1iZXIgb2Ygc2FtcGxlcyB3aXRoIG1hdGNoZXM6ICIsIHNhbXBsZXNfd2l0aF9zdW1fZ3RfMCkKYGBgCiMjIFBlcmNlbnRhZ2Ugb2Ygc2FtcGxlcyB3aXRoIG1hdGNoZXMKYGBge3IgcGVyY2VudGFnZS1zYW1wbGVzLXdpdGgtbWF0Y2hlcywgZXZhbD1UUlVFfQojIFRvdGFsIG51bWJlciBvZiBzYW1wbGVzIChjb2x1bW5zKQp0b3RhbF9zYW1wbGVzIDwtIG5jb2woc2FtcGxlX2NvbHVtbnMpCgojIFBlcmNlbnRhZ2Ugb2Ygc2FtcGxlcyB3aXRoIHN1bXMgZ3JlYXRlciB0aGFuIDAKcGVyY2VudGFnZV9zYW1wbGVzX2d0XzAgPC0gKHNhbXBsZXNfd2l0aF9zdW1fZ3RfMCAvIHRvdGFsX3NhbXBsZXMpICogMTAwCgpwYXN0ZSgiUGVyY2VudGFnZSBvZiBzYW1wbGVzIHdpdGggbWF0Y2hlczogIiwgcGVyY2VudGFnZV9zYW1wbGVzX2d0XzApCmBgYAoKCiMjIE51bWJlciBvZiBjbGFkZXMgd2l0aCBtYXRjaGVzCmBgYHtyIGRpc3RpbmN0LWNsYWRlcywgZXZhbD1UUlVFLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1oaWRlJ30KCnVuaXF1ZV9jbGFkZV9jb3VudCA8LSBtaXJ0cmFjZS5kZXRhaWxlZC5kZiAlPiUKICBkaXN0aW5jdChDTEFERSkgJT4lICAgICMgR2V0IHVuaXF1ZSBlbnRyaWVzIGluIENMQURFIGNvbHVtbgogIGNvdW50KCkgICAgICAgICAgICAgICAjIENvdW50IHRoZSBudW1iZXIgb2YgdW5pcXVlIGVudHJpZXMKCgoKcGFzdGUoIk51bWJlciBvZiBjbGFkZXMgd2l0aCBtYXRjaGVzOiIsIHVuaXF1ZV9jbGFkZV9jb3VudCkKCgpgYGAKCgojIyBbbWlSVHJhY2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9mcmllZGxhbmRlcmxhYi9taXJ0cmFjZSkgdGFibGUKClRvIG1ha2UgdGhlbSBlYXNpZXIgdG8gc2VlLCBjb3VudHMgPiAwIGFyZSBoaWdobGlnaHRlZCBpbiBncmVlbi4KYGBge3IgbWlydHJhY2Utb3V0cHV0LXRhYmxlLCBldmFsPVRSVUUsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLWhpZGUnfQoKbWlydHJhY2UuZGV0YWlsZWQuZGYgJT4lCiAgbXV0YXRlKAogICAgYWNyb3NzKAogICAgICBzdGFydHNfd2l0aCgic1JOQSIpLAogICAgICB+Y2VsbF9zcGVjKAogICAgICAgIC4sCiAgICAgICAgYmFja2dyb3VuZCA9IGlmZWxzZSgKICAgICAgICAgIC4gPiAwLAogICAgICAgICAgImxpZ2h0Z3JlZW4iLAogICAgICAgICAgIndoaXRlIgogICAgICAgICAgKQogICAgICAgICkKICAgICAgKQogICAgKSAlPiUKICBrYWJsZShlc2NhcGUgPSBGLCBjYXB0aW9uID0gIkNsYWRlcyBpZGVudGlmaWVkIGFzIGhhdmluZyBzUk5Bc2VxIG1hdGNoZXMuIikgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIpICU+JSAKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiNTAwcHgiKQpgYGAKCiMgQ2l0YXRpb25zCgoK