Use ShortStack (Axtell 2013; Shahid and Axtell 2014; Johnson et al. 2016)to perform alignment of sRNAseq data and annotation of sRNA-producing genes.

sRNA discovery, using A. pulchra genome for reference, using ShortStack 4.1.0, which provides much faster analysis times and additional functionality for visualizing miRNA hairpin structures and generating genome-browser-ready quantitative coverage tracks of aligned small RNAs.

As in deep-dive and deep-dive-expression, we will also use a customized miRBase database, utilizing cnidarian miRNAs curated by Jill Ashley, which includes published cnidarian miRNAs:


Inputs:

  • Requires trimmed sRNAseq files generated in 01.10-D-Apul-sRNAseq-trimming-fastp-FastQC-MultiQC

    • Filenames formatted: *fastp-adapters-polyG-31bp-merged.fq.gz
  • A.pulchra genome FastA. Not currently publicly available (still being annotated by collaborators)

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 ShortStack4_env

# Find conda path
which conda

1 Set R variables

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

2 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 timeseries_dir=/home/shared/8TB_HDD_02/shedurkin/timeseries_molecular'
echo 'export timeseries_data_dir="${timeseries_dir}/M-multi-species/data"'
echo 'export output_dir_top=${timeseries_dir}/D-Apul/output/04-Apul-sRNA-discovery-ShortStack'
echo ""

echo "# Input/Output files"
echo 'export genome_fasta_dir=${timeseries_dir}/D-Apul/data'
echo 'export genome_fasta_name="Apulchra-genome.fa"'
echo 'export shortstack_genome_fasta_name="Apulchra-genome.fa"'
echo 'export trimmed_fastqs_dir="${timeseries_dir}/D-Apul/output/01.10-D-Apul-sRNAseq-trimming-fastp-FastQC-MultiQC/trimmed-fastqs-sRNA"'

echo 'export mirbase_mature_fasta_version=cnidarian-mirbase-mature-v22.1.fasta'
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 timeseries_dir=/home/shared/8TB_HDD_02/shedurkin/timeseries_molecular
export timeseries_data_dir="${timeseries_dir}/M-multi-species/data"
export output_dir_top=${timeseries_dir}/D-Apul/output/04-Apul-sRNA-discovery-ShortStack

# Input/Output files
export genome_fasta_dir=${timeseries_dir}/D-Apul/data
export genome_fasta_name="Apulchra-genome.fa"
export shortstack_genome_fasta_name="Apulchra-genome.fa"
export trimmed_fastqs_dir="${timeseries_dir}/D-Apul/output/01.10-D-Apul-sRNAseq-trimming-fastp-FastQC-MultiQC/trimmed-fastqs-sRNA"
export mirbase_mature_fasta_version=cnidarian-mirbase-mature-v22.1.fasta
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=()

3 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)
py_config()
python:         /home/sam/programs/mambaforge/envs/ShortStack-4.1.0_env/bin/python
libpython:      /home/sam/programs/mambaforge/envs/ShortStack-4.1.0_env/lib/libpython3.12.so
pythonhome:     /home/sam/programs/mambaforge/envs/ShortStack-4.1.0_env:/home/sam/programs/mambaforge/envs/ShortStack-4.1.0_env
version:        3.12.7 | packaged by conda-forge | (main, Oct  4 2024, 16:05:46) [GCC 13.3.0]
numpy:          /home/sam/programs/mambaforge/envs/ShortStack-4.1.0_env/lib/python3.12/site-packages/numpy
numpy_version:  2.1.1

NOTE: Python version was forced by use_python() function

Note: I sometimes get an error “failed to initialize requested version of Python,” which seems to stem from the reticulate package default loading a python environment. I’ve been able to fix this by manually uninstalling the reticulate package, then restarting R and reinstalling reticulate before rerunning this code document. # Download reference files

3.1 A.pulchra genome

# Load bash variables into memory
source .bashvars

wget -O ${genome_fasta_dir}/${shortstack_genome_fasta_name} "https://osf.io/download/kn96u/"

3.2 Cnidarian+miRBase database

Available in deep-dive repo, here

# Load bash variables into memory
source .bashvars

wget -O ${timeseries_data_dir}/"${mirbase_mature_fasta_version}" "https://raw.githubusercontent.com/urol-e5/deep-dive/refs/heads/main/data/cnidarian-mirbase-mature-v22.1.fasta"
# Load bash variables into memory
source .bashvars

head -5 ${timeseries_data_dir}/"${mirbase_mature_fasta_version}"
>cel-let-7-5p MIMAT0000001 Caenorhabditis elegans let-7-5p
UGAGGUAGUAGGUUGUAUAGUU
>cel-let-7-3p MIMAT0015091 Caenorhabditis elegans let-7-3p
CUAUGCAAUUUUCUACCUUACC
>cel-lin-4-5p MIMAT0000002 Caenorhabditis elegans lin-4-5p

3.3 Trimmed sRNA-seq reads

Trimmed in 01.10-D-Apul-sRNAseq-trimming-fastp-FastQC-MultiQC

4 Run ShortStack

4.1 Modify genome filename for ShortStack compatability

# Load bash variables into memory
source .bashvars

# Check for FastA file first
# Then create rename file if doesn't exist
if [ -f "${genome_fasta_dir}/${shortstack_genome_fasta_name}" ]; then
  echo "${genome_fasta_dir}/${shortstack_genome_fasta_name}"
  echo ""
  echo "Already exists. Nothing to do."
  echo ""
else

  # Copy genome FastA to ShortStack-compatible filename (ending with .fa)
  cp ${genome_fasta_dir}/${genome_fasta_name} ${genome_fasta_dir}/${shortstack_genome_fasta_name}
fi

# Confirm
ls -lh ${genome_fasta_dir}/${shortstack_genome_fasta_name}
/home/shared/8TB_HDD_02/shedurkin/timeseries_molecular/D-Apul/data/Apulchra-genome.fa

Already exists. Nothing to do.

-rw-r--r-- 1 shedurkin labmembers 505M Oct  1 13:31 /home/shared/8TB_HDD_02/shedurkin/timeseries_molecular/D-Apul/data/Apulchra-genome.fa

4.2 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[*]}")


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

4.3 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: 70m35.956s

5 Results

5.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 51 MIRNA loci


Non-MIRNA loci by DicerCall:
N 18768
23 25
22 21
24 12
21 8

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

Fri 20 Dec 2024 19:43:23 -0800 PST
Run Completed!

real    70m35.956s
user    829m16.281s
sys 269m7.808s

ShortStack identified 51 miRNAs among all of the A.pulchra samples. This is a notably larger number than the 39 miRNAs identified in deep-dive-expression, which examined only 5 colonies from a single time point! I would guess the difference stems from either (a) our capture of more intraspecific diversity, or (b) different miRNA profiles associated with different environmental conditions (i.e. some A.pulchra miRNAs are only expressed under certain conditions). The counts data should give us more insight.

5.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
ntLink_7:3054-3472  Cluster_1   ntLink_7    3054    3472    419 625 186 0.032   -   UGAACGUAUUUUCUGAAGAAACUGCAAAG   45  6   600 2   4   7   6   N   N   NA
ntLink_7:9758-10311 Cluster_2   ntLink_7    9758    10311   554 2797    336 0.857   +   GUCAAGUGCAUCGAUCAAGGAUGGAUCAGG  651 11  2685    6   32  20  43  N   N   NA
ntLink_7:22562-22980    Cluster_3   ntLink_7    22562   22980   419 634 180 0.028   -   UCUUGAACGUAUUUUCUGAAGAAACUGC    37  7   608 2   1   5   11  N   N   NA
ntLink_7:29267-29820    Cluster_4   ntLink_7    29267   29820   554 2881    361 0.859   +   GUCAAGUGCAUCGAUCAAGGAUGGAUCAGG  459 17  2764    9   34  26  31  N   N   NA
ntLink_7:42050-42468    Cluster_5   ntLink_7    42050   42468   419 689 156 0.025   -   UCUGAAGAAACUGCAAAGUUCACUGUCCGC  105 2   675 0   1   6   5   N   N   NA
ntLink_7:43122-43556    Cluster_6   ntLink_7    43122   43556   435 1774    435 0.045   -   UGCUAGACGAACCUCUGGAUCCGCU   152 41  1613    8   19  10  83  N   N   NA
ntLink_7:48749-49302    Cluster_7   ntLink_7    48749   49302   554 2911    340 0.867   +   GUCAAGUGCAUCGAUCAAGGAUGGAUCAGG  680 13  2793    11  40  19  35  N   N   NA
ntLink_7:61554-61972    Cluster_8   ntLink_7    61554   61972   419 678 169 0.021   -   UCUGAAGAAACUGCAAAGUUCACUGUCCGC  100 6   660 2   2   3   5   N   N   NA
ntLink_7:68251-68804    Cluster_9   ntLink_7    68251   68804   554 3373    520 0.82    +   GUCAAGUGCAUCGAUCAAGGAUGGAUCAGG  728 49  3185    9   41  28  61  N   N   NA

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

