Code for trimming and QCing RNAseq data, to be used on Pacific cod RNAseq data, raw reads found here
FastQC/MultiQC assessment of raw and flexbar-trimmed sequences of
Inputs:
- RNAseq gzipped FastQs (e.g.
*.fastq.gz
)
Outputs:
FastQC
HTML reports for raw and trimmed reads.
MultiQC
HTML summaries of FastQC
for raw and trimmed reads.
Trimmed reads: *flexbar_trim.fastq.gz
(info about library prep/sequencing)
Create a Bash variables file
This allows usage of Bash variables (e.g. paths to common directories) across R Markdown chunks.
{
echo "#### Assign Variables ####"
echo ""
echo "# Data directories"
echo 'export cod_dir=/home/shared/8TB_HDD_02/shedurkin/project-cod-temperature'
echo 'export output_dir_top=${cod_dir}/output/05-cod-RNAseq-trimming'
echo 'export raw_fastqc_dir=${output_dir_top}/raw-fastqc'
echo 'export raw_reads_dir=${cod_dir}/data/05-cod-RNAseq-trimming/raw-reads'
echo 'export raw_reads_url="https://owl.fish.washington.edu/nightingales/G_macrocephalus/30-943133806/"'
echo 'export trimmed_fastqc_dir=${output_dir_top}/trimmed-fastqc'
echo 'export trimmed_reads_dir=${output_dir_top}/trimmed-reads'
echo ""
echo "# Paths to programs"
echo 'export fastqc=/home/shared/FastQC-0.12.1/fastqc'
echo 'export multiqc=/home/sam/programs/mambaforge/bin/multiqc'
echo 'export flexbar=/home/shared/flexbar-3.5.0-linux/flexbar'
echo ""
echo "# Set FastQ filename patterns"
echo "export fastq_pattern='*.fastq.gz'"
echo "export R1_fastq_pattern='*_R1_*.fastq.gz'"
echo "export R2_fastq_pattern='*_R2_*.fastq.gz'"
echo ""
echo "# Set number of CPUs to use"
echo 'export threads=20'
echo ""
echo "# Input/output files"
echo 'export fastq_checksums=input_fastq_checksums.md5'
echo 'export trimmed_checksums=trimmed_fastq_checksums.md5'
echo 'export NEB_adapters_fasta=NEB-adapters.fasta'
echo ""
echo "## Illumina adapters"
echo 'export first_adapter="AGATCGGAAGAGCACACGTCTGAACTCCAGTCA"'
echo 'export second_adapter="AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT"'
echo ""
echo "## Inititalize arrays"
echo 'export fastq_array_R1=()'
echo 'export fastq_array_R2=()'
echo 'export raw_fastqs_array=()'
echo 'export R1_names_array=()'
echo 'export R2_names_array=()'
echo 'export trimmed_fastqs_array=()'
echo ""
echo "# Programs associative array"
echo "declare -A programs_array"
echo "programs_array=("
echo '[fastqc]="${fastqc}" \'
echo '[multiqc]="${multiqc}" \'
echo '[flexbar]="${flexbar}"'
echo ")"
} > .bashvars
cat .bashvars
#### Assign Variables ####
# Data directories
export cod_dir=/home/shared/8TB_HDD_02/shedurkin/project-cod-temperature
export output_dir_top=${cod_dir}/output/05-cod-RNAseq-trimming
export raw_fastqc_dir=${output_dir_top}/raw-fastqc
export raw_reads_dir=${cod_dir}/data/05-cod-RNAseq-trimming/raw-reads
export raw_reads_url="https://owl.fish.washington.edu/nightingales/G_macrocephalus/30-943133806/"
export trimmed_fastqc_dir=${output_dir_top}/trimmed-fastqc
export trimmed_reads_dir=${output_dir_top}/trimmed-reads
# Paths to programs
export fastqc=/home/shared/FastQC-0.12.1/fastqc
export multiqc=/home/sam/programs/mambaforge/bin/multiqc
export flexbar=/home/shared/flexbar-3.5.0-linux/flexbar
# Set FastQ filename patterns
export fastq_pattern='*.fastq.gz'
export R1_fastq_pattern='*_R1_*.fastq.gz'
export R2_fastq_pattern='*_R2_*.fastq.gz'
# Set number of CPUs to use
export threads=20
# Input/output files
export fastq_checksums=input_fastq_checksums.md5
export trimmed_checksums=trimmed_fastq_checksums.md5
export NEB_adapters_fasta=NEB-adapters.fasta
## Illumina adapters
export first_adapter="AGATCGGAAGAGCACACGTCTGAACTCCAGTCA"
export second_adapter="AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT"
## Inititalize arrays
export fastq_array_R1=()
export fastq_array_R2=()
export raw_fastqs_array=()
export R1_names_array=()
export R2_names_array=()
export trimmed_fastqs_array=()
# Programs associative array
declare -A programs_array
programs_array=(
[fastqc]="${fastqc}" \
[multiqc]="${multiqc}" \
[flexbar]="${flexbar}"
)
Download raw RNAseq reads
Reads are downloaded from:
The --cut-dirs 3
command cuts the preceding directory structure (i.e. nightingales/P_meandrina/30-852430235/
) so that we just end up with
the reads.
# Load bash variables into memory
source .bashvars
wget \
--directory-prefix ${raw_reads_dir} \
--recursive \
--no-check-certificate \
--continue \
--cut-dirs 3 \
--no-host-directories \
--no-parent \
--quiet \
--accept ${fastq_pattern} ${raw_reads_url}
ls -lh "${raw_reads_dir}"
Verify raw read checksums
# Load bash variables into memory
source .bashvars
cd "${raw_reads_dir}"
md5sum checksums.md5 --check
FastQC/MultiQC on raw reads
# Load bash variables into memory
source .bashvars
############ RUN FASTQC ############
# Create array of raw FastQs
raw_fastqs_array=(${raw_reads_dir}/${fastq_pattern})
# Pass array contents to new variable as space-delimited list
raw_fastqc_list=$(echo "${raw_fastqs_array[*]}")
echo "Beginning FastQC on raw reads..."
echo ""
# Run FastQC
### NOTE: Do NOT quote raw_fastqc_list
${programs_array[fastqc]} \
--threads ${threads} \
--outdir ${raw_fastqc_dir} \
--quiet \
${raw_fastqc_list}
echo "FastQC on raw reads complete!"
echo ""
############ END FASTQC ############
############ RUN MULTIQC ############
echo "Beginning MultiQC on raw FastQC..."
echo ""
${programs_array[multiqc]} ${raw_fastqc_dir} -o ${raw_fastqc_dir}
echo ""
echo "MultiQC on raw FastQs complete."
echo ""
############ END MULTIQC ############
echo "Removing FastQC zip files."
echo ""
rm ${raw_fastqc_dir}/*.zip
echo "FastQC zip files removed."
echo ""
# View directory contents
ls -lh ${raw_fastqc_dir}
total 21M
drwxr-xr-x 2 shedurkin labmembers 4.0K Oct 25 12:54 01_temp-size-analysis
drwxr-xr-x 3 shedurkin labmembers 4.0K Oct 25 12:54 03-transcriptome-annotation_cache
drwxr-xr-x 3 shedurkin labmembers 4.0K Oct 25 12:54 03-transcriptome-annotation_files
-rw-r--r-- 1 shedurkin labmembers 17M Oct 25 12:54 03-transcriptome-annotation.html
-rw-r--r-- 1 shedurkin labmembers 8.9K Oct 25 12:54 03-transcriptome-annotation.Rmd
-rw-r--r-- 1 shedurkin labmembers 612K Nov 2 11:00 04-RNASeq-sample-size.html
-rw-r--r-- 1 shedurkin labmembers 3.0K Nov 2 10:58 04-RNASeq-sample-size.md
-rw-r--r-- 1 shedurkin labmembers 2.5K Nov 2 11:00 04-RNASeq-sample-size.Rmd
-rw-r--r-- 1 shedurkin labmembers 1.1M Mar 22 12:17 05-cod-RNAseq-trimming.html
-rw-r--r-- 1 shedurkin labmembers 15K Mar 22 12:15 05-cod-RNAseq-trimming.md
-rw-r--r-- 1 shedurkin labmembers 11K Mar 22 12:17 05-cod-RNAseq-trimming.Rmd
-rw-r--r-- 1 shedurkin labmembers 1.1M Mar 19 14:53 06-cod-RNAseq-alignment.html
-rw-r--r-- 1 shedurkin labmembers 35K Mar 19 14:43 06-cod-RNAseq-alignment.md
-rw-r--r-- 1 shedurkin labmembers 8.1K Mar 19 14:52 06-cod-RNAseq-alignment.Rmd
-rw-r--r-- 1 shedurkin labmembers 8.0K Mar 21 15:59 07-cod-RNAseq-DESeq2.Rmd
-rw-r--r-- 1 shedurkin labmembers 318 Oct 25 12:54 Rplot001.png
drwxr-xr-x 3 shedurkin labmembers 4.0K Oct 25 12:54 rsconnect
-rw-r--r-- 1 shedurkin labmembers 1.7M Oct 25 12:54 Temp-Size-Graph-Box-Line.html
-rw-r--r-- 1 shedurkin labmembers 3.7K Oct 25 12:54 Temp-Size-Graph-Box-Line.log
-rw-r--r-- 1 shedurkin labmembers 2.7K Oct 25 12:54 Temp-Size-Graph-Box-Line.Rmd
-rw-r--r-- 1 shedurkin labmembers 14K Oct 25 12:54 Temp-Size-Graph-Box-Line.tex
Samples 10, 13, 19, 37, 41, 48, 98, 129, 149, 57-S, 58-S had low quantity/quality of RNA after RNA extraction (see Azenta RNA extraction QC report)
Notes:
- Not enough starting material: 19, 41, 48, 98, 129, 149,
- RIN < 6: 10, 13, 37, 57-S, 58-S
- DV200 < 70: 19, 41, 48, 98, 129, 149, 57-S
RNA Integrity Number (RIN) is a measure of RNA quality ranging from 1 - 10, with 1 representing highly degraded RNA and 10 representing intact RNA. Most researchers aim for RIN values of > 8, but Azenta considers anything > 6 acceptable. It is also generally assumed that RIN is representative of mRNA quality. It’s worth noting there is some debate surrounding the accuracy of RIN as a measure of RNA integrity – see ScienceDirect’s summary of RIN
DV200 is another measure of RNA quality that represents the percentage of RNA fragments of >200 nucleotides in length. A recent study suggested that DV200 may be a more meaningful assessment of mRNA quality than RIN (Matsubara et al 2020) for NGS, but both are still commonly used.
# Load bash variables into memory
source .bashvars
# Change to directory with raw reads
cd "${raw_reads_dir}"
# Create arrays of FastQ R1 files and sample names
# Do NOT quote R1_fastq_pattern variable
for fastq in ${R1_fastq_pattern}
do
fastq_array_R1+=("${fastq}")
# Use parameter substitution to remove all text up to and including last "." from
# right side of string.
R1_names_array+=("${fastq%%.*}")
done
# Create array of FastQ R2 files
# Do NOT quote R2_fastq_pattern variable
for fastq in ${R2_fastq_pattern}
do
fastq_array_R2+=("${fastq}")
# Use parameter substitution to remove all text up to and including last "." from
# right side of string.
R2_names_array+=("${fastq%%.*}")
done
############ RUN FLEXBAR ############
# Uses parameter substitution (e.g. ${R1_sample_name%%_*})to rm the _R[12]
# Uses built-in adapter presets (https://github.com/seqan/flexbar/wiki/Manual#adapter-removal-presets)
# --adapter-preset TruSeq: several adapter presets for Illumina libraries are included in Flexbar
# --adapter-pair-overlap ON: Recommended by NEB sRNA kit
# --qtrim-threshold 25: Minimum quality
# --qtrim-format i1.8: Sets sequencer as Illumina
# --target: Sets file naming patterns
# --zip-output GZ: Sets type of compression. GZ = gzip
#
# Run flexbar on files
echo "Beginning flexbar trimming."
echo ""
time \
for index in "${!fastq_array_R1[@]}"
do
R1_sample_name="${R1_names_array[index]}"
R2_sample_name="${R2_names_array[index]}"
# Begin flexbar trimming
${programs_array[flexbar]} \
--reads ${fastq_array_R1[index]} \
--reads2 ${fastq_array_R2[index]} \
--adapter-preset "TruSeq" \
--adapter-pair-overlap ON \
--qtrim-format i1.8 \
--qtrim-threshold 25 \
--threads ${threads} \
--target "${trimmed_reads_dir}/${R1_sample_name%%_*}.flexbar_trim.R" \
--zip-output GZ
# Move to trimmed directory
# This is done so checksums file doesn't include excess path
cd ${trimmed_reads_dir}
# Generate md5 checksums for newly trimmed files
{
md5sum "${R1_sample_name%%_*}.flexbar_trim.R_1.fastq.gz"
md5sum "${R2_sample_name%%_*}.flexbar_trim.R_2.fastq.gz"
} >> "${trimmed_checksums}"
# Change back to to raw reads directory
cd "${raw_reads_dir}"
done
echo ""
echo "flexbar trimming complete."
echo ""
echo "Trimmed FastQs MD5 checksums:"
echo ""
cat "${trimmed_reads_dir}/${trimmed_checksums}"
############ END FLEXBAR ############
FastQC/MultiQC on trimmed reads
# Load bash variables into memory
source .bashvars
############ RUN FASTQC ############
### NOTE: Do NOT quote raw_fastqc_list
# Create array of trimmed FastQs
trimmed_fastqs_array=(${trimmed_reads_dir}/${fastq_pattern})
# Pass array contents to new variable as space-delimited list
trimmed_fastqc_list=$(echo "${trimmed_fastqs_array[*]}")
echo "Beginning FastQC on raw reads..."
echo ""
# Run FastQC
${programs_array[fastqc]} \
--threads ${threads} \
--outdir ${trimmed_fastqc_dir} \
--quiet \
${trimmed_fastqc_list}
echo "FastQC on trimmed reads complete!"
echo ""
############ END FASTQC ############
############ RUN MULTIQC ############
echo "Beginning MultiQC on raw FastQC..."
echo ""
${programs_array[multiqc]} ${trimmed_fastqc_dir} -o ${trimmed_fastqc_dir}
echo ""
echo "MultiQC on trimmed FastQs complete."
echo ""
############ END MULTIQC ############
echo "Removing FastQC zip files."
echo ""
rm ${trimmed_fastqc_dir}/*.zip
echo "FastQC zip files removed."
echo ""
# View directory contents
ls -lh ${trimmed_fastqc_dir}
total 21M
drwxr-xr-x 2 shedurkin labmembers 4.0K Oct 25 12:54 01_temp-size-analysis
drwxr-xr-x 3 shedurkin labmembers 4.0K Oct 25 12:54 03-transcriptome-annotation_cache
drwxr-xr-x 3 shedurkin labmembers 4.0K Oct 25 12:54 03-transcriptome-annotation_files
-rw-r--r-- 1 shedurkin labmembers 17M Oct 25 12:54 03-transcriptome-annotation.html
-rw-r--r-- 1 shedurkin labmembers 8.9K Oct 25 12:54 03-transcriptome-annotation.Rmd
-rw-r--r-- 1 shedurkin labmembers 612K Nov 2 11:00 04-RNASeq-sample-size.html
-rw-r--r-- 1 shedurkin labmembers 3.0K Nov 2 10:58 04-RNASeq-sample-size.md
-rw-r--r-- 1 shedurkin labmembers 2.5K Nov 2 11:00 04-RNASeq-sample-size.Rmd
-rw-r--r-- 1 shedurkin labmembers 1.1M Mar 22 12:17 05-cod-RNAseq-trimming.html
-rw-r--r-- 1 shedurkin labmembers 15K Mar 22 12:15 05-cod-RNAseq-trimming.md
-rw-r--r-- 1 shedurkin labmembers 11K Mar 22 12:17 05-cod-RNAseq-trimming.Rmd
-rw-r--r-- 1 shedurkin labmembers 1.1M Mar 19 14:53 06-cod-RNAseq-alignment.html
-rw-r--r-- 1 shedurkin labmembers 35K Mar 19 14:43 06-cod-RNAseq-alignment.md
-rw-r--r-- 1 shedurkin labmembers 8.1K Mar 19 14:52 06-cod-RNAseq-alignment.Rmd
-rw-r--r-- 1 shedurkin labmembers 8.0K Mar 21 15:59 07-cod-RNAseq-DESeq2.Rmd
-rw-r--r-- 1 shedurkin labmembers 318 Oct 25 12:54 Rplot001.png
drwxr-xr-x 3 shedurkin labmembers 4.0K Oct 25 12:54 rsconnect
-rw-r--r-- 1 shedurkin labmembers 1.7M Oct 25 12:54 Temp-Size-Graph-Box-Line.html
-rw-r--r-- 1 shedurkin labmembers 3.7K Oct 25 12:54 Temp-Size-Graph-Box-Line.log
-rw-r--r-- 1 shedurkin labmembers 2.7K Oct 25 12:54 Temp-Size-Graph-Box-Line.Rmd
-rw-r--r-- 1 shedurkin labmembers 14K Oct 25 12:54 Temp-Size-Graph-Box-Line.tex
Summary
LS0tCnRpdGxlOiAiMDUtY29kLVJOQXNlcS10cmltbWluZyIKYXV0aG9yOiAiS2F0aGxlZW4gRHVya2luIgpkYXRlOiAiMjAyNC0wMy0wNCIKYWx3YXlzX2FsbG93X2h0bWw6IHRydWUKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGh0bWxfcHJldmlldzogdHJ1ZSAKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCAgICAgICAgICMgRGlzcGxheSBjb2RlIGNodW5rcwogIGV2YWwgPSBGQUxTRSwgICAgICAgICMgRXZhbHVhdGUgY29kZSBjaHVua3MKICB3YXJuaW5nID0gRkFMU0UsICAgICAjIEhpZGUgd2FybmluZ3MKICBtZXNzYWdlID0gRkFMU0UsICAgICAjIEhpZGUgbWVzc2FnZXMKICBjb21tZW50ID0gIiIgICAgICAgICAjIFByZXZlbnRzIGFwcGVuZGluZyAnIyMnIHRvIGJlZ2lubmluZyBvZiBsaW5lcyBpbiBjb2RlIG91dHB1dAopCmBgYAoKQ29kZSBmb3IgdHJpbW1pbmcgYW5kIFFDaW5nIFJOQXNlcSBkYXRhLCB0byBiZSB1c2VkIG9uIFtQYWNpZmljIGNvZCBSTkFzZXEgZGF0YV0oaHR0cHM6Ly9zaGVkdXJraW4uZ2l0aHViLmlvL1JvYmVydHMtTGFiTm90ZWJvb2svcG9zdHMvcHJvamVjdHMvcGFjaWZpY19jb2QvMjAyM18xMl8xM19wYWNpZmljX2NvZC5odG1sKSwgcmF3IHJlYWRzIGZvdW5kIFtoZXJlXShodHRwczovL293bC5maXNoLndhc2hpbmd0b24uZWR1L25pZ2h0aW5nYWxlcy9HX21hY3JvY2VwaGFsdXMvMzAtOTQzMTMzODA2LykKCkZhc3RRQy9NdWx0aVFDIGFzc2Vzc21lbnQgb2YgcmF3IGFuZCBbZmxleGJhcl0oaHR0cHM6Ly9naXRodWIuY29tL3NlcWFuL2ZsZXhiYXIpLXRyaW1tZWQgc2VxdWVuY2VzIG9mIAoKSW5wdXRzOgoKLSBSTkFzZXEgZ3ppcHBlZCBGYXN0UXMgKGUuZy4gYCouZmFzdHEuZ3pgKQoKT3V0cHV0czoKCi0gW2BGYXN0UUNgXShodHRwczovL3d3dy5iaW9pbmZvcm1hdGljcy5iYWJyYWhhbS5hYy51ay9wcm9qZWN0cy9mYXN0cWMvKSBIVE1MIHJlcG9ydHMgZm9yIHJhdyBhbmQgdHJpbW1lZCByZWFkcy4KCi0gW2BNdWx0aVFDYF0oaHR0cHM6Ly9tdWx0aXFjLmluZm8vKSBIVE1MIHN1bW1hcmllcyBvZiBbYEZhc3RRQ2BdKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy8pIGZvciByYXcgYW5kIHRyaW1tZWQgcmVhZHMuCgotIFRyaW1tZWQgcmVhZHM6IGAqZmxleGJhcl90cmltLmZhc3RxLmd6YAoKKGluZm8gYWJvdXQgbGlicmFyeSBwcmVwL3NlcXVlbmNpbmcpCgoKLS0tCgoKCiMgQ3JlYXRlIGEgQmFzaCB2YXJpYWJsZXMgZmlsZQoKVGhpcyBhbGxvd3MgdXNhZ2Ugb2YgQmFzaCB2YXJpYWJsZXMgKGUuZy4gcGF0aHMgdG8gY29tbW9uIGRpcmVjdG9yaWVzKSBhY3Jvc3MgUiBNYXJrZG93biBjaHVua3MuCmBgYHtyIHNhdmUtYmFzaC12YXJpYWJsZXMtdG8tcnZhcnMtZmlsZSwgZW5naW5lPSdiYXNoJywgZXZhbD1UUlVFfQp7CmVjaG8gIiMjIyMgQXNzaWduIFZhcmlhYmxlcyAjIyMjIgplY2hvICIiCgplY2hvICIjIERhdGEgZGlyZWN0b3JpZXMiCmVjaG8gJ2V4cG9ydCBjb2RfZGlyPS9ob21lL3NoYXJlZC84VEJfSEREXzAyL3NoZWR1cmtpbi9wcm9qZWN0LWNvZC10ZW1wZXJhdHVyZScKZWNobyAnZXhwb3J0IG91dHB1dF9kaXJfdG9wPSR7Y29kX2Rpcn0vb3V0cHV0LzA1LWNvZC1STkFzZXEtdHJpbW1pbmcnCmVjaG8gJ2V4cG9ydCByYXdfZmFzdHFjX2Rpcj0ke291dHB1dF9kaXJfdG9wfS9yYXctZmFzdHFjJwplY2hvICdleHBvcnQgcmF3X3JlYWRzX2Rpcj0ke2NvZF9kaXJ9L2RhdGEvMDUtY29kLVJOQXNlcS10cmltbWluZy9yYXctcmVhZHMnCmVjaG8gJ2V4cG9ydCByYXdfcmVhZHNfdXJsPSJodHRwczovL293bC5maXNoLndhc2hpbmd0b24uZWR1L25pZ2h0aW5nYWxlcy9HX21hY3JvY2VwaGFsdXMvMzAtOTQzMTMzODA2LyInCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3RxY19kaXI9JHtvdXRwdXRfZGlyX3RvcH0vdHJpbW1lZC1mYXN0cWMnCmVjaG8gJ2V4cG9ydCB0cmltbWVkX3JlYWRzX2Rpcj0ke291dHB1dF9kaXJfdG9wfS90cmltbWVkLXJlYWRzJwplY2hvICIiCgplY2hvICIjIFBhdGhzIHRvIHByb2dyYW1zIgplY2hvICdleHBvcnQgZmFzdHFjPS9ob21lL3NoYXJlZC9GYXN0UUMtMC4xMi4xL2Zhc3RxYycKZWNobyAnZXhwb3J0IG11bHRpcWM9L2hvbWUvc2FtL3Byb2dyYW1zL21hbWJhZm9yZ2UvYmluL211bHRpcWMnCmVjaG8gJ2V4cG9ydCBmbGV4YmFyPS9ob21lL3NoYXJlZC9mbGV4YmFyLTMuNS4wLWxpbnV4L2ZsZXhiYXInCmVjaG8gIiIKCmVjaG8gIiMgU2V0IEZhc3RRIGZpbGVuYW1lIHBhdHRlcm5zIgplY2hvICJleHBvcnQgZmFzdHFfcGF0dGVybj0nKi5mYXN0cS5neiciCmVjaG8gImV4cG9ydCBSMV9mYXN0cV9wYXR0ZXJuPScqX1IxXyouZmFzdHEuZ3onIgplY2hvICJleHBvcnQgUjJfZmFzdHFfcGF0dGVybj0nKl9SMl8qLmZhc3RxLmd6JyIKZWNobyAiIgoKZWNobyAiIyBTZXQgbnVtYmVyIG9mIENQVXMgdG8gdXNlIgplY2hvICdleHBvcnQgdGhyZWFkcz0yMCcKZWNobyAiIgoKZWNobyAiIyBJbnB1dC9vdXRwdXQgZmlsZXMiCmVjaG8gJ2V4cG9ydCBmYXN0cV9jaGVja3N1bXM9aW5wdXRfZmFzdHFfY2hlY2tzdW1zLm1kNScKZWNobyAnZXhwb3J0IHRyaW1tZWRfY2hlY2tzdW1zPXRyaW1tZWRfZmFzdHFfY2hlY2tzdW1zLm1kNScKZWNobyAnZXhwb3J0IE5FQl9hZGFwdGVyc19mYXN0YT1ORUItYWRhcHRlcnMuZmFzdGEnCmVjaG8gIiIKCmVjaG8gIiMjIElsbHVtaW5hIGFkYXB0ZXJzIgplY2hvICdleHBvcnQgZmlyc3RfYWRhcHRlcj0iQUdBVENHR0FBR0FHQ0FDQUNHVENUR0FBQ1RDQ0FHVENBIicKZWNobyAnZXhwb3J0IHNlY29uZF9hZGFwdGVyPSJBR0FUQ0dHQUFHQUdDR1RDR1RHVEFHR0dBQUFHQUdUR1QiJwplY2hvICIiCgplY2hvICIjIyBJbml0aXRhbGl6ZSBhcnJheXMiCmVjaG8gJ2V4cG9ydCBmYXN0cV9hcnJheV9SMT0oKScKZWNobyAnZXhwb3J0IGZhc3RxX2FycmF5X1IyPSgpJwplY2hvICdleHBvcnQgcmF3X2Zhc3Rxc19hcnJheT0oKScKZWNobyAnZXhwb3J0IFIxX25hbWVzX2FycmF5PSgpJwplY2hvICdleHBvcnQgUjJfbmFtZXNfYXJyYXk9KCknCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3Rxc19hcnJheT0oKScKZWNobyAiIgoKZWNobyAiIyBQcm9ncmFtcyBhc3NvY2lhdGl2ZSBhcnJheSIKZWNobyAiZGVjbGFyZSAtQSBwcm9ncmFtc19hcnJheSIKZWNobyAicHJvZ3JhbXNfYXJyYXk9KCIKZWNobyAnW2Zhc3RxY109IiR7ZmFzdHFjfSIgXCcKZWNobyAnW211bHRpcWNdPSIke211bHRpcWN9IiBcJwplY2hvICdbZmxleGJhcl09IiR7ZmxleGJhcn0iJwplY2hvICIpIgp9ID4gLmJhc2h2YXJzCgpjYXQgLmJhc2h2YXJzCmBgYAoKCiMgRG93bmxvYWQgcmF3IFJOQXNlcSByZWFkcwoKUmVhZHMgYXJlIGRvd25sb2FkZWQgZnJvbToKClRoZSBgLS1jdXQtZGlycyAzYCBjb21tYW5kIGN1dHMgdGhlIHByZWNlZGluZyBkaXJlY3Rvcnkgc3RydWN0dXJlIChpLmUuIGBuaWdodGluZ2FsZXMvUF9tZWFuZHJpbmEvMzAtODUyNDMwMjM1L2ApIHNvIHRoYXQgd2UganVzdCBlbmQgdXAgd2l0aCAKdGhlIHJlYWRzLgoKYGBge3IgZG93bmxvYWQtcmF3LXJlYWRzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKd2dldCBcCi0tZGlyZWN0b3J5LXByZWZpeCAke3Jhd19yZWFkc19kaXJ9IFwKLS1yZWN1cnNpdmUgXAotLW5vLWNoZWNrLWNlcnRpZmljYXRlIFwKLS1jb250aW51ZSBcCi0tY3V0LWRpcnMgMyBcCi0tbm8taG9zdC1kaXJlY3RvcmllcyBcCi0tbm8tcGFyZW50IFwKLS1xdWlldCBcCi0tYWNjZXB0ICR7ZmFzdHFfcGF0dGVybn0gJHtyYXdfcmVhZHNfdXJsfQoKbHMgLWxoICIke3Jhd19yZWFkc19kaXJ9IgpgYGAKCiMjIFZlcmlmeSByYXcgcmVhZCBjaGVja3N1bXMKYGBge3IgdmVyaWZ5LXJhdy1yZWFkLWNoZWNrc3VtcywgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmNkICIke3Jhd19yZWFkc19kaXJ9IgoKbWQ1c3VtIGNoZWNrc3Vtcy5tZDUgLS1jaGVjawpgYGAKCgojIEZhc3RRQy9NdWx0aVFDIG9uIHJhdyByZWFkcwpgYGB7ciByYXctZmFzdHFjLW11bHRpcWMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIyMjIyMjIyMjIyMgUlVOIEZBU1RRQyAjIyMjIyMjIyMjIyMKCgojIENyZWF0ZSBhcnJheSBvZiByYXcgRmFzdFFzCnJhd19mYXN0cXNfYXJyYXk9KCR7cmF3X3JlYWRzX2Rpcn0vJHtmYXN0cV9wYXR0ZXJufSkKCiMgUGFzcyBhcnJheSBjb250ZW50cyB0byBuZXcgdmFyaWFibGUgYXMgc3BhY2UtZGVsaW1pdGVkIGxpc3QKcmF3X2Zhc3RxY19saXN0PSQoZWNobyAiJHtyYXdfZmFzdHFzX2FycmF5WypdfSIpCgplY2hvICJCZWdpbm5pbmcgRmFzdFFDIG9uIHJhdyByZWFkcy4uLiIKZWNobyAiIgoKIyBSdW4gRmFzdFFDCiMjIyBOT1RFOiBEbyBOT1QgcXVvdGUgcmF3X2Zhc3RxY19saXN0CiR7cHJvZ3JhbXNfYXJyYXlbZmFzdHFjXX0gXAotLXRocmVhZHMgJHt0aHJlYWRzfSBcCi0tb3V0ZGlyICR7cmF3X2Zhc3RxY19kaXJ9IFwKLS1xdWlldCBcCiR7cmF3X2Zhc3RxY19saXN0fQoKZWNobyAiRmFzdFFDIG9uIHJhdyByZWFkcyBjb21wbGV0ZSEiCmVjaG8gIiIKCiMjIyMjIyMjIyMjIyBFTkQgRkFTVFFDICMjIyMjIyMjIyMjIwoKIyMjIyMjIyMjIyMjIFJVTiBNVUxUSVFDICMjIyMjIyMjIyMjIwplY2hvICJCZWdpbm5pbmcgTXVsdGlRQyBvbiByYXcgRmFzdFFDLi4uIgplY2hvICIiCgoke3Byb2dyYW1zX2FycmF5W211bHRpcWNdfSAke3Jhd19mYXN0cWNfZGlyfSAtbyAke3Jhd19mYXN0cWNfZGlyfQoKZWNobyAiIgplY2hvICJNdWx0aVFDIG9uIHJhdyBGYXN0UXMgY29tcGxldGUuIgplY2hvICIiCgojIyMjIyMjIyMjIyMgRU5EIE1VTFRJUUMgIyMjIyMjIyMjIyMjCgplY2hvICJSZW1vdmluZyBGYXN0UUMgemlwIGZpbGVzLiIKZWNobyAiIgpybSAke3Jhd19mYXN0cWNfZGlyfS8qLnppcAplY2hvICJGYXN0UUMgemlwIGZpbGVzIHJlbW92ZWQuIgplY2hvICIiCmBgYAoKYGBge3Igdmlldy1yYXctcmVhZHMtUUMtZmlsZXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBWaWV3IGRpcmVjdG9yeSBjb250ZW50cwpscyAtbGggJHtyYXdfZmFzdHFjX2Rpcn0KYGBgCgpTYW1wbGVzIDEwLCAxMywgMTksIDM3LCA0MSwgNDgsIDk4LCAxMjksIDE0OSwgNTctUywgNTgtUyBoYWQgbG93IHF1YW50aXR5L3F1YWxpdHkgb2YgUk5BIGFmdGVyIFJOQSBleHRyYWN0aW9uIChzZWUgW0F6ZW50YSBSTkEgZXh0cmFjdGlvbiBRQyByZXBvcnRdKGh0dHBzOi8vZ2l0aHViLmNvbS9Sb2JlcnRzTGFiL3Byb2plY3QtY29kLXRlbXBlcmF0dXJlL2Jsb2IvbWFpbi9kYXRhL1NhbXBsZS5RQy5yZXBvcnQub2ZfMzAtOTQzMTMzODA2XzI0MDExODAyNTEwNi5wZGYpKQoKKipOb3RlczoqKgotIE5vdCBlbm91Z2ggc3RhcnRpbmcgbWF0ZXJpYWw6IDE5LCA0MSwgNDgsIDk4LCAxMjksIDE0OSwgCi0gUklOIDwgNjogMTAsIDEzLCAzNywgNTctUywgNTgtUwotIERWMjAwIDwgNzA6IDE5LCA0MSwgNDgsIDk4LCAxMjksIDE0OSwgNTctUwoKUk5BIEludGVncml0eSBOdW1iZXIgKFJJTikgaXMgYSBtZWFzdXJlIG9mIFJOQSBxdWFsaXR5IHJhbmdpbmcgZnJvbSAxIC0gMTAsIHdpdGggMSByZXByZXNlbnRpbmcgaGlnaGx5IGRlZ3JhZGVkIFJOQSBhbmQgMTAgcmVwcmVzZW50aW5nIGludGFjdCBSTkEuIE1vc3QgcmVzZWFyY2hlcnMgYWltIGZvciBSSU4gdmFsdWVzIG9mID4gOCwgYnV0IEF6ZW50YSBjb25zaWRlcnMgYW55dGhpbmcgPiA2IGFjY2VwdGFibGUuIEl0IGlzIGFsc28gZ2VuZXJhbGx5IGFzc3VtZWQgdGhhdCBSSU4gaXMgcmVwcmVzZW50YXRpdmUgb2YgbVJOQSBxdWFsaXR5LiBJdCdzIHdvcnRoIG5vdGluZyB0aGVyZSBpcyBzb21lIGRlYmF0ZSBzdXJyb3VuZGluZyB0aGUgYWNjdXJhY3kgb2YgUklOIGFzIGEgbWVhc3VyZSBvZiBSTkEgaW50ZWdyaXR5IC0tIHNlZSBbU2NpZW5jZURpcmVjdCdzIHN1bW1hcnkgb2YgUklOXShodHRwczovL3d3dy5zY2llbmNlZGlyZWN0LmNvbS90b3BpY3MvYmlvY2hlbWlzdHJ5LWdlbmV0aWNzLWFuZC1tb2xlY3VsYXItYmlvbG9neS9ybmEtaW50ZWdyaXR5LW51bWJlcikKCkRWMjAwIGlzIGFub3RoZXIgbWVhc3VyZSBvZiBSTkEgcXVhbGl0eSB0aGF0IHJlcHJlc2VudHMgdGhlIHBlcmNlbnRhZ2Ugb2YgUk5BIGZyYWdtZW50cyBvZiA+MjAwIG51Y2xlb3RpZGVzIGluIGxlbmd0aC4gQSByZWNlbnQgc3R1ZHkgc3VnZ2VzdGVkIHRoYXQgRFYyMDAgbWF5IGJlIGEgbW9yZSBtZWFuaW5nZnVsIGFzc2Vzc21lbnQgb2YgbVJOQSBxdWFsaXR5IHRoYW4gUklOIChbTWF0c3ViYXJhIGV0IGFsIDIwMjBdKGh0dHBzOi8vZG9pLm9yZy8xMC4xMTU1LzIwMjAvOTM0OTEzMikpIGZvciBOR1MsIGJ1dCBib3RoIGFyZSBzdGlsbCBjb21tb25seSB1c2VkLgoKCiMgVHJpbW1pbmcgd2l0aCBbZmxleGJhcl0oaHR0cHM6Ly9naXRodWIuY29tL3NlcWFuL2ZsZXhiYXIpCgpgYGB7ciBmbGV4YmFyLXRyaW1taW5nLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIExvYWQgYmFzaCB2YXJpYWJsZXMgaW50byBtZW1vcnkKc291cmNlIC5iYXNodmFycwoKIyBDaGFuZ2UgdG8gZGlyZWN0b3J5IHdpdGggcmF3IHJlYWRzCmNkICIke3Jhd19yZWFkc19kaXJ9IgoKIyBDcmVhdGUgYXJyYXlzIG9mIEZhc3RRIFIxIGZpbGVzIGFuZCBzYW1wbGUgbmFtZXMKIyBEbyBOT1QgcXVvdGUgUjFfZmFzdHFfcGF0dGVybiB2YXJpYWJsZQpmb3IgZmFzdHEgaW4gJHtSMV9mYXN0cV9wYXR0ZXJufQpkbwogIGZhc3RxX2FycmF5X1IxKz0oIiR7ZmFzdHF9IikKCiAgIyBVc2UgcGFyYW1ldGVyIHN1YnN0aXR1dGlvbiB0byByZW1vdmUgYWxsIHRleHQgdXAgdG8gYW5kIGluY2x1ZGluZyBsYXN0ICIuIiBmcm9tCiAgIyByaWdodCBzaWRlIG9mIHN0cmluZy4KICBSMV9uYW1lc19hcnJheSs9KCIke2Zhc3RxJSUuKn0iKQpkb25lCgojIENyZWF0ZSBhcnJheSBvZiBGYXN0USBSMiBmaWxlcwojIERvIE5PVCBxdW90ZSBSMl9mYXN0cV9wYXR0ZXJuIHZhcmlhYmxlCmZvciBmYXN0cSBpbiAke1IyX2Zhc3RxX3BhdHRlcm59CmRvCiAgZmFzdHFfYXJyYXlfUjIrPSgiJHtmYXN0cX0iKQoKICAjIFVzZSBwYXJhbWV0ZXIgc3Vic3RpdHV0aW9uIHRvIHJlbW92ZSBhbGwgdGV4dCB1cCB0byBhbmQgaW5jbHVkaW5nIGxhc3QgIi4iIGZyb20KICAjIHJpZ2h0IHNpZGUgb2Ygc3RyaW5nLgogIFIyX25hbWVzX2FycmF5Kz0oIiR7ZmFzdHElJS4qfSIpCmRvbmUKCgojIyMjIyMjIyMjIyMgUlVOIEZMRVhCQVIgIyMjIyMjIyMjIyMjCiMgVXNlcyBwYXJhbWV0ZXIgc3Vic3RpdHV0aW9uIChlLmcuICR7UjFfc2FtcGxlX25hbWUlJV8qfSl0byBybSB0aGUgX1JbMTJdCiMgVXNlcyBidWlsdC1pbiBhZGFwdGVyIHByZXNldHMgKGh0dHBzOi8vZ2l0aHViLmNvbS9zZXFhbi9mbGV4YmFyL3dpa2kvTWFudWFsI2FkYXB0ZXItcmVtb3ZhbC1wcmVzZXRzKQojIC0tYWRhcHRlci1wcmVzZXQgVHJ1U2VxOiBzZXZlcmFsIGFkYXB0ZXIgcHJlc2V0cyBmb3IgSWxsdW1pbmEgbGlicmFyaWVzIGFyZSBpbmNsdWRlZCBpbiBGbGV4YmFyCiMgLS1hZGFwdGVyLXBhaXItb3ZlcmxhcCBPTjogUmVjb21tZW5kZWQgYnkgTkVCIHNSTkEga2l0CiMgLS1xdHJpbS10aHJlc2hvbGQgMjU6IE1pbmltdW0gcXVhbGl0eQojIC0tcXRyaW0tZm9ybWF0IGkxLjg6IFNldHMgc2VxdWVuY2VyIGFzIElsbHVtaW5hCiMgLS10YXJnZXQ6IFNldHMgZmlsZSBuYW1pbmcgcGF0dGVybnMKIyAtLXppcC1vdXRwdXQgR1o6IFNldHMgdHlwZSBvZiBjb21wcmVzc2lvbi4gR1ogPSBnemlwCiMKCiMgUnVuIGZsZXhiYXIgb24gZmlsZXMKZWNobyAiQmVnaW5uaW5nIGZsZXhiYXIgdHJpbW1pbmcuIgplY2hvICIiCgp0aW1lIFwKZm9yIGluZGV4IGluICIkeyFmYXN0cV9hcnJheV9SMVtAXX0iCmRvCiAgUjFfc2FtcGxlX25hbWU9IiR7UjFfbmFtZXNfYXJyYXlbaW5kZXhdfSIKICBSMl9zYW1wbGVfbmFtZT0iJHtSMl9uYW1lc19hcnJheVtpbmRleF19IgoKICAjIEJlZ2luIGZsZXhiYXIgdHJpbW1pbmcKICAke3Byb2dyYW1zX2FycmF5W2ZsZXhiYXJdfSBcCiAgLS1yZWFkcyAke2Zhc3RxX2FycmF5X1IxW2luZGV4XX0gXAogIC0tcmVhZHMyICR7ZmFzdHFfYXJyYXlfUjJbaW5kZXhdfSAgXAogIC0tYWRhcHRlci1wcmVzZXQgIlRydVNlcSIgXAogIC0tYWRhcHRlci1wYWlyLW92ZXJsYXAgT04gXAogIC0tcXRyaW0tZm9ybWF0IGkxLjggXAogIC0tcXRyaW0tdGhyZXNob2xkIDI1IFwKICAtLXRocmVhZHMgJHt0aHJlYWRzfSBcCiAgLS10YXJnZXQgIiR7dHJpbW1lZF9yZWFkc19kaXJ9LyR7UjFfc2FtcGxlX25hbWUlJV8qfS5mbGV4YmFyX3RyaW0uUiIgXAogIC0temlwLW91dHB1dCBHWgogICAgICAgIAogICAgIyBNb3ZlIHRvIHRyaW1tZWQgZGlyZWN0b3J5CiAgICAjIFRoaXMgaXMgZG9uZSBzbyBjaGVja3N1bXMgZmlsZSBkb2Vzbid0IGluY2x1ZGUgZXhjZXNzIHBhdGgKICAgIGNkICR7dHJpbW1lZF9yZWFkc19kaXJ9CgogICAgIyBHZW5lcmF0ZSBtZDUgY2hlY2tzdW1zIGZvciBuZXdseSB0cmltbWVkIGZpbGVzCiAgICB7CiAgICAgIG1kNXN1bSAiJHtSMV9zYW1wbGVfbmFtZSUlXyp9LmZsZXhiYXJfdHJpbS5SXzEuZmFzdHEuZ3oiCiAgICAgIG1kNXN1bSAiJHtSMl9zYW1wbGVfbmFtZSUlXyp9LmZsZXhiYXJfdHJpbS5SXzIuZmFzdHEuZ3oiCiAgICB9ID4+ICIke3RyaW1tZWRfY2hlY2tzdW1zfSIKICAgIAogICAgIyBDaGFuZ2UgYmFjayB0byB0byByYXcgcmVhZHMgZGlyZWN0b3J5CiAgICBjZCAiJHtyYXdfcmVhZHNfZGlyfSIKCmRvbmUKCmVjaG8gIiIKZWNobyAiZmxleGJhciB0cmltbWluZyBjb21wbGV0ZS4iCmVjaG8gIiIKCmVjaG8gIlRyaW1tZWQgRmFzdFFzIE1ENSBjaGVja3N1bXM6IgplY2hvICIiCgpjYXQgIiR7dHJpbW1lZF9yZWFkc19kaXJ9LyR7dHJpbW1lZF9jaGVja3N1bXN9IgoKIyMjIyMjIyMjIyMjIEVORCBGTEVYQkFSICMjIyMjIyMjIyMjIwpgYGAKCgojIEZhc3RRQy9NdWx0aVFDIG9uIHRyaW1tZWQgcmVhZHMKCmBgYHtyIEZhc3RRQy1NdWx0aVFDLXRyaW1tZWQtcmVhZHMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgojIyMjIyMjIyMjIyMgUlVOIEZBU1RRQyAjIyMjIyMjIyMjIyMKCiMjIyBOT1RFOiBEbyBOT1QgcXVvdGUgcmF3X2Zhc3RxY19saXN0CiMgQ3JlYXRlIGFycmF5IG9mIHRyaW1tZWQgRmFzdFFzCnRyaW1tZWRfZmFzdHFzX2FycmF5PSgke3RyaW1tZWRfcmVhZHNfZGlyfS8ke2Zhc3RxX3BhdHRlcm59KQoKIyBQYXNzIGFycmF5IGNvbnRlbnRzIHRvIG5ldyB2YXJpYWJsZSBhcyBzcGFjZS1kZWxpbWl0ZWQgbGlzdAp0cmltbWVkX2Zhc3RxY19saXN0PSQoZWNobyAiJHt0cmltbWVkX2Zhc3Rxc19hcnJheVsqXX0iKQoKZWNobyAiQmVnaW5uaW5nIEZhc3RRQyBvbiByYXcgcmVhZHMuLi4iCmVjaG8gIiIKCiMgUnVuIEZhc3RRQwoke3Byb2dyYW1zX2FycmF5W2Zhc3RxY119IFwKLS10aHJlYWRzICR7dGhyZWFkc30gXAotLW91dGRpciAke3RyaW1tZWRfZmFzdHFjX2Rpcn0gXAotLXF1aWV0IFwKJHt0cmltbWVkX2Zhc3RxY19saXN0fQoKZWNobyAiRmFzdFFDIG9uIHRyaW1tZWQgcmVhZHMgY29tcGxldGUhIgplY2hvICIiCgojIyMjIyMjIyMjIyMgRU5EIEZBU1RRQyAjIyMjIyMjIyMjIyMKCiMjIyMjIyMjIyMjIyBSVU4gTVVMVElRQyAjIyMjIyMjIyMjIyMKZWNobyAiQmVnaW5uaW5nIE11bHRpUUMgb24gcmF3IEZhc3RRQy4uLiIKZWNobyAiIgoKJHtwcm9ncmFtc19hcnJheVttdWx0aXFjXX0gJHt0cmltbWVkX2Zhc3RxY19kaXJ9IC1vICR7dHJpbW1lZF9mYXN0cWNfZGlyfQoKZWNobyAiIgplY2hvICJNdWx0aVFDIG9uIHRyaW1tZWQgRmFzdFFzIGNvbXBsZXRlLiIKZWNobyAiIgoKIyMjIyMjIyMjIyMjIEVORCBNVUxUSVFDICMjIyMjIyMjIyMjIwoKZWNobyAiUmVtb3ZpbmcgRmFzdFFDIHppcCBmaWxlcy4iCmVjaG8gIiIKcm0gJHt0cmltbWVkX2Zhc3RxY19kaXJ9LyouemlwCmVjaG8gIkZhc3RRQyB6aXAgZmlsZXMgcmVtb3ZlZC4iCmVjaG8gIiIKYGBgCgpgYGB7ciB2aWV3LXRyaW1tZWQtcmVhZHMtUUMtZmlsZXMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KIyBWaWV3IGRpcmVjdG9yeSBjb250ZW50cwpscyAtbGggJHt0cmltbWVkX2Zhc3RxY19kaXJ9CmBgYAoKIyBTdW1tYXJ5