1 Description

Use ShortStack (Axtell2013-xu?; Johnson et al. 2016; Shahid2014-lx?) to perform alignment of sRNAseq data and annotation of sRNA-producing genes.

Due to large file sizes of some of the input and output files, not all files can be sync’d to GitHub. A full backup of this repo is available here:


Inputs:

  • Requires trimmed sRNAseq files generated by 01.00-trimming-fastp-fastqc.Rmd

    • Filenames formatted: *fastp-adapters-polyG-31bp-merged.fq.gz
  • Genome FastA: GCF_026571515.1_ASM2657151v2_genomic.fna

  • MiRBase v22.1 FastA: mirbase-mature-v22.1.fa

Outputs:

Software requirements:

  • Utilizes a ShortStack Conda/Mamba environment, per the installation instructions.

Replace with name of your ShortStack environment and the path to the corresponding conda installation (find this after you’ve activated the environment).

E.g.

# Activate environment
conda activate ShortStack-4.1.1_env

# Find conda path
which conda

2 Set R variables

shortstack_conda_env_name <- c("ShortStack-4.1.1_env")
shortstack_cond_path <- c("/home/sam/programs/mambaforge/condabin/conda")

3 Create a Bash variables file

This allows usage of Bash variables across R Markdown chunks.

{
echo "#### Assign Variables ####"
echo ""

echo "# Trimmed FastQ naming pattern"
echo "export trimmed_fastqs_pattern='*fastp-adapters-polyG-31bp-merged.fq.gz'"

echo "# Data directories"
echo 'export repo_dir=/home/shared/8TB_HDD_01/sam/gitrepos/RobertsLab/project-clam-oa'
echo 'export repo_data_dir="${repo_dir}/data"'
echo 'export output_dir_top=${repo_dir}/output/02.00-ShortStack-31bp-fastp-merged'
echo 'export trimmed_fastqs_dir="${repo_dir}/output/01.00-trimming-fastp-fastqc"'
echo ""

echo "# Input/Output files"
echo 'export genome_fasta_dir=${repo_data_dir}/genome_files'
echo 'export genome_fasta_name="GCF_026571515.1_ASM2657151v2_genomic.fna"'
echo 'export shortstack_genome_fasta_name="GCF_026571515.1_ASM2657151v2_genomic.fa"'
echo 'export mirbase_mature_fasta=mirbase-mature-v22.1.fa'
echo 'export genome_fasta="${genome_fasta_dir}/${shortstack_genome_fasta_name}"'
echo ""


echo "# Set number of CPUs to use"
echo 'export threads=40'
echo ""

echo "# Initialize arrays"
echo 'export trimmed_fastqs_array=()'


} > .bashvars

cat .bashvars
#### Assign Variables ####

# Trimmed FastQ naming pattern
export trimmed_fastqs_pattern='*fastp-adapters-polyG-31bp-merged.fq.gz'
# Data directories
export repo_dir=/home/shared/8TB_HDD_01/sam/gitrepos/RobertsLab/project-clam-oa
export repo_data_dir="${repo_dir}/data"
export output_dir_top=${repo_dir}/output/02.00-ShortStack-31bp-fastp-merged
export trimmed_fastqs_dir="${repo_dir}/output/01.00-trimming-fastp-fastqc"

# Input/Output files
export genome_fasta_dir=${repo_data_dir}/genome_files
export genome_fasta_name="GCF_026571515.1_ASM2657151v2_genomic.fna"
export shortstack_genome_fasta_name="GCF_026571515.1_ASM2657151v2_genomic.fa"
export mirbase_mature_fasta=mirbase-mature-v22.1.fa
export genome_fasta="${genome_fasta_dir}/${shortstack_genome_fasta_name}"

# Set number of CPUs to use
export threads=40

# Initialize arrays
export trimmed_fastqs_array=()

4 Load ShortStack conda environment

If this is successful, the first line of output should show that the Python being used is the one in your [ShortStack](https://github.com/MikeAxtell/ShortStack conda environment path.

E.g.

python: /home/sam/programs/mambaforge/envs/mirmachine_env/bin/python

use_condaenv(condaenv = shortstack_conda_env_name, conda = shortstack_cond_path)

# Check successful env loading
py_config()
python:         /home/sam/programs/mambaforge/envs/ShortStack-4.1.1_env/bin/python
libpython:      /home/sam/programs/mambaforge/envs/ShortStack-4.1.1_env/lib/libpython3.12.so
pythonhome:     /home/sam/programs/mambaforge/envs/ShortStack-4.1.1_env:/home/sam/programs/mambaforge/envs/ShortStack-4.1.1_env
version:        3.12.8 | packaged by conda-forge | (main, Dec  5 2024, 14:24:40) [GCC 13.3.0]
numpy:          /home/sam/programs/mambaforge/envs/ShortStack-4.1.1_env/lib/python3.12/site-packages/numpy
numpy_version:  2.2.0

NOTE: Python version was forced by use_python() function

5 Run ShortStack

5.1 Excecute ShortStack command

Uses the --dn_mirna option to identify miRNAs in the genome, without relying on the --known_miRNAs.

This part of the code redirects the output of time to the end of shortstack.log file.

  • ; } \ 2>> ${output_dir_top}/shortstack.log
# Load bash variables into memory
source .bashvars

# Make output directory, if it doesn't exist
mkdir --parents "${output_dir_top}"

# Create array of trimmed FastQs
trimmed_fastqs_array=(${trimmed_fastqs_dir}/${trimmed_fastqs_pattern})


# Pass array contents to new variable as space-delimited list
trimmed_fastqs_list=$(echo "${trimmed_fastqs_array[*]}")

# Rename genome FastA to ShortStack naming convention
cp "${genome_fasta_dir}"/"${genome_fasta_name}" "${genome_fasta}"


###### Run ShortStack ######
{ time \
ShortStack \
--genomefile "${genome_fasta}" \
--readfile ${trimmed_fastqs_list} \
--known_miRNAs ${repo_data_dir}/${mirbase_mature_fasta} \
--dn_mirna \
--threads ${threads} \
--outdir ${output_dir_top}/ShortStack_out \
&> ${output_dir_top}/shortstack.log ; } \
2>> ${output_dir_top}/shortstack.log

5.2 Check runtime

# Load bash variables into memory
source .bashvars

tail -n 3 ${output_dir_top}/shortstack.log \
| grep "real" \
| awk '{print "ShortStack runtime:" "\t" $2}'
ShortStack runtime: 52m22.645s

6 Results

6.1 ShortStack synopsis

# Load bash variables into memory
source .bashvars

tail -n 25 ${output_dir_top}/shortstack.log
Writing final files

Found a total of 37 MIRNA loci


Non-MIRNA loci by DicerCall:
N 33525
22 60
21 18
23 17
24 9

Creating visualizations of microRNA loci with strucVis
<<< WARNING >>>
Do not rely on these results alone to annotate new MIRNA loci!
The false positive rate for de novo MIRNA identification is low, but NOT ZERO
Insepct each mirna locus, especially the strucVis output, and see
https://doi.org/10.1105/tpc.17.00851 , https://doi.org/10.1093/nar/gky1141

Tue 10 Dec 2024 08:37:06 -0800 PST
Run Completed!

real    52m22.645s
user    672m59.895s
sys 196m42.848s

ShortStack found NN miRNAs.

6.2 Inspect Results.txt

# Load bash variables into memory
source .bashvars

head ${output_dir_top}/ShortStack_out/Results.txt

echo ""
echo "----------------------------------------------------------"
echo ""

echo "Nummber of potential loci:"
awk '(NR>1)' ${output_dir_top}/ShortStack_out/Results.txt | wc -l
Locus   Name    Chrom   Start   End Length  Reads   DistinctSequences   FracTop Strand  MajorRNA    MajorRNAReads   Short   Long    21  22  23  24  DicerCall   MIRNA   known_miRNAs
NW_026851514.1:11444-11873  Cluster_1   NW_026851514.1  11444   11873   430 934 210 0.913   +   UUGAAUUCUGCACACUACUUAUGAUAAAAGU 171 8   910 3   0   4   9   N   N   NA
NW_026851514.1:12401-12830  Cluster_2   NW_026851514.1  12401   12830   430 535 110 0.94    +   UGAUAACUCUUUUAACUGAUUCAUACGAAC  318 1   523 3   2   1   5   N   N   NA
NW_026851515.1:76365-77030  Cluster_3   NW_026851515.1  76365   77030   666 11653   547 0.003   -   UCCUACGAUCAAAGUUCGGCAACGUUCGAC  3215    5   11536   10  11  54  37  N   N   NA
NW_026851515.1:77089-77506  Cluster_4   NW_026851515.1  77089   77506   418 798 196 0.044   -   UACUAGUACCUCUUCGAUUGCAUUUU  100 5   732 3   16  22  20  N   N   NA
NW_026851515.1:77511-78358  Cluster_5   NW_026851515.1  77511   78358   848 5726    946 0.004   -   UAGAUAUGUCACUGUUUAUUUCAUUGUC    661 53  5066    261 114 98  134 N   N   NA
NW_026851515.1:78386-79090  Cluster_6   NW_026851515.1  78386   79090   705 1240    239 0.011   -   UGUAGUUCUUUGAAUAUAUCUCAGUCAUUG  264 6   1217    1   5   5   6   N   N   NA
NW_026851515.1:79280-79708  Cluster_7   NW_026851515.1  79280   79708   429 946 115 0.011   -   UUAUAUAUGUUCUUGCUGAUCUUAAUUGG   396 4   927 9   1   2   3   N   N   NA
NW_026851515.1:79774-80496  Cluster_8   NW_026851515.1  79774   80496   723 7823    1009    0.015   -   UUUGAUCGCUGUUUUUCAAUAUGACUGUGC  848 90  7238    248 71  48  128 N   N   NA
NW_026851515.1:88853-89546  Cluster_9   NW_026851515.1  88853   89546   694 1600    307 0.036   -   UCUGACUGUUUAUGUGUUUAAUAUAUAACC  221 10  1541    1   11  21  16  N   N   NA