Nummber of potential loci:
18885

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:
51

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

Number of loci _not_ characterized as miRNA:
18834

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

The echo command after the awk command is simply there to prove that the chunk executed.

# 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:
360

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

Number of loci _not_ matching miRBase miRNAs:
18526

5.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_02/shedurkin/timeseries_molecular/D-Apul/output/04-Apul-sRNA-discovery-ShortStack/
├── [4.0K]  figures
│   ├── [226K]  Apul_ShortStack_dbmatch_histogram.png
│   ├── [340K]  Apul_ShortStack_dbmatch_histogram_reduced.png
│   ├── [323K]  Apul_ShortStack_miRNA_histogram.png
│   ├── [294K]  Apul_ShortStack_miRNA_histogram_reduced.png
│   └── [202K]  Apul_ShortStack_venn.png
├── [ 53K]  shortstack.log
└── [ 20K]  ShortStack_out
    ├── [ 28M]  1A10-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [212K]  1A10-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 80M]  1A10-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 32M]  1A12-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [207K]  1A12-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 95M]  1A12-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 37M]  1A1-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [216K]  1A1-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [115M]  1A1-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 48M]  1A2-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [220K]  1A2-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [150M]  1A2-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 37M]  1A8-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [211K]  1A8-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [108M]  1A8-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 59M]  1A9-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [215K]  1A9-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [187M]  1A9-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 33M]  1B10-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [214K]  1B10-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 99M]  1B10-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 39M]  1B1-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [216K]  1B1-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [122M]  1B1-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 35M]  1B2-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [213K]  1B2-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [114M]  1B2-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 66M]  1B5-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [218K]  1B5-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [209M]  1B5-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 31M]  1B9-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [217K]  1B9-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 90M]  1B9-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 30M]  1C10-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [207K]  1C10-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [101M]  1C10-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 42M]  1C4-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [210K]  1C4-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [132M]  1C4-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 47M]  1D10-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [216K]  1D10-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [142M]  1D10-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 61M]  1D3-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [221K]  1D3-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [189M]  1D3-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 53M]  1D4-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [220K]  1D4-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [162M]  1D4-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 58M]  1D6-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [214K]  1D6-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [172M]  1D6-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 35M]  1D8-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [207K]  1D8-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [104M]  1D8-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 49M]  1D9-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [220K]  1D9-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [155M]  1D9-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 41M]  1E1-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [217K]  1E1-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [134M]  1E1-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 67M]  1E3-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [212K]  1E3-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [197M]  1E3-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 26M]  1E5-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [205K]  1E5-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 92M]  1E5-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 42M]  1E9-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [218K]  1E9-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [146M]  1E9-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 33M]  1F11-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [211K]  1F11-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 92M]  1F11-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 47M]  1F4-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [215K]  1F4-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [143M]  1F4-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 27M]  1F8-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [209K]  1F8-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 79M]  1F8-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 58M]  1G5-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [215K]  1G5-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [184M]  1G5-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 32M]  1H11-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [215K]  1H11-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 97M]  1H11-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 28M]  1H12-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [209K]  1H12-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [ 94M]  1H12-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 52M]  1H6-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [213K]  1H6-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [153M]  1H6-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 53M]  1H7-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [211K]  1H7-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [158M]  1H7-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 34M]  1H8-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [215K]  1H8-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [105M]  1H8-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 53M]  2B2-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [214K]  2B2-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [152M]  2B2-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 59M]  2B3-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [212K]  2B3-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [172M]  2B3-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 55M]  2C1-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [218K]  2C1-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [175M]  2C1-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 61M]  2C2-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [212K]  2C2-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [181M]  2C2-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 45M]  2D2-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [215K]  2D2-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [144M]  2D2-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 40M]  2E2-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [216K]  2E2-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [115M]  2E2-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 51M]  2F1-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [212K]  2F1-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [133M]  2F1-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [ 46M]  2G1-fastp-adapters-polyG-31bp-merged_condensed.bam
    ├── [210K]  2G1-fastp-adapters-polyG-31bp-merged_condensed.bam.csi
    ├── [132M]  2G1-fastp-adapters-polyG-31bp-merged_condensed.fa
    ├── [219K]  alignment_details.tsv
    ├── [2.8M]  Counts.txt
    ├── [110K]  known_miRNAs.gff3
    ├── [1.8M]  known_miRNAs_unaligned.fasta
    ├── [1.6G]  merged_alignments.bam
    ├── [184K]  merged_alignments.bam.csi
    ├── [ 14K]  mir.fasta
    ├── [1.9M]  Results.gff3
    ├── [2.7M]  Results.txt
    └── [4.0K]  strucVis
        ├── [9.8K]  Cluster_10452.ps.pdf
        ├── [9.0K]  Cluster_10452.txt
        ├── [9.2K]  Cluster_11565.ps.pdf
        ├── [3.6K]  Cluster_11565.txt
        ├── [8.4K]  Cluster_12081.ps.pdf
        ├── [3.1K]  Cluster_12081.txt
        ├── [8.4K]  Cluster_12083.ps.pdf
        ├── [3.0K]  Cluster_12083.txt
        ├── [8.6K]  Cluster_12087.ps.pdf
        ├── [3.1K]  Cluster_12087.txt
        ├── [8.9K]  Cluster_13327.ps.pdf
        ├── [ 12K]  Cluster_13327.txt
        ├── [7.8K]  Cluster_13647.ps.pdf
        ├── [1.7K]  Cluster_13647.txt
        ├── [ 10K]  Cluster_14146.ps.pdf
        ├── [ 27K]  Cluster_14146.txt
        ├── [ 12K]  Cluster_14165.ps.pdf
        ├── [ 59K]  Cluster_14165.txt
        ├── [ 10K]  Cluster_14532.ps.pdf
        ├── [ 70K]  Cluster_14532.txt
        ├── [9.2K]  Cluster_14605.ps.pdf
        ├── [ 15K]  Cluster_14605.txt
        ├── [ 10K]  Cluster_14610.ps.pdf
        ├── [ 10K]  Cluster_14610.txt
        ├── [7.9K]  Cluster_14633.ps.pdf
        ├── [1.9K]  Cluster_14633.txt
        ├── [9.3K]  Cluster_14692.ps.pdf
        ├── [ 13K]  Cluster_14692.txt
        ├── [8.9K]  Cluster_15097.ps.pdf
        ├── [ 17K]  Cluster_15097.txt
        ├── [ 11K]  Cluster_16354.ps.pdf
        ├── [ 83K]  Cluster_16354.txt
        ├── [ 11K]  Cluster_17173.ps.pdf
        ├── [ 79K]  Cluster_17173.txt
        ├── [ 10K]  Cluster_17186.ps.pdf
        ├── [ 32K]  Cluster_17186.txt
        ├── [ 11K]  Cluster_17192.ps.pdf
        ├── [ 97K]  Cluster_17192.txt
        ├── [8.8K]  Cluster_17245.ps.pdf
        ├── [ 34K]  Cluster_17245.txt
        ├── [8.7K]  Cluster_17623.ps.pdf
        ├── [8.1K]  Cluster_17623.txt
        ├── [ 10K]  Cluster_1819.ps.pdf
        ├── [ 14K]  Cluster_1819.txt
        ├── [9.8K]  Cluster_1832.ps.pdf
        ├── [ 56K]  Cluster_1832.txt
        ├── [9.7K]  Cluster_1833.ps.pdf
        ├── [4.3K]  Cluster_1833.txt
        ├── [8.7K]  Cluster_1836.ps.pdf
        ├── [ 60K]  Cluster_1836.txt
        ├── [ 11K]  Cluster_1865.ps.pdf
        ├── [ 39K]  Cluster_1865.txt
        ├── [ 11K]  Cluster_1950.ps.pdf
        ├── [ 33K]  Cluster_1950.txt
        ├── [ 11K]  Cluster_1951.ps.pdf
        ├── [ 23K]  Cluster_1951.txt
        ├── [ 11K]  Cluster_2372.ps.pdf
        ├── [ 50K]  Cluster_2372.txt
        ├── [ 11K]  Cluster_2500.ps.pdf
        ├── [7.9K]  Cluster_2500.txt
        ├── [9.7K]  Cluster_2746.ps.pdf
        ├── [ 29K]  Cluster_2746.txt
        ├── [ 10K]  Cluster_3109.ps.pdf
        ├── [7.9K]  Cluster_3109.txt
        ├── [ 10K]  Cluster_3226.ps.pdf
        ├── [ 46K]  Cluster_3226.txt
        ├── [ 10K]  Cluster_3227.ps.pdf
        ├── [ 48K]  Cluster_3227.txt
        ├── [9.9K]  Cluster_3301.ps.pdf
        ├── [ 33K]  Cluster_3301.txt
        ├── [9.8K]  Cluster_4026.ps.pdf
        ├── [6.6K]  Cluster_4026.txt
        ├── [9.1K]  Cluster_4034.ps.pdf
        ├── [ 43K]  Cluster_4034.txt
        ├── [ 10K]  Cluster_4036.ps.pdf
        ├── [8.5K]  Cluster_4036.txt
        ├── [ 12K]  Cluster_4752.ps.pdf
        ├── [ 85K]  Cluster_4752.txt
        ├── [ 11K]  Cluster_4754.ps.pdf
        ├── [ 20K]  Cluster_4754.txt
        ├── [ 10K]  Cluster_5516.ps.pdf
        ├── [ 15K]  Cluster_5516.txt
        ├── [ 12K]  Cluster_5517.ps.pdf
        ├── [ 64K]  Cluster_5517.txt
        ├── [ 11K]  Cluster_5603.ps.pdf
        ├── [ 37K]  Cluster_5603.txt
        ├── [8.8K]  Cluster_5685.ps.pdf
        ├── [1.9K]  Cluster_5685.txt
        ├── [ 10K]  Cluster_9366.ps.pdf
        ├── [ 20K]  Cluster_9366.txt
        ├── [ 10K]  Cluster_9380.ps.pdf
        ├── [ 64K]  Cluster_9380.txt
        ├── [ 11K]  Cluster_9420.ps.pdf
        ├── [ 36K]  Cluster_9420.txt
        ├── [ 11K]  Cluster_9512.ps.pdf
        ├── [ 66K]  Cluster_9512.txt
        ├── [ 10K]  Cluster_9532.ps.pdf
        ├── [ 15K]  Cluster_9532.txt
        ├── [9.9K]  Cluster_9706.ps.pdf
        ├── [ 31K]  Cluster_9706.txt
        ├── [ 11K]  Cluster_9786.ps.pdf
        └── [ 87K]  Cluster_9786.txt

