This Rmd file trims WGBS-seq files using fastp (Chen 2023), followed by quality checks with FastQC and MultiQC(Ewels et al. 2016).
Expects input files formatted like so: <number>M_[12].fastq.gz
All trimmed FastQs produced by this script are here:
00.10-trimming-fastp-FastQC-MultiQC/trimmed-fastqs/
Create a Bash variables file
This allows usage of Bash variables across R Markdown chunks.
{
echo "#### Assign Variables ####"
echo ""
echo "# Data directories"
echo 'export repo_dir="/gscratch/scrubbed/samwhite/gitrepos/project-mytilus-methylation"'
echo 'export output_dir_top="${repo_dir}/output/00.10-trimming-fastp-FastQC-MultiQC"'
echo 'export raw_reads_dir="${repo_dir}/data/raw-wgbs"'
echo 'export raw_reads_url="https://owl.fish.washington.edu/nightingales/M_trossulus/"'
echo 'export trimmed_fastqs_dir=${output_dir_top}/trimmed-fastqs'
echo 'export trimmed_fastqc_dir=${output_dir_top}/trimmed-fastqc'
echo ""
echo "# Set FastQ filename patterns"
echo "export fastq_pattern='*.fastq.gz'"
echo "export R1_fastq_pattern='*_1.fastq.gz'"
echo "export R2_fastq_pattern='*_2.fastq.gz'"
echo "export trimmed_fastq_pattern='*fastp-trim.fq.gz'"
echo ""
echo "# Set number of CPUs to use"
echo 'export threads=50'
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 ""
echo "# Print formatting"
echo 'export line="--------------------------------------------------------"'
echo ""
} > .bashvars
cat .bashvars
#### Assign Variables ####
# Data directories
export repo_dir="/gscratch/scrubbed/samwhite/gitrepos/project-mytilus-methylation"
export output_dir_top="${repo_dir}/output/00.10-trimming-fastp-FastQC-MultiQC"
export raw_reads_dir="${repo_dir}/data/raw-wgbs"
export raw_reads_url="https://owl.fish.washington.edu/nightingales/M_trossulus/"
export trimmed_fastqs_dir=${output_dir_top}/trimmed-fastqs
export trimmed_fastqc_dir=${output_dir_top}/trimmed-fastqc
# Set FastQ filename patterns
export fastq_pattern='*.fastq.gz'
export R1_fastq_pattern='*_1.fastq.gz'
export R2_fastq_pattern='*_2.fastq.gz'
export trimmed_fastq_pattern='*fastp-trim.fq.gz'
# Set number of CPUs to use
export threads=50
## Inititalize arrays
export fastq_array_R1=()
export fastq_array_R2=()
export raw_fastqs_array=()
export R1_names_array=()
export R2_names_array=()
# Print formatting
export line="--------------------------------------------------------"
If needed, download raw FastQs.
Change eval=FALSE
to eval=TRUE
to execute the next two chunks to download RNA-seq and then verify MD5 checksums.
Reads are downloaded from https://owl.fish.washington.edu/nightingales/M_trossulus/
# Load bash variables into memory
source .bashvars
# Make output directory if it doesn't exist
mkdir --parents ${raw_reads_dir}
# Run wget to retrieve FastQs and MD5 files
wget \
--directory-prefix ${raw_reads_dir} \
--recursive \
--no-check-certificate \
--continue \
--cut-dirs 3 \
--no-host-directories \
--no-parent \
--quiet \
--level=1 \
--accept "[0-9]M*.fastq.gz,[0-9]M*.fastq.gz.md5sum" \
${raw_reads_url}
ls -lh "${raw_reads_dir}"
Verify raw read checksums
# Load bash variables into memory
source .bashvars
cd "${raw_reads_dir}"
# Checksums file contains other files, so this just looks for the sRNAseq files.
for file in *.md5sum
do
md5sum --check "${file}"
done
Fastp Trimming
fastp (Chen 2023) is set to auto-detect Illumina adapters, as well as trim the first 20bp from each read, as past experience shows these first 20bp are more inconsistent than the remainder of the read length.
# Load bash variables into memory
source .bashvars
# Make output directories, if it doesn't exist
mkdir --parents "${trimmed_fastqs_dir}"
# Change to raw reads directory
cd "${raw_reads_dir}"
# Create arrays of fastq R1 files and sample names
for fastq in ${R1_fastq_pattern}
do
fastq_array_R1+=("${fastq}")
R1_names_array+=("$(echo "${fastq}" | awk -F"_" '{print $1}')")
done
# Create array of fastq R2 files
for fastq in ${R2_fastq_pattern}
do
fastq_array_R2+=("${fastq}")
R2_names_array+=("$(echo "${fastq}" | awk -F"_" '{print $1}')")
done
# Create list of fastq files used in analysis
# Create MD5 checksum for reference
if [ ! -f "${output_dir_top}"/raw-fastq-checksums.md5 ]; then
for fastq in *.gz
do
md5sum "${fastq}" >>"${output_dir_top}"/raw-fastq-checksums.md5
done
fi
# Run fastp on files
# Adds JSON report output for downstream usage by MultiQC
for index in "${!fastq_array_R1[@]}"
do
R1_sample_name=$(echo "${R1_names_array[index]}")
R2_sample_name=$(echo "${R2_names_array[index]}")
echo "${R1_sample_name}"
echo ""
fastp \
--in1 ${fastq_array_R1[index]} \
--in2 ${fastq_array_R2[index]} \
--detect_adapter_for_pe \
--trim_front1 20 \
--trim_front2 20 \
--thread ${threads} \
--html "${trimmed_fastqs_dir}"/"${R1_sample_name}".fastp-trim.report.html \
--json "${trimmed_fastqs_dir}"/"${R1_sample_name}".fastp-trim.report.json \
--out1 "${trimmed_fastqs_dir}"/"${R1_sample_name}"_R1.fastp-trim.fq.gz \
--out2 "${trimmed_fastqs_dir}"/"${R2_sample_name}"_R2.fastp-trim.fq.gz \
2>> "${trimmed_fastqs_dir}"/fastp.stderr
# Generate md5 checksums for newly trimmed files
cd "${trimmed_fastqs_dir}"
md5sum "${R1_sample_name}"_R1.fastp-trim.fq.gz > "${R1_sample_name}"_R1.fastp-trim.fq.gz.md5
md5sum "${R2_sample_name}"_R2.fastp-trim.fq.gz > "${R2_sample_name}"_R2.fastp-trim.fq.gz.md5
cd -
done
Quality Check with FastQC and MultiQC
# Load bash variables into memory
source .bashvars
############ RUN FASTQC ############
# Create array of trimmed FastQs
trimmed_fastqs_array=(${trimmed_fastqs_dir}/${trimmed_fastq_pattern})
# Pass array contents to new variable as space-delimited list
trimmed_fastqc_list=$(echo "${trimmed_fastqs_array[*]}")
echo "Beginning FastQC on trimmed reads..."
echo ""
# Run FastQC
### NOTE: Do NOT quote raw_fastqc_list
fastqc \
--threads ${threads} \
--outdir ${trimmed_fastqs_dir} \
--quiet \
${trimmed_fastqc_list}
echo "FastQC on trimmed reads complete!"
echo ""
############ END FASTQC ############
############ RUN MULTIQC ############
echo "Beginning MultiQC on trimmed FastQC..."
echo ""
multiqc ${trimmed_fastqs_dir} -o ${trimmed_fastqs_dir}
echo ""
echo "MultiQC on trimmed FastQs complete."
echo ""
############ END MULTIQC ############
echo "Removing FastQC zip files."
echo ""
rm ${trimmed_fastqs_dir}/*.zip
echo "FastQC zip files removed."
echo ""
Chen, Shifu. 2023.
“Ultrafast One-Pass FASTQ Data Preprocessing, Quality Control, and Deduplication Using Fastp.” iMeta 2 (2).
https://doi.org/10.1002/imt2.107.
Ewels, Philip, Måns Magnusson, Sverker Lundin, and Max Käller. 2016.
“MultiQC: Summarize Analysis Results for Multiple Tools and Samples in a Single Report.” Bioinformatics 32 (19): 3047–48.
https://doi.org/10.1093/bioinformatics/btw354.
LS0tCnRpdGxlOiAiMDAuMTAtdHJpbW1pbmctZmFzdHAtRmFzdFFDLU11bHRpUUMiCmF1dGhvcjogIlNhbSBXaGl0ZSIKZGF0ZTogIjIwMjQtMTEtMDciCm91dHB1dDogCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOgogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICBnaXRodWJfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQpiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwgICAgICAgICAjIERpc3BsYXkgY29kZSBjaHVua3MKICBldmFsID0gRkFMU0UsICAgICAgICAjIEV2YWx1YXRlIGNvZGUgY2h1bmtzCiAgd2FybmluZyA9IEZBTFNFLCAgICAgIyBIaWRlIHdhcm5pbmdzCiAgbWVzc2FnZSA9IEZBTFNFLCAgICAgIyBIaWRlIG1lc3NhZ2VzCiAgY29tbWVudCA9ICIiICAgICAgICAgIyBQcmV2ZW50cyBhcHBlbmRpbmcgJyMjJyB0byBiZWdpbm5pbmcgb2YgbGluZXMgaW4gY29kZSBvdXRwdXQKKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKVGhpcyBSbWQgZmlsZSB0cmltcyBXR0JTLXNlcSBmaWxlcyB1c2luZyBbZmFzdHBdKGh0dHBzOi8vZ2l0aHViLmNvbS9PcGVuR2VuZS9mYXN0cCkgW0BjaGVuMjAyM10sIGZvbGxvd2VkIGJ5IHF1YWxpdHkgY2hlY2tzIHdpdGggW0Zhc3RRQ10oaHR0cHM6Ly9naXRodWIuY29tL3MtYW5kcmV3cy9GYXN0UUMpIGFuZCBbTXVsdGlRQ10oaHR0cHM6Ly9tdWx0aXFjLmluZm8vKVtAZXdlbHMyMDE2XS4KCkV4cGVjdHMgaW5wdXQgZmlsZXMgZm9ybWF0dGVkIGxpa2Ugc286IGA8bnVtYmVyPk1fWzEyXS5mYXN0cS5nemAKCkFsbCB0cmltbWVkIEZhc3RRcyBwcm9kdWNlZCBieSB0aGlzIHNjcmlwdCBhcmUgaGVyZToKClswMC4xMC10cmltbWluZy1mYXN0cC1GYXN0UUMtTXVsdGlRQy90cmltbWVkLWZhc3Rxcy9dKGh0dHBzOi8vZ2FubmV0LmZpc2gud2FzaGluZ3Rvbi5lZHUvQXR1bWVmYWNpZW5zL2dpdHJlcG9zL3Byb2plY3QtbXl0aWx1cy1tZXRoeWxhdGlvbi9vdXRwdXQvMDAuMTAtdHJpbW1pbmctZmFzdHAtRmFzdFFDLU11bHRpUUMvdHJpbW1lZC1mYXN0cXMvKQoKIyBDcmVhdGUgYSBCYXNoIHZhcmlhYmxlcyBmaWxlCgpUaGlzIGFsbG93cyB1c2FnZSBvZiBCYXNoIHZhcmlhYmxlcyBhY3Jvc3MgUiBNYXJrZG93biBjaHVua3MuCgpgYGB7ciBzYXZlLWJhc2gtdmFyaWFibGVzLXRvLXJ2YXJzLWZpbGUsIGVuZ2luZT0nYmFzaCcsIGV2YWw9VFJVRX0KewplY2hvICIjIyMjIEFzc2lnbiBWYXJpYWJsZXMgIyMjIyIKZWNobyAiIgoKZWNobyAiIyBEYXRhIGRpcmVjdG9yaWVzIgplY2hvICdleHBvcnQgcmVwb19kaXI9Ii9nc2NyYXRjaC9zY3J1YmJlZC9zYW13aGl0ZS9naXRyZXBvcy9wcm9qZWN0LW15dGlsdXMtbWV0aHlsYXRpb24iJwplY2hvICdleHBvcnQgb3V0cHV0X2Rpcl90b3A9IiR7cmVwb19kaXJ9L291dHB1dC8wMC4xMC10cmltbWluZy1mYXN0cC1GYXN0UUMtTXVsdGlRQyInCmVjaG8gJ2V4cG9ydCByYXdfcmVhZHNfZGlyPSIke3JlcG9fZGlyfS9kYXRhL3Jhdy13Z2JzIicKZWNobyAnZXhwb3J0IHJhd19yZWFkc191cmw9Imh0dHBzOi8vb3dsLmZpc2gud2FzaGluZ3Rvbi5lZHUvbmlnaHRpbmdhbGVzL01fdHJvc3N1bHVzLyInCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3Rxc19kaXI9JHtvdXRwdXRfZGlyX3RvcH0vdHJpbW1lZC1mYXN0cXMnCmVjaG8gJ2V4cG9ydCB0cmltbWVkX2Zhc3RxY19kaXI9JHtvdXRwdXRfZGlyX3RvcH0vdHJpbW1lZC1mYXN0cWMnCmVjaG8gIiIKCgplY2hvICIjIFNldCBGYXN0USBmaWxlbmFtZSBwYXR0ZXJucyIKZWNobyAiZXhwb3J0IGZhc3RxX3BhdHRlcm49JyouZmFzdHEuZ3onIgplY2hvICJleHBvcnQgUjFfZmFzdHFfcGF0dGVybj0nKl8xLmZhc3RxLmd6JyIKZWNobyAiZXhwb3J0IFIyX2Zhc3RxX3BhdHRlcm49JypfMi5mYXN0cS5neiciCmVjaG8gImV4cG9ydCB0cmltbWVkX2Zhc3RxX3BhdHRlcm49JypmYXN0cC10cmltLmZxLmd6JyIKZWNobyAiIgoKZWNobyAiIyBTZXQgbnVtYmVyIG9mIENQVXMgdG8gdXNlIgplY2hvICdleHBvcnQgdGhyZWFkcz01MCcKZWNobyAiIgoKCmVjaG8gIiMjIEluaXRpdGFsaXplIGFycmF5cyIKZWNobyAnZXhwb3J0IGZhc3RxX2FycmF5X1IxPSgpJwplY2hvICdleHBvcnQgZmFzdHFfYXJyYXlfUjI9KCknCmVjaG8gJ2V4cG9ydCByYXdfZmFzdHFzX2FycmF5PSgpJwplY2hvICdleHBvcnQgUjFfbmFtZXNfYXJyYXk9KCknCmVjaG8gJ2V4cG9ydCBSMl9uYW1lc19hcnJheT0oKScKZWNobyAiIgoKZWNobyAiIyBQcmludCBmb3JtYXR0aW5nIgplY2hvICdleHBvcnQgbGluZT0iLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0iJwplY2hvICIiCgp9ID4gLmJhc2h2YXJzCgpjYXQgLmJhc2h2YXJzCmBgYAoKSWYgbmVlZGVkLCBkb3dubG9hZCByYXcgRmFzdFFzLgoKQ2hhbmdlIGBldmFsPUZBTFNFYCB0byBgZXZhbD1UUlVFYCB0byBleGVjdXRlIHRoZSBuZXh0IHR3byBjaHVua3MgdG8gZG93bmxvYWQgUk5BLXNlcSBhbmQgdGhlbiB2ZXJpZnkgTUQ1IGNoZWNrc3Vtcy4KClJlYWRzIGFyZSBkb3dubG9hZGVkIGZyb20gPGh0dHBzOi8vb3dsLmZpc2gud2FzaGluZ3Rvbi5lZHUvbmlnaHRpbmdhbGVzL01fdHJvc3N1bHVzLz4KCmBgYHtiYXNoIGRvd25sb2FkLXJhdy1yZWFkcywgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCiMgTWFrZSBvdXRwdXQgZGlyZWN0b3J5IGlmIGl0IGRvZXNuJ3QgZXhpc3QKbWtkaXIgLS1wYXJlbnRzICR7cmF3X3JlYWRzX2Rpcn0KCiMgUnVuIHdnZXQgdG8gcmV0cmlldmUgRmFzdFFzIGFuZCBNRDUgZmlsZXMKd2dldCBcCi0tZGlyZWN0b3J5LXByZWZpeCAke3Jhd19yZWFkc19kaXJ9IFwKLS1yZWN1cnNpdmUgXAotLW5vLWNoZWNrLWNlcnRpZmljYXRlIFwKLS1jb250aW51ZSBcCi0tY3V0LWRpcnMgMyBcCi0tbm8taG9zdC1kaXJlY3RvcmllcyBcCi0tbm8tcGFyZW50IFwKLS1xdWlldCBcCi0tbGV2ZWw9MSBcCi0tYWNjZXB0ICJbMC05XU0qLmZhc3RxLmd6LFswLTldTSouZmFzdHEuZ3oubWQ1c3VtIiBcCiR7cmF3X3JlYWRzX3VybH0KCgpscyAtbGggIiR7cmF3X3JlYWRzX2Rpcn0iCmBgYAoKVmVyaWZ5IHJhdyByZWFkIGNoZWNrc3VtcwoKYGBge2Jhc2ggdmVyaWZ5LXJhdy1yZWFkLWNoZWNrc3VtcywgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCmNkICIke3Jhd19yZWFkc19kaXJ9IgoKIyBDaGVja3N1bXMgZmlsZSBjb250YWlucyBvdGhlciBmaWxlcywgc28gdGhpcyBqdXN0IGxvb2tzIGZvciB0aGUgc1JOQXNlcSBmaWxlcy4KZm9yIGZpbGUgaW4gKi5tZDVzdW0KZG8KICBtZDVzdW0gLS1jaGVjayAiJHtmaWxlfSIKZG9uZQpgYGAKCiMgRmFzdHAgVHJpbW1pbmcKCltmYXN0cF0oaHR0cHM6Ly9naXRodWIuY29tL09wZW5HZW5lL2Zhc3RwKSBbQGNoZW4yMDIzXSBpcyBzZXQgdG8gYXV0by1kZXRlY3QgSWxsdW1pbmEgYWRhcHRlcnMsIGFzIHdlbGwgYXMgdHJpbSB0aGUgZmlyc3QgMjBicCBmcm9tIGVhY2ggcmVhZCwgYXMgcGFzdCBleHBlcmllbmNlIHNob3dzIHRoZXNlIGZpcnN0IDIwYnAgYXJlIG1vcmUgaW5jb25zaXN0ZW50IHRoYW4gdGhlIHJlbWFpbmRlciBvZiB0aGUgcmVhZCBsZW5ndGguCgpgYGB7YmFzaCBmYXN0cC10cmltbWluZywgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyBMb2FkIGJhc2ggdmFyaWFibGVzIGludG8gbWVtb3J5CnNvdXJjZSAuYmFzaHZhcnMKCiMgTWFrZSBvdXRwdXQgZGlyZWN0b3JpZXMsIGlmIGl0IGRvZXNuJ3QgZXhpc3QKbWtkaXIgLS1wYXJlbnRzICIke3RyaW1tZWRfZmFzdHFzX2Rpcn0iCgojIENoYW5nZSB0byByYXcgcmVhZHMgZGlyZWN0b3J5CmNkICIke3Jhd19yZWFkc19kaXJ9IgoKIyBDcmVhdGUgYXJyYXlzIG9mIGZhc3RxIFIxIGZpbGVzIGFuZCBzYW1wbGUgbmFtZXMKZm9yIGZhc3RxIGluICR7UjFfZmFzdHFfcGF0dGVybn0KZG8KICBmYXN0cV9hcnJheV9SMSs9KCIke2Zhc3RxfSIpCiAgUjFfbmFtZXNfYXJyYXkrPSgiJChlY2hvICIke2Zhc3RxfSIgfCBhd2sgLUYiXyIgJ3twcmludCAkMX0nKSIpCmRvbmUKCiMgQ3JlYXRlIGFycmF5IG9mIGZhc3RxIFIyIGZpbGVzCmZvciBmYXN0cSBpbiAke1IyX2Zhc3RxX3BhdHRlcm59CmRvCiAgZmFzdHFfYXJyYXlfUjIrPSgiJHtmYXN0cX0iKQogIFIyX25hbWVzX2FycmF5Kz0oIiQoZWNobyAiJHtmYXN0cX0iIHwgYXdrIC1GIl8iICd7cHJpbnQgJDF9JykiKQpkb25lCgojIENyZWF0ZSBsaXN0IG9mIGZhc3RxIGZpbGVzIHVzZWQgaW4gYW5hbHlzaXMKIyBDcmVhdGUgTUQ1IGNoZWNrc3VtIGZvciByZWZlcmVuY2UKaWYgWyAhIC1mICIke291dHB1dF9kaXJfdG9wfSIvcmF3LWZhc3RxLWNoZWNrc3Vtcy5tZDUgXTsgdGhlbgogIGZvciBmYXN0cSBpbiAqLmd6CiAgICBkbwogICAgICBtZDVzdW0gIiR7ZmFzdHF9IiA+PiIke291dHB1dF9kaXJfdG9wfSIvcmF3LWZhc3RxLWNoZWNrc3Vtcy5tZDUKICBkb25lCmZpCgojIFJ1biBmYXN0cCBvbiBmaWxlcwojIEFkZHMgSlNPTiByZXBvcnQgb3V0cHV0IGZvciBkb3duc3RyZWFtIHVzYWdlIGJ5IE11bHRpUUMKZm9yIGluZGV4IGluICIkeyFmYXN0cV9hcnJheV9SMVtAXX0iCmRvCiAgUjFfc2FtcGxlX25hbWU9JChlY2hvICIke1IxX25hbWVzX2FycmF5W2luZGV4XX0iKQogIFIyX3NhbXBsZV9uYW1lPSQoZWNobyAiJHtSMl9uYW1lc19hcnJheVtpbmRleF19IikKICBlY2hvICIke1IxX3NhbXBsZV9uYW1lfSIKICBlY2hvICIiCiAgZmFzdHAgXAogIC0taW4xICR7ZmFzdHFfYXJyYXlfUjFbaW5kZXhdfSBcCiAgLS1pbjIgJHtmYXN0cV9hcnJheV9SMltpbmRleF19IFwKICAtLWRldGVjdF9hZGFwdGVyX2Zvcl9wZSBcCiAgLS10cmltX2Zyb250MSAyMCBcCiAgLS10cmltX2Zyb250MiAyMCBcCiAgLS10aHJlYWQgJHt0aHJlYWRzfSBcCiAgLS1odG1sICIke3RyaW1tZWRfZmFzdHFzX2Rpcn0iLyIke1IxX3NhbXBsZV9uYW1lfSIuZmFzdHAtdHJpbS5yZXBvcnQuaHRtbCBcCiAgLS1qc29uICIke3RyaW1tZWRfZmFzdHFzX2Rpcn0iLyIke1IxX3NhbXBsZV9uYW1lfSIuZmFzdHAtdHJpbS5yZXBvcnQuanNvbiBcCiAgLS1vdXQxICIke3RyaW1tZWRfZmFzdHFzX2Rpcn0iLyIke1IxX3NhbXBsZV9uYW1lfSJfUjEuZmFzdHAtdHJpbS5mcS5neiBcCiAgLS1vdXQyICIke3RyaW1tZWRfZmFzdHFzX2Rpcn0iLyIke1IyX3NhbXBsZV9uYW1lfSJfUjIuZmFzdHAtdHJpbS5mcS5neiBcCiAgMj4+ICIke3RyaW1tZWRfZmFzdHFzX2Rpcn0iL2Zhc3RwLnN0ZGVycgoKICAjIEdlbmVyYXRlIG1kNSBjaGVja3N1bXMgZm9yIG5ld2x5IHRyaW1tZWQgZmlsZXMKICBjZCAiJHt0cmltbWVkX2Zhc3Rxc19kaXJ9IgogIG1kNXN1bSAiJHtSMV9zYW1wbGVfbmFtZX0iX1IxLmZhc3RwLXRyaW0uZnEuZ3ogPiAiJHtSMV9zYW1wbGVfbmFtZX0iX1IxLmZhc3RwLXRyaW0uZnEuZ3oubWQ1CiAgbWQ1c3VtICIke1IyX3NhbXBsZV9uYW1lfSJfUjIuZmFzdHAtdHJpbS5mcS5neiA+ICIke1IyX3NhbXBsZV9uYW1lfSJfUjIuZmFzdHAtdHJpbS5mcS5nei5tZDUKICBjZCAtCmRvbmUKYGBgCgojIFF1YWxpdHkgQ2hlY2sgd2l0aCBGYXN0UUMgYW5kIE11bHRpUUMKCmBgYHtiYXNoIHRyaW1tZWQtZmFzdHFjLW11bHRpcWMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMgTG9hZCBiYXNoIHZhcmlhYmxlcyBpbnRvIG1lbW9yeQpzb3VyY2UgLmJhc2h2YXJzCgoKIyMjIyMjIyMjIyMjIFJVTiBGQVNUUUMgIyMjIyMjIyMjIyMjCgoKIyBDcmVhdGUgYXJyYXkgb2YgdHJpbW1lZCBGYXN0UXMKdHJpbW1lZF9mYXN0cXNfYXJyYXk9KCR7dHJpbW1lZF9mYXN0cXNfZGlyfS8ke3RyaW1tZWRfZmFzdHFfcGF0dGVybn0pCgojIFBhc3MgYXJyYXkgY29udGVudHMgdG8gbmV3IHZhcmlhYmxlIGFzIHNwYWNlLWRlbGltaXRlZCBsaXN0CnRyaW1tZWRfZmFzdHFjX2xpc3Q9JChlY2hvICIke3RyaW1tZWRfZmFzdHFzX2FycmF5WypdfSIpCgplY2hvICJCZWdpbm5pbmcgRmFzdFFDIG9uIHRyaW1tZWQgcmVhZHMuLi4iCmVjaG8gIiIKCiMgUnVuIEZhc3RRQwojIyMgTk9URTogRG8gTk9UIHF1b3RlIHJhd19mYXN0cWNfbGlzdApmYXN0cWMgXAotLXRocmVhZHMgJHt0aHJlYWRzfSBcCi0tb3V0ZGlyICR7dHJpbW1lZF9mYXN0cXNfZGlyfSBcCi0tcXVpZXQgXAoke3RyaW1tZWRfZmFzdHFjX2xpc3R9CgplY2hvICJGYXN0UUMgb24gdHJpbW1lZCByZWFkcyBjb21wbGV0ZSEiCmVjaG8gIiIKCiMjIyMjIyMjIyMjIyBFTkQgRkFTVFFDICMjIyMjIyMjIyMjIwoKIyMjIyMjIyMjIyMjIFJVTiBNVUxUSVFDICMjIyMjIyMjIyMjIwplY2hvICJCZWdpbm5pbmcgTXVsdGlRQyBvbiB0cmltbWVkIEZhc3RRQy4uLiIKZWNobyAiIgoKbXVsdGlxYyAke3RyaW1tZWRfZmFzdHFzX2Rpcn0gLW8gJHt0cmltbWVkX2Zhc3Rxc19kaXJ9CgplY2hvICIiCmVjaG8gIk11bHRpUUMgb24gdHJpbW1lZCBGYXN0UXMgY29tcGxldGUuIgplY2hvICIiCgojIyMjIyMjIyMjIyMgRU5EIE1VTFRJUUMgIyMjIyMjIyMjIyMjCgplY2hvICJSZW1vdmluZyBGYXN0UUMgemlwIGZpbGVzLiIKZWNobyAiIgpybSAke3RyaW1tZWRfZmFzdHFzX2Rpcn0vKi56aXAKZWNobyAiRmFzdFFDIHppcCBmaWxlcyByZW1vdmVkLiIKZWNobyAiIgpgYGAK