----------------------------------------------------------

Nummber of potential loci:
33666

Column 20 of the Results.txt file identifies if a cluster is a miRNA or not (Y or N).

# Load bash variables into memory
source .bashvars

echo "Number of loci characterized as miRNA:"
awk '$20=="Y" {print $0}' ${output_dir_top}/ShortStack_out/Results.txt \
| wc -l
echo ""

echo "----------------------------------------------------------"

echo ""
echo "Number of loci _not_ characterized as miRNA:"
awk '$20=="N" {print $0}' ${output_dir_top}/ShortStack_out/Results.txt \
| wc -l
Number of loci characterized as miRNA:
37

----------------------------------------------------------

Number of loci _not_ characterized as miRNA:
33629

Column 21 of the Results.txt file identifies if a cluster aligned to a known miRNA (miRBase) or not (Y or NA).

# Load bash variables into memory
source .bashvars

echo "Number of loci matching miRBase miRNAs:"
awk '$21!="NA" {print $0}' ${output_dir_top}/ShortStack_out/Results.txt \
| wc -l
echo ""

echo "----------------------------------------------------------"

echo ""
echo "Number of loci _not_ matching miRBase miRNAs:"
awk '$21=="NA" {print $0}' ${output_dir_top}/ShortStack_out/Results.txt \
| wc -l
Number of loci matching miRBase miRNAs:
92

----------------------------------------------------------

Number of loci _not_ matching miRBase miRNAs:
33575

Although there are 92 loci with matches to miRBase miRNAs, ShortStack did not annotate 55 of these clusters as miRNAs likely because they do not also match secondary structure criteria.

This explains the difference between the 46 and 37 miRNAs.

6.2.1 Directory tree of all ShortStack outputs

Many of these are large (by GitHub standards) BAM files, so will not be added to the repo.

Additionally, it’s unlikely we’ll utilize most of the other files (bigwig) generated by ShortStack.

# Load bash variables into memory
source .bashvars

tree -h ${output_dir_top}/
/home/shared/8TB_HDD_01/sam/gitrepos/RobertsLab/project-clam-oa/output/02.00-ShortStack-31bp-fastp-merged/
├── [ 27K]  shortstack.log
└── [436K]  ShortStack_out
    ├── [ 84M]  196-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [697K]  196-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [270M]  196-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 64M]  199-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [642K]  199-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [205M]  199-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 76M]  211-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [666K]  211-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [242M]  211-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 72M]  24-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [670K]  24-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [223M]  24-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 71M]  260-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [672K]  260-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [221M]  260-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 61M]  26-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [646K]  26-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [187M]  26-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 74M]  30-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [658K]  30-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [235M]  30-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 71M]  310-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [667K]  310-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [222M]  310-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 72M]  33-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [665K]  33-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [227M]  33-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 69M]  341-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [666K]  341-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [213M]  341-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 79M]  34-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [669K]  34-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [251M]  34-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 64M]  35-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [648K]  35-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [199M]  35-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 68M]  363-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [640K]  363-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [216M]  363-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 74M]  367-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [673K]  367-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [231M]  367-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [104M]  376-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [703K]  376-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [339M]  376-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 72M]  460-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [671K]  460-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [230M]  460-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 72M]  485-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [665K]  485-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [228M]  485-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 85M]  501-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [697K]  501-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [269M]  501-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 99M]  71-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [725K]  71-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [320M]  71-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 78M]  88-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [683K]  88-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [250M]  88-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [111K]  alignment_details.tsv
    ├── [3.4M]  Counts.txt
    ├── [1.6M]  known_miRNAs.gff3
    ├── [1.7M]  known_miRNAs_unaligned.fasta
    ├── [1.3G]  merged_alignments.bam
    ├── [747K]  merged_alignments.bam.csi
    ├── [ 11K]  mir.fasta
    ├── [3.3M]  Results.gff3
    ├── [4.8M]  Results.txt
    └── [4.0K]  strucVis
        ├── [8.0K]  Cluster_11267.ps.pdf
        ├── [6.7K]  Cluster_11267.txt
        ├── [ 10K]  Cluster_13141.ps.pdf
        ├── [ 20K]  Cluster_13141.txt
        ├── [ 11K]  Cluster_13225.ps.pdf
        ├── [ 37K]  Cluster_13225.txt
        ├── [8.2K]  Cluster_13226.ps.pdf
        ├── [ 17K]  Cluster_13226.txt
        ├── [9.0K]  Cluster_13708.ps.pdf
        ├── [ 29K]  Cluster_13708.txt
        ├── [9.4K]  Cluster_14095.ps.pdf
        ├── [ 33K]  Cluster_14095.txt
        ├── [9.3K]  Cluster_14096.ps.pdf
        ├── [ 52K]  Cluster_14096.txt
        ├── [8.9K]  Cluster_15325.ps.pdf
        ├── [5.9K]  Cluster_15325.txt
        ├── [9.7K]  Cluster_15635.ps.pdf
        ├── [ 18K]  Cluster_15635.txt
        ├── [8.3K]  Cluster_15636.ps.pdf
        ├── [4.8K]  Cluster_15636.txt
        ├── [ 12K]  Cluster_15637.ps.pdf
        ├── [ 19K]  Cluster_15637.txt
        ├── [8.6K]  Cluster_15638.ps.pdf
        ├── [ 23K]  Cluster_15638.txt
        ├── [ 11K]  Cluster_15639.ps.pdf
        ├── [ 37K]  Cluster_15639.txt
        ├── [9.1K]  Cluster_16249.ps.pdf
        ├── [4.1K]  Cluster_16249.txt
        ├── [9.3K]  Cluster_16250.ps.pdf
        ├── [3.5K]  Cluster_16250.txt
        ├── [9.1K]  Cluster_17619.ps.pdf
        ├── [6.1K]  Cluster_17619.txt
        ├── [9.0K]  Cluster_1785.ps.pdf
        ├── [ 16K]  Cluster_1785.txt
        ├── [8.4K]  Cluster_19246.ps.pdf
        ├── [6.2K]  Cluster_19246.txt
        ├── [8.5K]  Cluster_20177.ps.pdf
        ├── [9.0K]  Cluster_20177.txt
        ├── [ 10K]  Cluster_2042.ps.pdf
        ├── [ 54K]  Cluster_2042.txt
        ├── [8.4K]  Cluster_22161.ps.pdf
        ├── [ 41K]  Cluster_22161.txt
        ├── [9.5K]  Cluster_22586.ps.pdf
        ├── [ 44K]  Cluster_22586.txt
        ├── [7.7K]  Cluster_23993.ps.pdf
        ├── [ 13K]  Cluster_23993.txt
        ├── [8.6K]  Cluster_24004.ps.pdf
        ├── [ 12K]  Cluster_24004.txt
        ├── [9.0K]  Cluster_24617.ps.pdf
        ├── [7.5K]  Cluster_24617.txt
        ├── [8.4K]  Cluster_25443.ps.pdf
        ├── [ 21K]  Cluster_25443.txt
        ├── [8.3K]  Cluster_2646.ps.pdf
        ├── [ 21K]  Cluster_2646.txt
        ├── [9.2K]  Cluster_29018.ps.pdf
        ├── [ 29K]  Cluster_29018.txt
        ├── [ 12K]  Cluster_31844.ps.pdf
        ├── [ 26K]  Cluster_31844.txt
        ├── [7.5K]  Cluster_32917.ps.pdf
        ├── [4.5K]  Cluster_32917.txt
        ├── [9.3K]  Cluster_32918.ps.pdf
        ├── [ 25K]  Cluster_32918.txt
        ├── [7.5K]  Cluster_32919.ps.pdf
        ├── [3.4K]  Cluster_32919.txt
        ├── [9.4K]  Cluster_3720.ps.pdf
        ├── [ 10K]  Cluster_3720.txt
        ├── [8.2K]  Cluster_4396.ps.pdf
        ├── [2.2K]  Cluster_4396.txt
        ├── [8.0K]  Cluster_5150.ps.pdf
        ├── [2.1K]  Cluster_5150.txt
        ├── [7.5K]  Cluster_9285.ps.pdf
        ├── [5.6K]  Cluster_9285.txt
        ├── [ 11K]  Cluster_9399.ps.pdf
        └── [5.4K]  Cluster_9399.txt

2 directories, 144 files
Johnson, Nathan R, Jonathan M Yeoh, Ceyda Coruh, and Michael J Axtell. 2016. “Improved Placement of Multi-Mapping Small RNAs.” G3 Genes|Genomes|Genetics 6 (7): 2103–11. https://doi.org/10.1534/g3.116.030452.
LS0tCnRpdGxlOiAiMDIuMDAtU2hvcnRTdGFjay0zMWJwLWZhc3RwLW1lcmdlZCIKYXV0aG9yOiAiU2FtIFdoaXRlIgpkYXRlOiAiMjAyNC0xMi0wOSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCmJpYmxpb2dyYXBoeTogcmVmZXJlbmNlcy5iaWIKbGluay1jaXRhdGlvbnM6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJldGljdWxhdGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KGdndmVubikKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBGQUxTRSwgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKCiMgRGVzY3JpcHRpb24KClVzZSBbU2hvcnRTdGFja10oaHR0cHM6Ly9naXRodWIuY29tL01pa2VBeHRlbGwvU2hvcnRTdGFjaykgW0BBeHRlbGwyMDEzLXh1OyBAam9obnNvbjIwMTY7IEBTaGFoaWQyMDE0LWx4XSB0byBwZXJmb3JtIGFsaWdubWVudCBvZiBzUk5Bc2VxIGRhdGEgYW5kIGFubm90YXRpb24gb2Ygc1JOQS1wcm9kdWNpbmcgZ2VuZXMuCgpEdWUgdG8gbGFyZ2UgZmlsZSBzaXplcyBvZiBzb21lIG9mIHRoZSBpbnB1dCBhbmQgb3V0cHV0IGZpbGVzLCBub3QgYWxsIGZpbGVzIGNhbiBiZSBzeW5jJ2QgdG8gR2l0SHViLiBBIGZ1bGwgYmFja3VwIG9mIHRoaXMgcmVwbyBpcyBhdmFpbGFibGUgaGVyZToKCi0gW2h0dHBzOi8vZ2FubmV0LmZpc2gud2FzaGluZ3Rvbi5lZHUvZ2l0cmVwb3MvcHJvamVjdC1jbGFtLW9hXShodHRwczovL2dhbm5ldC5maXNoLndhc2hpbmd0b24uZWR1L2dpdHJlcG9zL3Byb2plY3QtY2xhbS1vYSkKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKSW5wdXRzOgoKLSAgIFJlcXVpcmVzIHRyaW1tZWQgc1JOQXNlcSBmaWxlcyBnZW5lcmF0ZWQgYnkgWzAxLjAwLXRyaW1taW5nLWZhc3RwLWZhc3RxYy5SbWRdKC4vMDEuMDAtdHJpbW1pbmctZmFzdHAtZmFzdHFjLlJtZCkKCiAgICAtICAgRmlsZW5hbWVzIGZvcm1hdHRlZDogYCpmYXN0cC1hZGFwdGVycy1wb2x5Ry0zMWJwLW1lcmdlZC5mcS5nemAKCi0gICBHZW5vbWUgRmFzdEE6IGBHQ0ZfMDI2NTcxNTE1LjFfQVNNMjY1NzE1MXYyX2dlbm9taWMuZm5hYAoKLSBNaVJCYXNlIHYyMi4xIEZhc3RBOiBgbWlyYmFzZS1tYXR1cmUtdjIyLjEuZmFgCgpPdXRwdXRzOgoKLSAgIFNlZSBbU2hvcnRTdGFjayBvdXRwdXRzIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlQXh0ZWxsL1Nob3J0U3RhY2sjb3V0cHV0cykgZm9yIGZ1bGwgbGlzdCBhbmQgZGV0YWlsZWQgZGVzY3JpcHRpb25zLgoKU29mdHdhcmUgcmVxdWlyZW1lbnRzOgoKLSAgIFV0aWxpemVzIGEgW1Nob3J0U3RhY2tdKGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlQXh0ZWxsL1Nob3J0U3RhY2sjaW5zdGFsbGF0aW9uKSBDb25kYS9NYW1iYSBlbnZpcm9ubWVudCwgcGVyIHRoZSBpbnN0YWxsYXRpb24gaW5zdHJ1Y3Rpb25zLgoKUmVwbGFjZSB3aXRoIG5hbWUgb2YgeW91ciBTaG9ydFN0YWNrIGVudmlyb25tZW50IGFuZCB0aGUgcGF0aCB0byB0aGUgY29ycmVzcG9uZGluZyBjb25kYSBpbnN0YWxsYXRpb24gKGZpbmQgdGhpcyAqYWZ0ZXIqIHlvdSd2ZSBhY3RpdmF0ZWQgdGhlIGVudmlyb25tZW50KS4KCkUuZy4KCmBgYCBiYXNoCiMgQWN0aXZhdGUgZW52aXJvbm1lbnQKY29uZGEgYWN0aXZhdGUgU2hvcnRTdGFjay00LjEuMV9lbnYKCiMgRmluZCBjb25kYSBwYXRoCndoaWNoIGNvbmRhCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIFNldCBSIHZhcmlhYmxlcwoKYGBge3IgUi12YXJpYWJsZXMsIGV2YWw9VFJVRX0Kc2hvcnRzdGFja19jb25kYV9lbnZfbmFtZSA8LSBjKCJTaG9ydFN0YWNrLTQuMS4xX2VudiIpCnNob3J0c3RhY2tfY29uZF9wYXRoIDwtIGMoIi9ob21lL3NhbS9wcm9ncmFtcy9tYW1iYWZvcmdlL2NvbmRhYmluL2NvbmRhIikKYGBgCgojIENyZWF0ZSBhIEJhc2ggdmFyaWFibGVzIGZpbGUKClRoaXMgYWxsb3dzIHVzYWdlIG9mIEJhc2ggdmFyaWFibGVzIGFjcm9zcyBSIE1hcmtkb3duIGNodW5rcy4KCmBgYHtyIHNhdmUtYmFzaC12YXJpYWJsZXMtdG8tcnZhcnMtZmlsZSwgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQp7CmVjaG8gIiMjIyMgQXNzaWduIFZhcmlhYmxlcyAjIyMjIgplY2hvICIiCgplY2hvICIjIFRyaW1tZWQgRmFzdFEgbmFtaW5nIHBhdHRlcm4iCmVjaG8gImV4cG9ydCB0cmltbWVkX2Zhc3Rxc19wYXR0ZXJuPScqZmFzdHAtYWRhcHRlcnMtcG9seUctMzFicC1tZXJnZWQuZnEuZ3onIgoKZWNobyAiIyBEYXRhIGRpcmVjdG9yaWVzIgplY2hvICdleHBvcnQgcmVwb19kaXI9L2hvbWUvc2hhcmVkLzhUQl9IRERfMDEvc2FtL2dpdHJlcG9zL1JvYmVydHNMYWIvcHJvamVjdC1jbGFtLW9hJwplY2hvICdleHBvcnQgcmVwb19kYXRhX2Rpcj0iJHtyZXBvX2Rpcn0vZGF0YSInCmVjaG8gJ2V4cG9ydCBvdXRwdXRfZGlyX3RvcD0ke3JlcG9fZGlyfS9vdXRwdXQvMDIuMDAtU2hvcnRTdGFjay0zMWJwLWZhc3RwLW1lcmdlZCcKZWNobyAnZXhwb3J0IHRyaW1tZWRfZmFzdHFzX2Rpcj0iJHtyZXBvX2Rpcn0vb3V0cHV0LzAxLjAwLXRyaW1taW5nLWZhc3RwLWZhc3RxYyInCmVjaG8gIiIKCmVjaG8gIiMgSW5wdXQvT3V0cHV0IGZpbGVzIgplY2hvICdleHBvcnQgZ2Vub21lX2Zhc3RhX2Rpcj0ke3JlcG9fZGF0YV9kaXJ9L2dlbm9tZV9maWxlcycKZWNobyAnZXhwb3J0IGdlbm9tZV9mYXN0YV9uYW1lPSJHQ0ZfMDI2NTcxNTE1LjFfQVNNMjY1NzE1MXYyX2dlbm9taWMuZm5hIicKZWNobyAnZXhwb3J0IHNob3J0c3RhY2tfZ2Vub21lX2Zhc3RhX25hbWU9IkdDRl8wMjY1NzE1MTUuMV9BU00yNjU3MTUxdjJfZ2Vub21pYy5mYSInCmVjaG8gJ2V4cG9ydCBtaXJiYXNlX21hdHVyZV9mYXN0YT1taXJiYXNlLW1hdHVyZS12MjIuMS5mYScKZWNobyAnZXhwb3J0IGdlbm9tZV9mYXN0YT0iJHtnZW5vbWVfZmFzdGFfZGlyfS8ke3Nob3J0c3RhY2tfZ2Vub21lX2Zhc3RhX25hbWV9IicKZWNobyAiIgoKCmVjaG8gIiMgU2V0IG51bWJlciBvZiBDUFVzIHRvIHVzZSIKZWNobyAnZXhwb3J0IHRocmVhZHM9NDAnCmVjaG8gIiIKCmVjaG8gIiMgSW5pdGlhbGl6ZSBhcnJheXMiCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3Rxc19hcnJheT0oKScKCgp9ID4gLmJhc2h2YXJzCgpjYXQgLmJhc2h2YXJzCmBgYAoKIyBMb2FkIFtTaG9ydFN0YWNrXShodHRwczovL2dpdGh1Yi5jb20vTWlrZUF4dGVsbC9TaG9ydFN0YWNrKSBjb25kYSBlbnZpcm9ubWVudAoKSWYgdGhpcyBpcyBzdWNjZXNzZnVsLCB0aGUgZmlyc3QgbGluZSBvZiBvdXRwdXQgc2hvdWxkIHNob3cgdGhhdCB0aGUgUHl0aG9uIGJlaW5nIHVzZWQgaXMgdGhlIG9uZSBpbiB5b3VyIFtTaG9ydFN0YWNrXSg8aHR0cHM6Ly9naXRodWIuY29tL01pa2VBeHRlbGwvU2hvcnRTdGFjaz4gY29uZGEgZW52aXJvbm1lbnQgcGF0aC4KCkUuZy4KCmBweXRob246ICAgICAgICAgL2hvbWUvc2FtL3Byb2dyYW1zL21hbWJhZm9yZ2UvZW52cy9taXJtYWNoaW5lX2Vudi9iaW4vcHl0aG9uYAoKYGBge3IgbG9hZC1zaG9ydHN0YWNrLWNvbmRhLWVudiwgZXZhbD1UUlVFfQp1c2VfY29uZGFlbnYoY29uZGFlbnYgPSBzaG9ydHN0YWNrX2NvbmRhX2Vudl9uYW1lLCBjb25kYSA9IHNob3J0c3RhY2tfY29uZF9wYXRoKQoKIyBDaGVjayBzdWNjZXNzZnVsIGVudiBsb2FkaW5nCnB5X2NvbmZpZygpCmBgYAoKCgojIFJ1biBTaG9ydFN0YWNrCgojIyBFeGNlY3V0ZSBTaG9ydFN0YWNrIGNvbW1hbmQKClVzZXMgdGhlIGAtLWRuX21pcm5hYCBvcHRpb24gdG8gaWRlbnRpZnkgbWlSTkFzIGluIHRoZSBnZW5vbWUsIHdpdGhvdXQgcmVseWluZyBvbiB0aGUgYC0ta25vd25fbWlSTkFzYC4KClRoaXMgcGFydCBvZiB0aGUgY29kZSByZWRpcmVjdHMgdGhlIG91dHB1dCBvZiBgdGltZWAgdG8gdGhlIGVuZCBvZiBgc2hvcnRzdGFjay5sb2dgIGZpbGUuCgotICAgYDsgfSBcIDI+PiAke291dHB1dF9kaXJfdG9wfS9zaG9ydHN0YWNrLmxvZ2AKCmBgYHtyIHNob3J0c3RhY2ssIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCiMgTWFrZSBvdXRwdXQgZGlyZWN0b3J5LCBpZiBpdCBkb2Vzbid0IGV4aXN0Cm1rZGlyIC0tcGFyZW50cyAiJHtvdXRwdXRfZGlyX3RvcH0iCgojIENyZWF0ZSBhcnJheSBvZiB0cmltbWVkIEZhc3RRcwp0cmltbWVkX2Zhc3Rxc19hcnJheT0oJHt0cmltbWVkX2Zhc3Rxc19kaXJ9LyR7dHJpbW1lZF9mYXN0cXNfcGF0dGVybn0pCgoKIyBQYXNzIGFycmF5IGNvbnRlbnRzIHRvIG5ldyB2YXJpYWJsZSBhcyBzcGFjZS1kZWxpbWl0ZWQgbGlzdAp0cmltbWVkX2Zhc3Rxc19saXN0PSQoZWNobyAiJHt0cmltbWVkX2Zhc3Rxc19hcnJheVsqXX0iKQoKIyBSZW5hbWUgZ2Vub21lIEZhc3RBIHRvIFNob3J0U3RhY2sgbmFtaW5nIGNvbnZlbnRpb24KY3AgIiR7Z2Vub21lX2Zhc3RhX2Rpcn0iLyIke2dlbm9tZV9mYXN0YV9uYW1lfSIgIiR7Z2Vub21lX2Zhc3RhfSIKCgojIyMjIyMgUnVuIFNob3J0U3RhY2sgIyMjIyMjCnsgdGltZSBcClNob3J0U3RhY2sgXAotLWdlbm9tZWZpbGUgIiR7Z2Vub21lX2Zhc3RhfSIgXAotLXJlYWRmaWxlICR7dHJpbW1lZF9mYXN0cXNfbGlzdH0gXAotLWtub3duX21pUk5BcyAke3JlcG9fZGF0YV9kaXJ9LyR7bWlyYmFzZV9tYXR1cmVfZmFzdGF9IFwKLS1kbl9taXJuYSBcCi0tdGhyZWFkcyAke3RocmVhZHN9IFwKLS1vdXRkaXIgJHtvdXRwdXRfZGlyX3RvcH0vU2hvcnRTdGFja19vdXQgXAomPiAke291dHB1dF9kaXJfdG9wfS9zaG9ydHN0YWNrLmxvZyA7IH0gXAoyPj4gJHtvdXRwdXRfZGlyX3RvcH0vc2hvcnRzdGFjay5sb2cKCmBgYAoKIyMgQ2hlY2sgcnVudGltZQoKYGBge3IgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKdGFpbCAtbiAzICR7b3V0cHV0X2Rpcl90b3B9L3Nob3J0c3RhY2subG9nIFwKfCBncmVwICJyZWFsIiBcCnwgYXdrICd7cHJpbnQgIlNob3J0U3RhY2sgcnVudGltZToiICJcdCIgJDJ9JwoKYGBgCgojIFJlc3VsdHMKCiMjIFNob3J0U3RhY2sgc3lub3BzaXMKCmBgYHtyIHNob3J0c3RhY2stc3lub3BzaXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCnRhaWwgLW4gMjUgJHtvdXRwdXRfZGlyX3RvcH0vc2hvcnRzdGFjay5sb2cKYGBgCgpTaG9ydFN0YWNrIGZvdW5kIE5OIG1pUk5Bcy4KCiMjIEluc3BlY3QgYFJlc3VsdHMudHh0YAoKYGBge3IgcmVzdWx0cy10eHQtZmlsZSwgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKaGVhZCAke291dHB1dF9kaXJfdG9wfS9TaG9ydFN0YWNrX291dC9SZXN1bHRzLnR4dAoKZWNobyAiIgplY2hvICItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIgplY2hvICIiCgplY2hvICJOdW1tYmVyIG9mIHBvdGVudGlhbCBsb2NpOiIKYXdrICcoTlI+MSknICR7b3V0cHV0X2Rpcl90b3B9L1Nob3J0U3RhY2tfb3V0L1Jlc3VsdHMudHh0IHwgd2MgLWwKYGBgCgpDb2x1bW4gMjAgb2YgdGhlIGBSZXN1bHRzLnR4dGAgZmlsZSBpZGVudGlmaWVzIGlmIGEgY2x1c3RlciBpcyBhIG1pUk5BIG9yIG5vdCAoYFlgIG9yIGBOYCkuCgpgYGB7ciByZXN1bHRzLXR4dC1taVJOQXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmVjaG8gIk51bWJlciBvZiBsb2NpIGNoYXJhY3Rlcml6ZWQgYXMgbWlSTkE6Igphd2sgJyQyMD09IlkiIHtwcmludCAkMH0nICR7b3V0cHV0X2Rpcl90b3B9L1Nob3J0U3RhY2tfb3V0L1Jlc3VsdHMudHh0IFwKfCB3YyAtbAplY2hvICIiCgplY2hvICItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIgoKZWNobyAiIgplY2hvICJOdW1iZXIgb2YgbG9jaSBfbm90XyBjaGFyYWN0ZXJpemVkIGFzIG1pUk5BOiIKYXdrICckMjA9PSJOIiB7cHJpbnQgJDB9JyAke291dHB1dF9kaXJfdG9wfS9TaG9ydFN0YWNrX291dC9SZXN1bHRzLnR4dCBcCnwgd2MgLWwKCmBgYAoKQ29sdW1uIDIxIG9mIHRoZSBgUmVzdWx0cy50eHRgIGZpbGUgaWRlbnRpZmllcyBpZiBhIGNsdXN0ZXIgYWxpZ25lZCB0byBhIGtub3duIG1pUk5BIChtaVJCYXNlKSBvciBub3QgKGBZYCBvciBgTkFgKS4KCgpgYGB7ciByZXN1bHRzLXR4dC1taVJCYXNlLW1pUk5BcywgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKZWNobyAiTnVtYmVyIG9mIGxvY2kgbWF0Y2hpbmcgbWlSQmFzZSBtaVJOQXM6Igphd2sgJyQyMSE9Ik5BIiB7cHJpbnQgJDB9JyAke291dHB1dF9kaXJfdG9wfS9TaG9ydFN0YWNrX291dC9SZXN1bHRzLnR4dCBcCnwgd2MgLWwKZWNobyAiIgoKZWNobyAiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSIKCmVjaG8gIiIKZWNobyAiTnVtYmVyIG9mIGxvY2kgX25vdF8gbWF0Y2hpbmcgbWlSQmFzZSBtaVJOQXM6Igphd2sgJyQyMT09Ik5BIiB7cHJpbnQgJDB9JyAke291dHB1dF9kaXJfdG9wfS9TaG9ydFN0YWNrX291dC9SZXN1bHRzLnR4dCBcCnwgd2MgLWwKCmBgYAoKQWx0aG91Z2ggdGhlcmUgYXJlIDkyIGxvY2kgd2l0aCBtYXRjaGVzIHRvIG1pUkJhc2UgbWlSTkFzLCBTaG9ydFN0YWNrIGRpZCAqbm90KiBhbm5vdGF0ZSA1NSBvZiB0aGVzZSBjbHVzdGVycyBhcyBtaVJOQXMgbGlrZWx5IFtiZWNhdXNlIHRoZXkgZG8gbm90ICphbHNvKiBtYXRjaCBzZWNvbmRhcnkgc3RydWN0dXJlIGNyaXRlcmlhXShodHRwczovL2dpdGh1Yi5jb20vTWlrZUF4dGVsbC9TaG9ydFN0YWNrI21pcm5hLWFubm90YXRpb24pLgoKVGhpcyBleHBsYWlucyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSA0NiBhbmQgMzcgbWlSTkFzLgoKIyMjIERpcmVjdG9yeSB0cmVlIG9mIGFsbCBTaG9ydFN0YWNrIG91dHB1dHMKCk1hbnkgb2YgdGhlc2UgYXJlIGxhcmdlIChieSBHaXRIdWIgc3RhbmRhcmRzKSBCQU0gZmlsZXMsIHNvIHdpbGwgbm90IGJlIGFkZGVkIHRvIHRoZSByZXBvLgoKQWRkaXRpb25hbGx5LCBpdCdzIHVubGlrZWx5IHdlJ2xsIHV0aWxpemUgbW9zdCBvZiB0aGUgb3RoZXIgZmlsZXMgKGJpZ3dpZykgZ2VuZXJhdGVkIGJ5IFNob3J0U3RhY2suCgpgYGB7ciBzaG9ydHN0YWNrLWRpcmVjdG9yeS10cmVlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgp0cmVlIC1oICR7b3V0cHV0X2Rpcl90b3B9LwoKYGBg