3 directories, 237 files

5.3 Visualize

We noticed that a) not all of the identified miRNAs have database matches, and b) some reads have a match in the database but are not classified as miRNAs. Let’s look at this in more depth.

Apul_shortstack_results <- read.csv("../output/04-Apul-sRNA-discovery-ShortStack/ShortStack_out/Results.txt", sep="\t")
# Reads identified as miRNAs (but not necessarily known)
Apul_shortstack_results %>% 
  filter(MIRNA == "Y") %>%
  mutate(known_miRNAs = str_sub(known_miRNAs, 1, 40)) %>%
  mutate(Locus = str_sub(Locus, 20, 40)) %>%
  ggplot(aes(x = reorder(Locus, Reads), y = Reads, fill = known_miRNAs)) +
  geom_bar(stat = "identity") +
   geom_text(aes(label = Reads), vjust = 0.5, hjust = 0, color = "black", size = 2.5, angle = 90) +
  labs(x = "miRNA", y = "Read count", 
       title = "Reads identified by ShortStack as miRNAs",
       fill = "Annotation") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

ggsave("../output/04-Apul-sRNA-discovery-ShortStack/figures/Apul_ShortStack_miRNA_histogram.png", width = 12, height = 7, units = "in")


# Reads matched in the reference db (but not necessarily identified as miRNA)
Apul_shortstack_results %>% 
  filter(!is.na(known_miRNAs)) %>%
  mutate(known_miRNAs = str_sub(known_miRNAs, 1, 40)) %>%
  mutate(Locus = str_sub(Locus, 20, 40)) %>%
  ggplot(aes(x = reorder(Locus, Reads), y = Reads, fill = MIRNA)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Reads), vjust = 0.5, hjust = 0, color = "black", size = 2.5, angle = 90) +
  labs(x = "miRNA", y = "Read count", 
       title = "Reads with miRBase+cnidarian database matches",
       fill = "Identified as miRNA?") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

ggsave("../output/04-Apul-sRNA-discovery-ShortStack/figures/Apul_ShortStack_dbmatch_histogram.png", width = 12, height = 7, units = "in")

There’s a few miRNAs with very high read counts, and it’s making visualization of the rest difficult. Let’s remove them and retry visualizing the rest.

# Reads identified as miRNAs (but not necessarily known)
Apul_shortstack_results %>% 
  filter(MIRNA == "Y") %>%
  filter(Reads < 100000) %>%
  mutate(known_miRNAs = str_sub(known_miRNAs, 1, 40)) %>%
  mutate(Locus = str_sub(Locus, 20, 40)) %>%
  ggplot(aes(x = reorder(Locus, Reads), y = Reads, fill = known_miRNAs)) +
  geom_bar(stat = "identity") +
   geom_text(aes(label = Reads), vjust = 0.5, hjust = 0, color = "black", size = 2.5, angle = 90) +
  labs(x = "miRNA", y = "Read count", 
       title = "Reads identified by ShortStack as miRNAs",
       fill = "Annotation") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

ggsave("../output/04-Apul-sRNA-discovery-ShortStack/figures/Apul_ShortStack_miRNA_histogram_reduced.png", width = 12, height = 7, units = "in")


# Reads matched in the reference db (but not necessarily identified as miRNA)
Apul_shortstack_results %>% 
  filter(!is.na(known_miRNAs)) %>%
  filter(Reads < 100000) %>%
  mutate(known_miRNAs = str_sub(known_miRNAs, 1, 40)) %>%
  mutate(Locus = str_sub(Locus, 20, 40)) %>%
  ggplot(aes(x = reorder(Locus, Reads), y = Reads, fill = MIRNA)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = Reads), vjust = 0.5, hjust = 0, color = "black", size = 2.5, angle = 90) +
  labs(x = "miRNA", y = "Read count", 
       title = "Reads with miRBase+cnidarian database matches",
       fill = "Identified as miRNA?") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank())

ggsave("../output/04-Apul-sRNA-discovery-ShortStack/figures/Apul_ShortStack_dbmatch_histogram_reduced.png", width = 12, height = 7, units = "in")

It seems like an sRNa is both more likely to be previously described and to have been annoted by ShortStack as an miRNA if it is more highly expressed.

# Make list
mirnas <- Apul_shortstack_results %>% filter(MIRNA == "Y") %>% pull(Locus)
matches <- Apul_shortstack_results %>% filter(!is.na(known_miRNAs)) %>% pull(Locus)

Apul_shortstack_vennlist <- list(
  "Identified as miRNA" = mirnas,
  "Database match" = matches
)

# Make venn diagrams
ggvenn(Apul_shortstack_vennlist)

ggsave("../output/04-Apul-sRNA-discovery-ShortStack/figures/Apul_ShortStack_venn.png", width = 12, height = 7, units = "in")

Citations

Axtell, Michael J. 2013. “ShortStack: Comprehensive Annotation and Quantification of Small RNA Genes.” RNA 19 (6): 740–51. https://doi.org/10.1261/rna.035279.112.
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.
Shahid, Saima, and Michael J. Axtell. 2014. “Identification and Annotation of Small RNA Genes Using ShortStack.” Methods 67 (1): 20–27. https://doi.org/10.1016/j.ymeth.2013.10.004.
LS0tCnRpdGxlOiAiMDQtQXB1bC1zUk5BLWRpc2NvdmVyeS1TaG9ydFN0YWNrIgphdXRob3I6ICJLYXRobGVlbiBEdXJraW4iCmRhdGU6ICIyMDI0LTEyLTE4IgpvdXRwdXQ6IAogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgZ2l0aHViX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYgpsaW5rLWNpdGF0aW9uczogdHJ1ZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmV0aWN1bGF0ZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoZ2d2ZW5uKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZWNobyA9IFRSVUUsICAgICAgICAgIyBEaXNwbGF5IGNvZGUgY2h1bmtzCiAgZXZhbCA9IEZBTFNFLCAgICAgICAgIyBFdmFsdWF0ZSBjb2RlIGNodW5rcwogIHdhcm5pbmcgPSBGQUxTRSwgICAgICMgSGlkZSB3YXJuaW5ncwogIG1lc3NhZ2UgPSBGQUxTRSwgICAgICMgSGlkZSBtZXNzYWdlcwogIGNvbW1lbnQgPSAiIiAgICAgICAgICMgUHJldmVudHMgYXBwZW5kaW5nICcjIycgdG8gYmVnaW5uaW5nIG9mIGxpbmVzIGluIGNvZGUgb3V0cHV0CikKYGBgCgpVc2UgW1Nob3J0U3RhY2tdKGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlQXh0ZWxsL1Nob3J0U3RhY2spIFtAYXh0ZWxsMjAxM2E7IEBzaGFoaWQyMDE0OyBAam9obnNvbjIwMTZhXXRvIHBlcmZvcm0gYWxpZ25tZW50IG9mIHNSTkFzZXEgZGF0YSBhbmQgYW5ub3RhdGlvbiBvZiBzUk5BLXByb2R1Y2luZyBnZW5lcy4KCnNSTkEgZGlzY292ZXJ5LCB1c2luZyAqQS4gcHVsY2hyYSogZ2Vub21lIGZvciByZWZlcmVuY2UsIHVzaW5nIFtTaG9ydFN0YWNrIDQuMS4wXShodHRwczovL2dpdGh1Yi5jb20vTWlrZUF4dGVsbC9TaG9ydFN0YWNrP3RhYj1yZWFkbWUtb3YtZmlsZSNzaG9ydHN0YWNrLXZlcnNpb24tNC1tYWpvci1jaGFuZ2VzKSwgd2hpY2ggcHJvdmlkZXMgbXVjaCBmYXN0ZXIgYW5hbHlzaXMgdGltZXMgKmFuZCogYWRkaXRpb25hbCBmdW5jdGlvbmFsaXR5IGZvciB2aXN1YWxpemluZyBtaVJOQSBoYWlycGluIHN0cnVjdHVyZXMgYW5kIGdlbmVyYXRpbmcgZ2Vub21lLWJyb3dzZXItcmVhZHkgcXVhbnRpdGF0aXZlIGNvdmVyYWdlIHRyYWNrcyBvZiBhbGlnbmVkIHNtYWxsIFJOQXMuIAoKQXMgaW4gYGRlZXAtZGl2ZWAgYW5kIGBkZWVwLWRpdmUtZXhwcmVzc2lvbmAsIHdlIHdpbGwgYWxzbyB1c2UgYSBjdXN0b21pemVkIG1pUkJhc2UgZGF0YWJhc2UsIHV0aWxpemluZyBjbmlkYXJpYW4gbWlSTkFzIGN1cmF0ZWQgYnkgSmlsbCBBc2hsZXksIHdoaWNoIGluY2x1ZGVzIHB1Ymxpc2hlZCBjbmlkYXJpYW4gbWlSTkFzOgoKLSBbYGNuaWRhcmlhbi1taXJiYXNlLW1hdHVyZS12MjIuMS5mYXN0YWBdKC4uLy4uL2RhdGEvY25pZGFyaWFuLW1pcmJhc2UtbWF0dXJlLXYyMi4xLmZhc3RhKQoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpJbnB1dHM6CgotICAgUmVxdWlyZXMgdHJpbW1lZCBzUk5Bc2VxIGZpbGVzIGdlbmVyYXRlZCBpbiBgMDEuMTAtRC1BcHVsLXNSTkFzZXEtdHJpbW1pbmctZmFzdHAtRmFzdFFDLU11bHRpUUNgIAoKICAgIC0gICBGaWxlbmFtZXMgZm9ybWF0dGVkOiBgKmZhc3RwLWFkYXB0ZXJzLXBvbHlHLTMxYnAtbWVyZ2VkLmZxLmd6YAoKLSAgICpBLnB1bGNocmEqIGdlbm9tZSBGYXN0QS4gTm90IGN1cnJlbnRseSBwdWJsaWNseSBhdmFpbGFibGUgKHN0aWxsIGJlaW5nIGFubm90YXRlZCBieSBjb2xsYWJvcmF0b3JzKQoKT3V0cHV0czoKCi0gICBTZWUgW1Nob3J0U3RhY2sgb3V0cHV0cyBkb2N1bWVudGF0aW9uXShodHRwczovL2dpdGh1Yi5jb20vTWlrZUF4dGVsbC9TaG9ydFN0YWNrI291dHB1dHMpIGZvciBmdWxsIGxpc3QgYW5kIGRldGFpbGVkIGRlc2NyaXB0aW9ucy4KClNvZnR3YXJlIHJlcXVpcmVtZW50czoKCi0gICBVdGlsaXplcyBhIFtTaG9ydFN0YWNrXShodHRwczovL2dpdGh1Yi5jb20vTWlrZUF4dGVsbC9TaG9ydFN0YWNrI2luc3RhbGxhdGlvbikgQ29uZGEvTWFtYmEgZW52aXJvbm1lbnQsIHBlciB0aGUgaW5zdGFsbGF0aW9uIGluc3RydWN0aW9ucy4KClJlcGxhY2Ugd2l0aCBuYW1lIG9mIHlvdXIgU2hvcnRTdGFjayBlbnZpcm9ubWVudCBhbmQgdGhlIHBhdGggdG8gdGhlIGNvcnJlc3BvbmRpbmcgY29uZGEgaW5zdGFsbGF0aW9uIChmaW5kIHRoaXMgKmFmdGVyKiB5b3UndmUgYWN0aXZhdGVkIHRoZSBlbnZpcm9ubWVudCkuCgpFLmcuCgpgYGAgYmFzaAojIEFjdGl2YXRlIGVudmlyb25tZW50CmNvbmRhIGFjdGl2YXRlIFNob3J0U3RhY2s0X2VudgoKIyBGaW5kIGNvbmRhIHBhdGgKd2hpY2ggY29uZGEKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgU2V0IFIgdmFyaWFibGVzCgpgYGB7ciBSLXZhcmlhYmxlcywgZXZhbD1UUlVFfQpzaG9ydHN0YWNrX2NvbmRhX2Vudl9uYW1lIDwtIGMoIlNob3J0U3RhY2stNC4xLjBfZW52IikKc2hvcnRzdGFja19jb25kX3BhdGggPC0gYygiL2hvbWUvc2FtL3Byb2dyYW1zL21hbWJhZm9yZ2UvY29uZGFiaW4vY29uZGEiKQpgYGAKCiMgQ3JlYXRlIGEgQmFzaCB2YXJpYWJsZXMgZmlsZQoKVGhpcyBhbGxvd3MgdXNhZ2Ugb2YgQmFzaCB2YXJpYWJsZXMgYWNyb3NzIFIgTWFya2Rvd24gY2h1bmtzLgoKYGBge3Igc2F2ZS1iYXNoLXZhcmlhYmxlcy10by1ydmFycy1maWxlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CnsKZWNobyAiIyMjIyBBc3NpZ24gVmFyaWFibGVzICMjIyMiCmVjaG8gIiIKCmVjaG8gIiMgVHJpbW1lZCBGYXN0USBuYW1pbmcgcGF0dGVybiIKZWNobyAiZXhwb3J0IHRyaW1tZWRfZmFzdHFzX3BhdHRlcm49JypmYXN0cC1hZGFwdGVycy1wb2x5Ry0zMWJwLW1lcmdlZC5mcS5neiciCgplY2hvICIjIERhdGEgZGlyZWN0b3JpZXMiCmVjaG8gJ2V4cG9ydCB0aW1lc2VyaWVzX2Rpcj0vaG9tZS9zaGFyZWQvOFRCX0hERF8wMi9zaGVkdXJraW4vdGltZXNlcmllc19tb2xlY3VsYXInCmVjaG8gJ2V4cG9ydCB0aW1lc2VyaWVzX2RhdGFfZGlyPSIke3RpbWVzZXJpZXNfZGlyfS9NLW11bHRpLXNwZWNpZXMvZGF0YSInCmVjaG8gJ2V4cG9ydCBvdXRwdXRfZGlyX3RvcD0ke3RpbWVzZXJpZXNfZGlyfS9ELUFwdWwvb3V0cHV0LzA0LUFwdWwtc1JOQS1kaXNjb3ZlcnktU2hvcnRTdGFjaycKZWNobyAiIgoKZWNobyAiIyBJbnB1dC9PdXRwdXQgZmlsZXMiCmVjaG8gJ2V4cG9ydCBnZW5vbWVfZmFzdGFfZGlyPSR7dGltZXNlcmllc19kaXJ9L0QtQXB1bC9kYXRhJwplY2hvICdleHBvcnQgZ2Vub21lX2Zhc3RhX25hbWU9IkFwdWxjaHJhLWdlbm9tZS5mYSInCmVjaG8gJ2V4cG9ydCBzaG9ydHN0YWNrX2dlbm9tZV9mYXN0YV9uYW1lPSJBcHVsY2hyYS1nZW5vbWUuZmEiJwplY2hvICdleHBvcnQgdHJpbW1lZF9mYXN0cXNfZGlyPSIke3RpbWVzZXJpZXNfZGlyfS9ELUFwdWwvb3V0cHV0LzAxLjEwLUQtQXB1bC1zUk5Bc2VxLXRyaW1taW5nLWZhc3RwLUZhc3RRQy1NdWx0aVFDL3RyaW1tZWQtZmFzdHFzLXNSTkEiJwoKZWNobyAnZXhwb3J0IG1pcmJhc2VfbWF0dXJlX2Zhc3RhX3ZlcnNpb249Y25pZGFyaWFuLW1pcmJhc2UtbWF0dXJlLXYyMi4xLmZhc3RhJwplY2hvICdleHBvcnQgZ2Vub21lX2Zhc3RhPSIke2dlbm9tZV9mYXN0YV9kaXJ9LyR7c2hvcnRzdGFja19nZW5vbWVfZmFzdGFfbmFtZX0iJwplY2hvICIiCgplY2hvICIjIFNldCBudW1iZXIgb2YgQ1BVcyB0byB1c2UiCmVjaG8gJ2V4cG9ydCB0aHJlYWRzPTQwJwplY2hvICIiCgplY2hvICIjIEluaXRpYWxpemUgYXJyYXlzIgplY2hvICdleHBvcnQgdHJpbW1lZF9mYXN0cXNfYXJyYXk9KCknCgoKfSA+IC5iYXNodmFycwoKY2F0IC5iYXNodmFycwpgYGAKCiMgTG9hZCBbU2hvcnRTdGFja10oaHR0cHM6Ly9naXRodWIuY29tL01pa2VBeHRlbGwvU2hvcnRTdGFjaykgY29uZGEgZW52aXJvbm1lbnQKCklmIHRoaXMgaXMgc3VjY2Vzc2Z1bCwgdGhlIGZpcnN0IGxpbmUgb2Ygb3V0cHV0IHNob3VsZCBzaG93IHRoYXQgdGhlIFB5dGhvbiBiZWluZyB1c2VkIGlzIHRoZSBvbmUgaW4geW91ciBbU2hvcnRTdGFja10oPGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlQXh0ZWxsL1Nob3J0U3RhY2s+IGNvbmRhIGVudmlyb25tZW50IHBhdGguCgpFLmcuCgpgcHl0aG9uOiAgICAgICAgIC9ob21lL3NhbS9wcm9ncmFtcy9tYW1iYWZvcmdlL2VudnMvbWlybWFjaGluZV9lbnYvYmluL3B5dGhvbmAKCmBgYHtyIGxvYWQtc2hvcnRzdGFjay1jb25kYS1lbnYsIGV2YWw9VFJVRX0KdXNlX2NvbmRhZW52KGNvbmRhZW52ID0gc2hvcnRzdGFja19jb25kYV9lbnZfbmFtZSwgY29uZGEgPSBzaG9ydHN0YWNrX2NvbmRfcGF0aCkKcHlfY29uZmlnKCkKYGBgCk5vdGU6IEkgc29tZXRpbWVzIGdldCBhbiBlcnJvciAiZmFpbGVkIHRvIGluaXRpYWxpemUgcmVxdWVzdGVkIHZlcnNpb24gb2YgUHl0aG9uLCIgd2hpY2ggc2VlbXMgdG8gc3RlbSBmcm9tIHRoZSBgcmV0aWN1bGF0ZWAgcGFja2FnZSBkZWZhdWx0IGxvYWRpbmcgYSBweXRob24gZW52aXJvbm1lbnQuIEkndmUgYmVlbiBhYmxlIHRvIGZpeCB0aGlzIGJ5IG1hbnVhbGx5IHVuaW5zdGFsbGluZyB0aGUgYHJldGljdWxhdGVgIHBhY2thZ2UsIHRoZW4gcmVzdGFydGluZyBSIGFuZCByZWluc3RhbGxpbmcgYHJldGljdWxhdGVgIGJlZm9yZSByZXJ1bm5pbmcgdGhpcyBjb2RlIGRvY3VtZW50LgojIERvd25sb2FkIHJlZmVyZW5jZSBmaWxlcwoKIyMgQS5wdWxjaHJhIGdlbm9tZQoKYGBge3IgZG93bmxvYWQtZ2Vub21lLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKd2dldCAtTyAke2dlbm9tZV9mYXN0YV9kaXJ9LyR7c2hvcnRzdGFja19nZW5vbWVfZmFzdGFfbmFtZX0gImh0dHBzOi8vb3NmLmlvL2Rvd25sb2FkL2tuOTZ1LyIKYGBgCgojIyBDbmlkYXJpYW4rbWlSQmFzZSBkYXRhYmFzZQoKQXZhaWxhYmxlIGluIGBkZWVwLWRpdmVgIHJlcG8sIFtoZXJlXShodHRwczovL2dpdGh1Yi5jb20vdXJvbC1lNS9kZWVwLWRpdmUvYmxvYi9tYWluL2RhdGEvY25pZGFyaWFuLW1pcmJhc2UtbWF0dXJlLXYyMi4xLmZhc3RhKQoKYGBge3IgZG93bmxvYWQtZGIsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgp3Z2V0IC1PICR7dGltZXNlcmllc19kYXRhX2Rpcn0vIiR7bWlyYmFzZV9tYXR1cmVfZmFzdGFfdmVyc2lvbn0iICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vdXJvbC1lNS9kZWVwLWRpdmUvcmVmcy9oZWFkcy9tYWluL2RhdGEvY25pZGFyaWFuLW1pcmJhc2UtbWF0dXJlLXYyMi4xLmZhc3RhIgpgYGAKCmBgYHtyIGNoZWNrLWRiLWZpbGUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmhlYWQgLTUgJHt0aW1lc2VyaWVzX2RhdGFfZGlyfS8iJHttaXJiYXNlX21hdHVyZV9mYXN0YV92ZXJzaW9ufSIKYGBgCgojIyBUcmltbWVkIHNSTkEtc2VxIHJlYWRzCgpUcmltbWVkIGluIGAwMS4xMC1ELUFwdWwtc1JOQXNlcS10cmltbWluZy1mYXN0cC1GYXN0UUMtTXVsdGlRQ2AKCiMgUnVuIFNob3J0U3RhY2sKCiMjIE1vZGlmeSBnZW5vbWUgZmlsZW5hbWUgZm9yIFNob3J0U3RhY2sgY29tcGF0YWJpbGl0eQoKYGBge3IgcmVuYW1lLWdlbm9tZS1maWxlbmFtZSwgZW5naW5lPSdiYXNoJywgY2FjaGU9VFJVRSwgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyBDaGVjayBmb3IgRmFzdEEgZmlsZSBmaXJzdAojIFRoZW4gY3JlYXRlIHJlbmFtZSBmaWxlIGlmIGRvZXNuJ3QgZXhpc3QKaWYgWyAtZiAiJHtnZW5vbWVfZmFzdGFfZGlyfS8ke3Nob3J0c3RhY2tfZ2Vub21lX2Zhc3RhX25hbWV9IiBdOyB0aGVuCiAgZWNobyAiJHtnZW5vbWVfZmFzdGFfZGlyfS8ke3Nob3J0c3RhY2tfZ2Vub21lX2Zhc3RhX25hbWV9IgogIGVjaG8gIiIKICBlY2hvICJBbHJlYWR5IGV4aXN0cy4gTm90aGluZyB0byBkby4iCiAgZWNobyAiIgplbHNlCgogICMgQ29weSBnZW5vbWUgRmFzdEEgdG8gU2hvcnRTdGFjay1jb21wYXRpYmxlIGZpbGVuYW1lIChlbmRpbmcgd2l0aCAuZmEpCiAgY3AgJHtnZW5vbWVfZmFzdGFfZGlyfS8ke2dlbm9tZV9mYXN0YV9uYW1lfSAke2dlbm9tZV9mYXN0YV9kaXJ9LyR7c2hvcnRzdGFja19nZW5vbWVfZmFzdGFfbmFtZX0KZmkKCiMgQ29uZmlybQpscyAtbGggJHtnZW5vbWVfZmFzdGFfZGlyfS8ke3Nob3J0c3RhY2tfZ2Vub21lX2Zhc3RhX25hbWV9CmBgYAoKCiMjIEV4Y2VjdXRlIFNob3J0U3RhY2sgY29tbWFuZAoKVXNlcyB0aGUgYC0tZG5fbWlybmFgIG9wdGlvbiB0byBpZGVudGlmeSBtaVJOQXMgaW4gdGhlIGdlbm9tZSwgd2l0aG91dCByZWx5aW5nIG9uIHRoZSBgLS1rbm93bl9taVJOQXNgLgoKVGhpcyBwYXJ0IG9mIHRoZSBjb2RlIHJlZGlyZWN0cyB0aGUgb3V0cHV0IG9mIGB0aW1lYCB0byB0aGUgZW5kIG9mIGBzaG9ydHN0YWNrLmxvZ2AgZmlsZS4KCi0gICBgOyB9IFwgMj4+ICR7b3V0cHV0X2Rpcl90b3B9L3Nob3J0c3RhY2subG9nYAoKCgpgYGB7ciBzaG9ydHN0YWNrLCBlbmdpbmU9J2Jhc2gnLCBjYWNoZT1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyBNYWtlIG91dHB1dCBkaXJlY3RvcnksIGlmIGl0IGRvZXNuJ3QgZXhpc3QKbWtkaXIgLS1wYXJlbnRzICIke291dHB1dF9kaXJfdG9wfSIKCiMgQ3JlYXRlIGFycmF5IG9mIHRyaW1tZWQgRmFzdFFzCnRyaW1tZWRfZmFzdHFzX2FycmF5PSgke3RyaW1tZWRfZmFzdHFzX2Rpcn0vJHt0cmltbWVkX2Zhc3Rxc19wYXR0ZXJufSkKCgojIFBhc3MgYXJyYXkgY29udGVudHMgdG8gbmV3IHZhcmlhYmxlIGFzIHNwYWNlLWRlbGltaXRlZCBsaXN0CnRyaW1tZWRfZmFzdHFzX2xpc3Q9JChlY2hvICIke3RyaW1tZWRfZmFzdHFzX2FycmF5WypdfSIpCgoKIyMjIyMjIFJ1biBTaG9ydFN0YWNrICMjIyMjIwp7IHRpbWUgXApTaG9ydFN0YWNrIFwKLS1nZW5vbWVmaWxlICIke2dlbm9tZV9mYXN0YX0iIFwKLS1yZWFkZmlsZSAke3RyaW1tZWRfZmFzdHFzX2xpc3R9IFwKLS1rbm93bl9taVJOQXMgJHt0aW1lc2VyaWVzX2RhdGFfZGlyfS8ke21pcmJhc2VfbWF0dXJlX2Zhc3RhX3ZlcnNpb259IFwKLS1kbl9taXJuYSBcCi0tdGhyZWFkcyAke3RocmVhZHN9IFwKLS1vdXRkaXIgJHtvdXRwdXRfZGlyX3RvcH0vU2hvcnRTdGFja19vdXQgXAomPiAke291dHB1dF9kaXJfdG9wfS9zaG9ydHN0YWNrLmxvZyA7IH0gXAoyPj4gJHtvdXRwdXRfZGlyX3RvcH0vc2hvcnRzdGFjay5sb2cKCmBgYAoKIyMgQ2hlY2sgcnVudGltZQoKYGBge3IgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKdGFpbCAtbiAzICR7b3V0cHV0X2Rpcl90b3B9L3Nob3J0c3RhY2subG9nIFwKfCBncmVwICJyZWFsIiBcCnwgYXdrICd7cHJpbnQgIlNob3J0U3RhY2sgcnVudGltZToiICJcdCIgJDJ9JwoKYGBgCgoKIyBSZXN1bHRzCgojIyBTaG9ydFN0YWNrIHN5bm9wc2lzCgpgYGB7ciBzaG9ydHN0YWNrLXN5bm9wc2lzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgp0YWlsIC1uIDI1ICR7b3V0cHV0X2Rpcl90b3B9L3Nob3J0c3RhY2subG9nCmBgYAoKU2hvcnRTdGFjayBpZGVudGlmaWVkIDUxIG1pUk5BcyBhbW9uZyBhbGwgb2YgdGhlIEEucHVsY2hyYSBzYW1wbGVzLiBUaGlzIGlzIGEgbm90YWJseSBsYXJnZXIgbnVtYmVyIHRoYW4gdGhlIDM5IG1pUk5BcyBpZGVudGlmaWVkIGluIGBkZWVwLWRpdmUtZXhwcmVzc2lvbmAsIHdoaWNoIGV4YW1pbmVkIG9ubHkgNSBjb2xvbmllcyBmcm9tIGEgc2luZ2xlIHRpbWUgcG9pbnQhIEkgd291bGQgZ3Vlc3MgdGhlIGRpZmZlcmVuY2Ugc3RlbXMgZnJvbSBlaXRoZXIgKGEpIG91ciBjYXB0dXJlIG9mIG1vcmUgaW50cmFzcGVjaWZpYyBkaXZlcnNpdHksIG9yIChiKSBkaWZmZXJlbnQgbWlSTkEgcHJvZmlsZXMgYXNzb2NpYXRlZCB3aXRoIGRpZmZlcmVudCBlbnZpcm9ubWVudGFsIGNvbmRpdGlvbnMgKGkuZS4gc29tZSBBLnB1bGNocmEgbWlSTkFzIGFyZSBvbmx5IGV4cHJlc3NlZCB1bmRlciBjZXJ0YWluIGNvbmRpdGlvbnMpLiBUaGUgY291bnRzIGRhdGEgc2hvdWxkIGdpdmUgdXMgbW9yZSBpbnNpZ2h0LgoKIyMgSW5zcGVjdCBgUmVzdWx0cy50eHRgCgpgYGB7ciByZXN1bHRzLXR4dC1maWxlLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgpoZWFkICR7b3V0cHV0X2Rpcl90b3B9L1Nob3J0U3RhY2tfb3V0L1Jlc3VsdHMudHh0CgplY2hvICIiCmVjaG8gIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0iCmVjaG8gIiIKCmVjaG8gIk51bW1iZXIgb2YgcG90ZW50aWFsIGxvY2k6Igphd2sgJyhOUj4xKScgJHtvdXRwdXRfZGlyX3RvcH0vU2hvcnRTdGFja19vdXQvUmVzdWx0cy50eHQgfCB3YyAtbApgYGAKCkNvbHVtbiAyMCBvZiB0aGUgYFJlc3VsdHMudHh0YCBmaWxlIGlkZW50aWZpZXMgaWYgYSBjbHVzdGVyIGlzIGEgbWlSTkEgb3Igbm90IChgWWAgb3IgYE5gKS4KCmBgYHtyIHJlc3VsdHMtdHh0LW1pUk5BcywgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKZWNobyAiTnVtYmVyIG9mIGxvY2kgY2hhcmFjdGVyaXplZCBhcyBtaVJOQToiCmF3ayAnJDIwPT0iWSIge3ByaW50ICQwfScgJHtvdXRwdXRfZGlyX3RvcH0vU2hvcnRTdGFja19vdXQvUmVzdWx0cy50eHQgXAp8IHdjIC1sCmVjaG8gIiIKCmVjaG8gIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0iCgplY2hvICIiCmVjaG8gIk51bWJlciBvZiBsb2NpIF9ub3RfIGNoYXJhY3Rlcml6ZWQgYXMgbWlSTkE6Igphd2sgJyQyMD09Ik4iIHtwcmludCAkMH0nICR7b3V0cHV0X2Rpcl90b3B9L1Nob3J0U3RhY2tfb3V0L1Jlc3VsdHMudHh0IFwKfCB3YyAtbAoKYGBgCgpDb2x1bW4gMjEgb2YgdGhlIGBSZXN1bHRzLnR4dGAgZmlsZSBpZGVudGlmaWVzIGlmIGEgY2x1c3RlciBhbGlnbmVkIHRvIGEga25vd24gbWlSTkEgKG1pUkJhc2UpIG9yIG5vdCAoYFlgIG9yIGBOQWApLgoKVGhlIGBlY2hvYCBjb21tYW5kIGFmdGVyIHRoZSBgYXdrYCBjb21tYW5kIGlzIHNpbXBseSB0aGVyZSB0byBwcm92ZSB0aGF0IHRoZSBjaHVuayBleGVjdXRlZC4KCmBgYHtyIHJlc3VsdHMtdHh0LW1pUkJhc2UtbWlSTkFzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPVRSVUV9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgplY2hvICJOdW1iZXIgb2YgbG9jaSBtYXRjaGluZyBtaVJCYXNlIG1pUk5BczoiCmF3ayAnJDIxIT0iTkEiIHtwcmludCAkMH0nICR7b3V0cHV0X2Rpcl90b3B9L1Nob3J0U3RhY2tfb3V0L1Jlc3VsdHMudHh0IFwKfCB3YyAtbAplY2hvICIiCgplY2hvICItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIgoKZWNobyAiIgplY2hvICJOdW1iZXIgb2YgbG9jaSBfbm90XyBtYXRjaGluZyBtaVJCYXNlIG1pUk5BczoiCmF3ayAnJDIxPT0iTkEiIHtwcmludCAkMH0nICR7b3V0cHV0X2Rpcl90b3B9L1Nob3J0U3RhY2tfb3V0L1Jlc3VsdHMudHh0IFwKfCB3YyAtbAoKYGBgCgojIyMgRGlyZWN0b3J5IHRyZWUgb2YgYWxsIFNob3J0U3RhY2sgb3V0cHV0cwoKTWFueSBvZiB0aGVzZSBhcmUgbGFyZ2UgKGJ5IEdpdEh1YiBzdGFuZGFyZHMpIEJBTSBmaWxlcywgc28gd2lsbCBub3QgYmUgYWRkZWQgdG8gdGhlIHJlcG8uCgpBZGRpdGlvbmFsbHksIGl0J3MgdW5saWtlbHkgd2UnbGwgdXRpbGl6ZSBtb3N0IG9mIHRoZSBvdGhlciBmaWxlcyAoYmlnd2lnKSBnZW5lcmF0ZWQgYnkgU2hvcnRTdGFjay4KCmBgYHtyIHNob3J0c3RhY2stZGlyZWN0b3J5LXRyZWUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCnRyZWUgLWggJHtvdXRwdXRfZGlyX3RvcH0vCgpgYGAKCgojIyBWaXN1YWxpemUKCldlIG5vdGljZWQgdGhhdCBhKSBub3QgYWxsIG9mIHRoZSBpZGVudGlmaWVkIG1pUk5BcyBoYXZlIGRhdGFiYXNlIG1hdGNoZXMsIGFuZCBiKSBzb21lIHJlYWRzIGhhdmUgYSBtYXRjaCBpbiB0aGUgZGF0YWJhc2UgYnV0IGFyZSAqbm90KiBjbGFzc2lmaWVkIGFzIG1pUk5Bcy4gTGV0J3MgbG9vayBhdCB0aGlzIGluIG1vcmUgZGVwdGguCgpgYGB7ciBsb2FkLXJlc3VsdHMsIGV2YWw9VFJVRX0KQXB1bF9zaG9ydHN0YWNrX3Jlc3VsdHMgPC0gcmVhZC5jc3YoIi4uL291dHB1dC8wNC1BcHVsLXNSTkEtZGlzY292ZXJ5LVNob3J0U3RhY2svU2hvcnRTdGFja19vdXQvUmVzdWx0cy50eHQiLCBzZXA9Ilx0IikKYGBgCgpgYGB7ciBnZW5lcmF0ZS1wbG90cywgZXZhbD1UUlVFfQojIFJlYWRzIGlkZW50aWZpZWQgYXMgbWlSTkFzIChidXQgbm90IG5lY2Vzc2FyaWx5IGtub3duKQpBcHVsX3Nob3J0c3RhY2tfcmVzdWx0cyAlPiUgCiAgZmlsdGVyKE1JUk5BID09ICJZIikgJT4lCiAgbXV0YXRlKGtub3duX21pUk5BcyA9IHN0cl9zdWIoa25vd25fbWlSTkFzLCAxLCA0MCkpICU+JQogIG11dGF0ZShMb2N1cyA9IHN0cl9zdWIoTG9jdXMsIDIwLCA0MCkpICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoTG9jdXMsIFJlYWRzKSwgeSA9IFJlYWRzLCBmaWxsID0ga25vd25fbWlSTkFzKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBSZWFkcyksIHZqdXN0ID0gMC41LCBoanVzdCA9IDAsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIuNSwgYW5nbGUgPSA5MCkgKwogIGxhYnMoeCA9ICJtaVJOQSIsIHkgPSAiUmVhZCBjb3VudCIsIAogICAgICAgdGl0bGUgPSAiUmVhZHMgaWRlbnRpZmllZCBieSBTaG9ydFN0YWNrIGFzIG1pUk5BcyIsCiAgICAgICBmaWxsID0gIkFubm90YXRpb24iKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpKQogIApnZ3NhdmUoIi4uL291dHB1dC8wNC1BcHVsLXNSTkEtZGlzY292ZXJ5LVNob3J0U3RhY2svZmlndXJlcy9BcHVsX1Nob3J0U3RhY2tfbWlSTkFfaGlzdG9ncmFtLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIHVuaXRzID0gImluIikKCgojIFJlYWRzIG1hdGNoZWQgaW4gdGhlIHJlZmVyZW5jZSBkYiAoYnV0IG5vdCBuZWNlc3NhcmlseSBpZGVudGlmaWVkIGFzIG1pUk5BKQpBcHVsX3Nob3J0c3RhY2tfcmVzdWx0cyAlPiUgCiAgZmlsdGVyKCFpcy5uYShrbm93bl9taVJOQXMpKSAlPiUKICBtdXRhdGUoa25vd25fbWlSTkFzID0gc3RyX3N1Yihrbm93bl9taVJOQXMsIDEsIDQwKSkgJT4lCiAgbXV0YXRlKExvY3VzID0gc3RyX3N1YihMb2N1cywgMjAsIDQwKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihMb2N1cywgUmVhZHMpLCB5ID0gUmVhZHMsIGZpbGwgPSBNSVJOQSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBSZWFkcyksIHZqdXN0ID0gMC41LCBoanVzdCA9IDAsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIuNSwgYW5nbGUgPSA5MCkgKwogIGxhYnMoeCA9ICJtaVJOQSIsIHkgPSAiUmVhZCBjb3VudCIsIAogICAgICAgdGl0bGUgPSAiUmVhZHMgd2l0aCBtaVJCYXNlK2NuaWRhcmlhbiBkYXRhYmFzZSBtYXRjaGVzIiwKICAgICAgIGZpbGwgPSAiSWRlbnRpZmllZCBhcyBtaVJOQT8iKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpKQoKZ2dzYXZlKCIuLi9vdXRwdXQvMDQtQXB1bC1zUk5BLWRpc2NvdmVyeS1TaG9ydFN0YWNrL2ZpZ3VyZXMvQXB1bF9TaG9ydFN0YWNrX2RibWF0Y2hfaGlzdG9ncmFtLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIHVuaXRzID0gImluIikKYGBgCgpUaGVyZSdzIGEgZmV3IG1pUk5BcyB3aXRoIHZlcnkgaGlnaCByZWFkIGNvdW50cywgYW5kIGl0J3MgbWFraW5nIHZpc3VhbGl6YXRpb24gb2YgdGhlIHJlc3QgZGlmZmljdWx0LiBMZXQncyByZW1vdmUgdGhlbSBhbmQgcmV0cnkgdmlzdWFsaXppbmcgdGhlIHJlc3QuCgpgYGB7ciBnZW5lcmF0ZS1wbG90cy1yZWR1Y2VkLCBldmFsPVRSVUV9CiMgUmVhZHMgaWRlbnRpZmllZCBhcyBtaVJOQXMgKGJ1dCBub3QgbmVjZXNzYXJpbHkga25vd24pCkFwdWxfc2hvcnRzdGFja19yZXN1bHRzICU+JSAKICBmaWx0ZXIoTUlSTkEgPT0gIlkiKSAlPiUKICBmaWx0ZXIoUmVhZHMgPCAxMDAwMDApICU+JQogIG11dGF0ZShrbm93bl9taVJOQXMgPSBzdHJfc3ViKGtub3duX21pUk5BcywgMSwgNDApKSAlPiUKICBtdXRhdGUoTG9jdXMgPSBzdHJfc3ViKExvY3VzLCAyMCwgNDApKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKExvY3VzLCBSZWFkcyksIHkgPSBSZWFkcywgZmlsbCA9IGtub3duX21pUk5BcykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICBnZW9tX3RleHQoYWVzKGxhYmVsID0gUmVhZHMpLCB2anVzdCA9IDAuNSwgaGp1c3QgPSAwLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyLjUsIGFuZ2xlID0gOTApICsKICBsYWJzKHggPSAibWlSTkEiLCB5ID0gIlJlYWQgY291bnQiLCAKICAgICAgIHRpdGxlID0gIlJlYWRzIGlkZW50aWZpZWQgYnkgU2hvcnRTdGFjayBhcyBtaVJOQXMiLAogICAgICAgZmlsbCA9ICJBbm5vdGF0aW9uIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSkKICAKZ2dzYXZlKCIuLi9vdXRwdXQvMDQtQXB1bC1zUk5BLWRpc2NvdmVyeS1TaG9ydFN0YWNrL2ZpZ3VyZXMvQXB1bF9TaG9ydFN0YWNrX21pUk5BX2hpc3RvZ3JhbV9yZWR1Y2VkLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIHVuaXRzID0gImluIikKCgojIFJlYWRzIG1hdGNoZWQgaW4gdGhlIHJlZmVyZW5jZSBkYiAoYnV0IG5vdCBuZWNlc3NhcmlseSBpZGVudGlmaWVkIGFzIG1pUk5BKQpBcHVsX3Nob3J0c3RhY2tfcmVzdWx0cyAlPiUgCiAgZmlsdGVyKCFpcy5uYShrbm93bl9taVJOQXMpKSAlPiUKICBmaWx0ZXIoUmVhZHMgPCAxMDAwMDApICU+JQogIG11dGF0ZShrbm93bl9taVJOQXMgPSBzdHJfc3ViKGtub3duX21pUk5BcywgMSwgNDApKSAlPiUKICBtdXRhdGUoTG9jdXMgPSBzdHJfc3ViKExvY3VzLCAyMCwgNDApKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKExvY3VzLCBSZWFkcyksIHkgPSBSZWFkcywgZmlsbCA9IE1JUk5BKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFJlYWRzKSwgdmp1c3QgPSAwLjUsIGhqdXN0ID0gMCwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMi41LCBhbmdsZSA9IDkwKSArCiAgbGFicyh4ID0gIm1pUk5BIiwgeSA9ICJSZWFkIGNvdW50IiwgCiAgICAgICB0aXRsZSA9ICJSZWFkcyB3aXRoIG1pUkJhc2UrY25pZGFyaWFuIGRhdGFiYXNlIG1hdGNoZXMiLAogICAgICAgZmlsbCA9ICJJZGVudGlmaWVkIGFzIG1pUk5BPyIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUoIi4uL291dHB1dC8wNC1BcHVsLXNSTkEtZGlzY292ZXJ5LVNob3J0U3RhY2svZmlndXJlcy9BcHVsX1Nob3J0U3RhY2tfZGJtYXRjaF9oaXN0b2dyYW1fcmVkdWNlZC5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCB1bml0cyA9ICJpbiIpCmBgYApJdCBzZWVtcyBsaWtlIGFuIHNSTmEgaXMgYm90aCBtb3JlIGxpa2VseSB0byBiZSBwcmV2aW91c2x5IGRlc2NyaWJlZCBhbmQgdG8gaGF2ZSBiZWVuIGFubm90ZWQgYnkgU2hvcnRTdGFjayBhcyBhbiBtaVJOQSBpZiBpdCBpcyBtb3JlIGhpZ2hseSBleHByZXNzZWQuCgpgYGB7ciB2ZW5uLWRpYWdyYW0sIGV2YWw9VFJVRX0KIyBNYWtlIGxpc3QKbWlybmFzIDwtIEFwdWxfc2hvcnRzdGFja19yZXN1bHRzICU+JSBmaWx0ZXIoTUlSTkEgPT0gIlkiKSAlPiUgcHVsbChMb2N1cykKbWF0Y2hlcyA8LSBBcHVsX3Nob3J0c3RhY2tfcmVzdWx0cyAlPiUgZmlsdGVyKCFpcy5uYShrbm93bl9taVJOQXMpKSAlPiUgcHVsbChMb2N1cykKCkFwdWxfc2hvcnRzdGFja192ZW5ubGlzdCA8LSBsaXN0KAogICJJZGVudGlmaWVkIGFzIG1pUk5BIiA9IG1pcm5hcywKICAiRGF0YWJhc2UgbWF0Y2giID0gbWF0Y2hlcwopCgojIE1ha2UgdmVubiBkaWFncmFtcwpnZ3Zlbm4oQXB1bF9zaG9ydHN0YWNrX3Zlbm5saXN0KQoKZ2dzYXZlKCIuLi9vdXRwdXQvMDQtQXB1bC1zUk5BLWRpc2NvdmVyeS1TaG9ydFN0YWNrL2ZpZ3VyZXMvQXB1bF9TaG9ydFN0YWNrX3Zlbm4ucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgdW5pdHMgPSAiaW4iKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBDaXRhdGlvbnM=