index.html
Copy reads to the working tree
I prefer to concatenate the multiple sequence files into a single file for each the forward(R1) and reverse(R2) sequences. Interestingly, for this data I decided to handle all steps in one shot with a single script which is invoked with 1 argument for each sample. The text of that script ‘copy_process.sh’ follows:
cd preprocessing
for i in $(/bin/ls hpgl*); do
./copy_process.sh ${i}
done
## startdir=$(pwd)
## for i in "$@"; do
## cd $startdir
## cyoa --task rnaseq --method copyraw --raw_dir "/cbcb/lab/nelsayed/raw_data/ade" --hpgl ${i}
## cd $i
## inputs="${i}_forward.fastq.gz:${i}_reverse.fastq.gz"
## trimmed="${i}_forward-trimmed.fastq.gz:${i}_reverse-trimmed.fastq.gz"
## cyoa --task rnaseq --method fastqc --input ${inputs}
## cyoa --task rnaseq --method trimomatic --input ${inputs}
## trim_id=$(cat last_job.txt)
## cyoa --task rnaseq --method tophat --input ${trimmed} -s lpanamensis --depends "${trim_id}"
## lp_id=$(cat last_job.txt)
## cyoa --task rnaseq --method tophat --input ${trimmed} -s lbraziliensis --depends "${trim_id}"
## lb_id=$(cat last_job.txt)
## cyoa --task rnaseq --method tophat --input ${trimmed} -s hsapiens --depends "${trim_id}"
## hs_id=$(cat last_job.txt)
## rm last_job.txt
## cd $startdir
## done
This process is therefore done in 6 steps: 1. Copy the raw data from Najib’s raw_data directory 2. Perform fastqc on the raw reads 3. Perform trimomatic 4. Align with tophat against the L.panamensis genome 5. Align with tophat against the L.braziliensis genome 6. Align with tophat against the H.sapiens genome
One small caveat, these sequences were created in two separate groups, hpgl0241-hpgl0322 and hpgl0630-hpgl0663.
Fastqc
The cyoa tool writes out a script which looks like the following:
## This FastQC run is against rnaseq data and is used for
## an initial estimation of the overall sequencing quality.
mkdir -p outputs/fastqc && \
fastqc --extract -o outputs/fastqc hpgl0241_forward-trimmed.fastq hpgl0241_reverse-trimmed.fastq \
2>outputs/fastqc.out 1>&2
A relevant plot from fastqc is (from sample hpgl0241):
Forward qualities:
Reverse qualities: 
Trimomatic
The trimomatic script looks like: It is worth noting that in some cases, the illumina adapter removal results in a java exception. If that happens, rather than lose the data I made my cyoa script re-invoke trimomatic without the illumina clipping. In addition, if things need to be redone, then the sequences may in fact have been moved into the sequences/ directory and compressed with xz -9e, thus the if [[]] at the beginning testing for those files.
## Trimomatic_Pairwise: In case a trimming needs to be redone...
if [[ ! -r "hpgl0663_forward.fastq.gz" ]]; then
if [[ -r "sequences/hpgl0663_forward.fastq.xz" ]]; then
mv sequences/hpgl0663_forward.fastq.xz . && pxz -d hpgl0663_forward.fastq.xz && pigz hpgl0663_forward.fastq && mv sequences/hpgl0663_reverse.fastq.xz . &&
pxz -d hpgl0663_reverse.fastq.xz && pigz hpgl0663_reverse.fastq
else
echo "Missing files. Did not find hpgl0663_forward.fastq.gz nor sequences/hpgl0663_forward.fastq.xz"
exit 1
fi
fi
trimomatic PE -threads 1 -phred33 hpgl0663_forward.fastq.gz hpgl0663_reverse.fastq.gz hpgl0663_forward-trimmed_paired.fastq.gz hpgl0663_forward-trimmed_unpair
ed.fastq.gz hpgl0663_reverse-trimmed_paired.fastq.gz hpgl0663_reverse-trimmed_unpaired.fastq.gz ILLUMINACLIP:/cbcbhomes/abelew/libraries/adapters.fa:2:20:4 SL
IDINGWINDOW:4:25 1>outputs/hpgl0663-trimomatic.out 2>&1
excepted=$(grep "Exception" outputs/hpgl0663-trimomatic.out)
## The following is in case the illumina clipping fails, which it does if this has already been run I think.
if [[ "${excepted}" != "" ]]; then
trimomatic PE -threads 1 -phred33 hpgl0663_forward.fastq.gz hpgl0663_reverse.fastq.gz hpgl0663_forward-trimmed_paired.fastq.gz hpgl0663_forward-trimmed_unpa
ired.fastq.gz hpgl0663_reverse-trimmed_paired.fastq.gz hpgl0663_reverse-trimmed_unpaired.fastq.gz SLIDINGWINDOW:4:25 1>>outputs/hpgl0663-trimomatic.out 2>&1
fi
sleep 10
mv hpgl0663_forward-trimmed_paired.fastq.gz hpgl0663_forward-trimmed.fastq.gz && mv hpgl0663_reverse-trimmed_paired.fastq.gz hpgl0663_reverse-trimmed.fastq.gz
The end result should be a set of files with trimmed, paired sequences separated from unpaired sequences.
Tophat
The tophat process is actually a couple of steps rolled into one, the trimmed/paired reads are fed to tophat, then the accepted_hits.bam is tested for properly paired reads and those reads are separated into accepted_paired.bam. These 2 bam files are sorted and indexed, and finally passed to htseq. Thus the tophat scripts look like:
These scripts however, do not include the additional processing step which split the accepted_hits.bam into accepted_paired.bam I am not sure why, but these scripts are missing the following step which was performed but not properly logged:
if [ -r "${tophat_dir}/accepted_hits.bam" ]; then
samtools view -b -f 2 ${tophat_dir}/accepted_hits.bam > ${tophat_dir}/accepted_paired.bam && samtools index ${tophat_dir}/accepted_paired.bam
fi
I know this step was performed, because the files accepted_paired.bam exists for each directory, but the option -f 2 says that the ‘2’ flag must be set, which is the flag for an alignment which is paired.
## scripts/th_lbraziliensis-hpgl0663.sh
mkdir -p outputs/tophat_lbraziliensis && tophat -g 1 \
-G /cbcbhomes/abelew/libraries/genome/lbraziliensis.gff \
--b2-very-sensitive -p 4 -o outputs/tophat_lbraziliensis \
/cbcbhomes/abelew/libraries/genome/indexes/lbraziliensis \
hpgl0663_forward-trimmed.fastq.gz hpgl0663_reverse-trimmed.fastq.gz && \
samtools sort -l 9 -n outputs/tophat_lbraziliensis/accepted_hits.bam outputs/tophat_lbraziliensis/accepted_sorted && \
mv outputs/tophat_lbraziliensis/accepted_sorted.bam outputs/tophat_lbraziliensis/accepted_hits.bam && \
samtools index outputs/tophat_lbraziliensis/accepted_hits.bam && \
samtools sort -l 9 -n outputs/tophat_lbraziliensis/unmapped.bam outputs/tophat_lbraziliensis/unmapped_sorted && \
mv outputs/tophat_lbraziliensis/unmapped_sorted.bam outputs/tophat_lbraziliensis/unmapped.bam && \
samtools index outputs/tophat_lbraziliensis/unmapped.bam
## scripts/th_lpanamensis-hpgl0663.sh
mkdir -p outputs/tophat_lpanamensis && tophat -g 1 \
-G /cbcbhomes/abelew/libraries/genome/lpanamensis.gff \
--b2-very-sensitive -p 4 -o outputs/tophat_lpanamensis \
/cbcbhomes/abelew/libraries/genome/indexes/lpanamensis \
hpgl0663_forward-trimmed.fastq.gz hpgl0663_reverse-trimmed.fastq.gz && \
samtools sort -l 9 -n outputs/tophat_lpanamensis/accepted_hits.bam outputs/tophat_lpanamensis/accepted_sorted && \
mv outputs/tophat_lpanamensis/accepted_sorted.bam outputs/tophat_lpanamensis/accepted_hits.bam && \
samtools index outputs/tophat_lpanamensis/accepted_hits.bam && \
samtools sort -l 9 -n outputs/tophat_lpanamensis/unmapped.bam outputs/tophat_lpanamensis/unmapped_sorted && \
mv outputs/tophat_lpanamensis/unmapped_sorted.bam outputs/tophat_lpanamensis/unmapped.bam && \
samtools index outputs/tophat_lpanamensis/unmapped.bam
## scripts/th_hsapiens-hpgl0633.sh
mkdir -p outputs/tophat_hsapiens && tophat -g 1 \
-G /cbcbhomes/abelew/libraries/genome/hsapiens.gtf \
--b2-very-sensitive -p 4 -o outputs/tophat_hsapiens \
/cbcbhomes/abelew/libraries/genome/indexes/hsapiens \
hpgl0241_forward-trimmed.fastq hpgl0241_reverse-trimmed.fastq && \
samtools sort -l 9 -n outputs/tophat_hsapiens/accepted_hits.bam outputs/tophat_hsapiens/accepted_sorted && \
mv outputs/tophat_hsapiens/accepted_sorted.bam outputs/tophat_hsapiens/accepted_hits.bam && \
samtools index outputs/tophat_hsapiens/accepted_hits.bam
Run htseq
The above scripts create sorted accepted_hits.bam files, I think that I manually made the accepted_paired.bam files and added those steps to the cyoa script post-facto, but the end result is the same and so I needed to run htseq on both:
## scripts/th_lpanamensis-hpgl0241.sh
## Counting the number of hits in outputs/tophat_lpanamensis/accepted_hits.bam for each feature found in /cbcbhomes/abelew/libraries/genome/lpanamensis.gff
## Is this stranded? no. The defaults of htseq are:
## --order=name --idattr=gene_id --minaqual=10 --type=exon --stranded=yes --mode=union
htseq-count -q -f bam -s no -i ID \
outputs/tophat_lpanamensis/accepted_hits.bam /cbcbhomes/abelew/libraries/genome/lpanamensis.gff \
1>outputs/tophat_lpanamensis/accepted_hits.count 2>outputs/tophat_lpanamensis/accepted_hits.error && \
xz -9e outputs/tophat_lpanamensis/accepted_hits.count
## I am not going to belabor the point and print the htseq commands for all species.
Run Kallisto
A new alignment tool is kallisto, which skips all the intermediate steps and generates a set of pseudo-counts using a database of all possible transcripts as the index. The following describes one such invocation:
## scripts/kall_hsapiens-hpgl0241.sh
## This is a kallisto pseudoalignment of HPGL0241_R1_filtered_adaptertrim.fastq.xz HPGL0241_R2_filtered_adaptertrim.fastq against
## /cbcbhomes/abelew/libraries/genome/indexes/hsapiens.idx.
## This jobs depended on: 685883.cbcbsrv.umiacs.umd.edu
## I am not sure why I have that sleep...
mkdir -p outputs/kallisto_hsapiens && sleep 10 && \
kallisto quant --plaintext -t 4 -b 100 -o outputs/kallisto_hsapiens -i /cbcbhomes/abelew/libraries/genome/indexes/hsapiens.idx \
HPGL0241_R1_filtered_adaptertrim.fastq.xz HPGL0241_R2_filtered_adaptertrim.fastq 2>outputs/kallisto/HPGL0241_R1_filtered_adaptertrim.fastq.xz:HPGL0241_R2_filtered_adaptertrim-kallisto.err 1>outputs/kallisto/HPGL0241_R1_filtered_adaptertrim.fastq.xz:HPGL0241_R2_filtered_adaptertrim-kallisto.out
index.html
LS0tCnRpdGxlOiAiUHJlcHJvY2Vzc2luZyBSTkFzZXEgc2FtcGxlcyBmcm9tIExlaXNobWFuaWEgcGFuYW1lbnNpcy4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogdGFuZ28KICBrZWVwX21kOiBmYWxzZQogIG1vZGU6IHNlbGZjb250YWluZWQKICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogIHRoZW1lOiBjb3NtbwogIHRvYzogdHJ1ZQogIHRvY19mbG9hdDoKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIDwhLS0gRG9jdW1lbnQgcHJlbHVkZSByZXZpc2lvbiAyMDE2LTEwIC0tPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4Owp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlPUZBTFNFfQojIyBUaGVzZSBhcmUgdGhlIG9wdGlvbnMgSSB0ZW5kIHRvIGZhdm9yCmxpYnJhcnkoImhwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KAogICAgcHJvZ3Jlc3MgPSBUUlVFLAogICAgdmVyYm9zZSA9IFRSVUUsCiAgICB3aWR0aCA9IDkwLAogICAgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAgIGVycm9yID0gVFJVRSwKICAgIGZpZy53aWR0aCA9IDgsCiAgICBmaWcuaGVpZ2h0ID0gOCwKICAgIGRwaSA9IDk2KQpvcHRpb25zKAogICAgZGlnaXRzID0gNCwKICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwKICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpzZXQuc2VlZCgxKQpybWRfZmlsZSA8LSAicHJlcHJvY2Vzc2luZy5SbWQiCmBgYAoKW2luZGV4Lmh0bWxdKGluZGV4Lmh0bWwpCgpgYGB7ciByZW5kZXIsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CiMjIFRoaXMgYmxvY2sgaXMgdXNlZCB0byByZW5kZXIgYSBkb2N1bWVudCBmcm9tIHdpdGhpbiBpdC4Kcm1hcmtkb3duOjpyZW5kZXIocm1kX2ZpbGUpCgojIyBBbiBleHRyYSByZW5kZXJlciBmb3IgcGRmIG91dHB1dApybWFya2Rvd246OnJlbmRlcihybWRfZmlsZSwgb3V0cHV0X2Zvcm1hdD0icGRmX2RvY3VtZW50Iiwgb3V0cHV0X29wdGlvbnM9Yygic2tpcF9odG1sIikpCiMjIE9yIHRvIHNhdmUvbG9hZCBsYXJnZSBSZGF0YSBmaWxlcy4KaHBnbHRvb2xzOjo6c2F2ZW1lKCkKaHBnbHRvb2xzOjo6bG9hZG1lKCkKcm0obGlzdD1scygpKQpgYGAKCiMgQ29weSByZWFkcyB0byB0aGUgd29ya2luZyB0cmVlCgpJIHByZWZlciB0byBjb25jYXRlbmF0ZSB0aGUgbXVsdGlwbGUgc2VxdWVuY2UgZmlsZXMgaW50byBhIHNpbmdsZSBmaWxlIGZvciBlYWNoIHRoZSBmb3J3YXJkKFIxKSBhbmQKcmV2ZXJzZShSMikgc2VxdWVuY2VzLiAgSW50ZXJlc3RpbmdseSwgZm9yIHRoaXMgZGF0YSBJIGRlY2lkZWQgdG8gaGFuZGxlIGFsbCBzdGVwcyBpbiBvbmUgc2hvdCB3aXRoCmEgc2luZ2xlIHNjcmlwdCB3aGljaCBpcyBpbnZva2VkIHdpdGggMSBhcmd1bWVudCBmb3IgZWFjaCBzYW1wbGUuICBUaGUgdGV4dCBvZiB0aGF0IHNjcmlwdAonY29weV9wcm9jZXNzLnNoJyBmb2xsb3dzOgoKYGBge3IgbWtkaXJzLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQpjZCBwcmVwcm9jZXNzaW5nCmZvciBpIGluICQoL2Jpbi9scyBocGdsKik7IGRvCiAgLi9jb3B5X3Byb2Nlc3Muc2ggJHtpfQpkb25lCgojIyBzdGFydGRpcj0kKHB3ZCkKIyMgZm9yIGkgaW4gIiRAIjsgZG8KIyMgICBjZCAkc3RhcnRkaXIKIyMgICBjeW9hIC0tdGFzayBybmFzZXEgLS1tZXRob2QgY29weXJhdyAtLXJhd19kaXIgIi9jYmNiL2xhYi9uZWxzYXllZC9yYXdfZGF0YS9hZGUiIC0taHBnbCAke2l9CiMjICAgY2QgJGkKIyMgICBpbnB1dHM9IiR7aX1fZm9yd2FyZC5mYXN0cS5nejoke2l9X3JldmVyc2UuZmFzdHEuZ3oiCiMjICAgdHJpbW1lZD0iJHtpfV9mb3J3YXJkLXRyaW1tZWQuZmFzdHEuZ3o6JHtpfV9yZXZlcnNlLXRyaW1tZWQuZmFzdHEuZ3oiCiMjICAgY3lvYSAtLXRhc2sgcm5hc2VxIC0tbWV0aG9kIGZhc3RxYyAtLWlucHV0ICR7aW5wdXRzfQojIyAgIGN5b2EgLS10YXNrIHJuYXNlcSAtLW1ldGhvZCB0cmltb21hdGljIC0taW5wdXQgJHtpbnB1dHN9CiMjICAgdHJpbV9pZD0kKGNhdCBsYXN0X2pvYi50eHQpCiMjICAgY3lvYSAtLXRhc2sgcm5hc2VxIC0tbWV0aG9kIHRvcGhhdCAtLWlucHV0ICR7dHJpbW1lZH0gLXMgbHBhbmFtZW5zaXMgLS1kZXBlbmRzICIke3RyaW1faWR9IgojIyAgIGxwX2lkPSQoY2F0IGxhc3Rfam9iLnR4dCkKIyMgICBjeW9hIC0tdGFzayBybmFzZXEgLS1tZXRob2QgdG9waGF0IC0taW5wdXQgJHt0cmltbWVkfSAtcyBsYnJhemlsaWVuc2lzIC0tZGVwZW5kcyAiJHt0cmltX2lkfSIKIyMgICBsYl9pZD0kKGNhdCBsYXN0X2pvYi50eHQpCiMjICAgY3lvYSAtLXRhc2sgcm5hc2VxIC0tbWV0aG9kIHRvcGhhdCAtLWlucHV0ICR7dHJpbW1lZH0gLXMgaHNhcGllbnMgLS1kZXBlbmRzICIke3RyaW1faWR9IgojIyAgIGhzX2lkPSQoY2F0IGxhc3Rfam9iLnR4dCkKIyMgICBybSBsYXN0X2pvYi50eHQKIyMgICBjZCAkc3RhcnRkaXIKIyMgZG9uZQpgYGAKClRoaXMgcHJvY2VzcyBpcyB0aGVyZWZvcmUgZG9uZSBpbiA2IHN0ZXBzOgoxLiAgQ29weSB0aGUgcmF3IGRhdGEgZnJvbSBOYWppYidzIHJhd19kYXRhIGRpcmVjdG9yeQoyLiAgUGVyZm9ybSBmYXN0cWMgb24gdGhlIHJhdyByZWFkcwozLiAgUGVyZm9ybSB0cmltb21hdGljCjQuICBBbGlnbiB3aXRoIHRvcGhhdCBhZ2FpbnN0IHRoZSBMLnBhbmFtZW5zaXMgZ2Vub21lCjUuICBBbGlnbiB3aXRoIHRvcGhhdCBhZ2FpbnN0IHRoZSBMLmJyYXppbGllbnNpcyBnZW5vbWUKNi4gIEFsaWduIHdpdGggdG9waGF0IGFnYWluc3QgdGhlIEguc2FwaWVucyBnZW5vbWUKCk9uZSBzbWFsbCBjYXZlYXQsIHRoZXNlIHNlcXVlbmNlcyB3ZXJlIGNyZWF0ZWQgaW4gdHdvIHNlcGFyYXRlIGdyb3VwcywgaHBnbDAyNDEtaHBnbDAzMjIgYW5kCmhwZ2wwNjMwLWhwZ2wwNjYzLgoKIyBGYXN0cWMKClRoZSBjeW9hIHRvb2wgd3JpdGVzIG91dCBhIHNjcmlwdCB3aGljaCBsb29rcyBsaWtlIHRoZSBmb2xsb3dpbmc6CgpgYGB7ciBmYXN0cWNfc2NyaXB0LCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIyBUaGlzIEZhc3RRQyBydW4gaXMgYWdhaW5zdCBybmFzZXEgZGF0YSBhbmQgaXMgdXNlZCBmb3IKIyMgYW4gaW5pdGlhbCBlc3RpbWF0aW9uIG9mIHRoZSBvdmVyYWxsIHNlcXVlbmNpbmcgcXVhbGl0eS4KbWtkaXIgLXAgb3V0cHV0cy9mYXN0cWMgJiYgXAogIGZhc3RxYyAtLWV4dHJhY3QgLW8gb3V0cHV0cy9mYXN0cWMgaHBnbDAyNDFfZm9yd2FyZC10cmltbWVkLmZhc3RxIGhwZ2wwMjQxX3JldmVyc2UtdHJpbW1lZC5mYXN0cSBcCiAgMj5vdXRwdXRzL2Zhc3RxYy5vdXQgMT4mMgpgYGAKCkEgcmVsZXZhbnQgcGxvdCBmcm9tIGZhc3RxYyBpcyAoZnJvbSBzYW1wbGUgaHBnbDAyNDEpOgoKRm9yd2FyZCBxdWFsaXRpZXM6CiFbZm9yd2FyZCBxdWFsaXR5XShwcmVwcm9jZXNzaW5nL2hwZ2wwMjQxL291dHB1dHMvZmFzdHFjL2hwZ2wwMjQxX2ZvcndhcmQtdHJpbW1lZF9mYXN0cWMvSW1hZ2VzL3Blcl9iYXNlX3F1YWxpdHkucG5nKQpSZXZlcnNlIHF1YWxpdGllczoKIVtyZXZlcnNlIHF1YWxpdHldKHByZXByb2Nlc3NpbmcvaHBnbDAyNDEvb3V0cHV0cy9mYXN0cWMvaHBnbDAyNDFfcmV2ZXJzZS10cmltbWVkX2Zhc3RxYy9JbWFnZXMvcGVyX2Jhc2VfcXVhbGl0eS5wbmcpCgojIFRyaW1vbWF0aWMKClRoZSB0cmltb21hdGljIHNjcmlwdCBsb29rcyBsaWtlOgpJdCBpcyB3b3J0aCBub3RpbmcgdGhhdCBpbiBzb21lIGNhc2VzLCB0aGUgaWxsdW1pbmEgYWRhcHRlciByZW1vdmFsIHJlc3VsdHMgaW4gYSBqYXZhIGV4Y2VwdGlvbi4gIElmCnRoYXQgaGFwcGVucywgcmF0aGVyIHRoYW4gbG9zZSB0aGUgZGF0YSBJIG1hZGUgbXkgY3lvYSBzY3JpcHQgcmUtaW52b2tlIHRyaW1vbWF0aWMgd2l0aG91dCB0aGUKaWxsdW1pbmEgY2xpcHBpbmcuICBJbiBhZGRpdGlvbiwgaWYgdGhpbmdzIG5lZWQgdG8gYmUgcmVkb25lLCB0aGVuIHRoZSBzZXF1ZW5jZXMgbWF5IGluIGZhY3QgaGF2ZQpiZWVuIG1vdmVkIGludG8gdGhlIHNlcXVlbmNlcy8gZGlyZWN0b3J5IGFuZCBjb21wcmVzc2VkIHdpdGggeHogLTllLCB0aHVzIHRoZSBpZiBbW11dIGF0IHRoZQpiZWdpbm5pbmcgdGVzdGluZyBmb3IgdGhvc2UgZmlsZXMuCgpgYGB7ciB0cmltb21hdGljX3NjcmlwdCwgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyMgVHJpbW9tYXRpY19QYWlyd2lzZTogSW4gY2FzZSBhIHRyaW1taW5nIG5lZWRzIHRvIGJlIHJlZG9uZS4uLgppZiBbWyAhIC1yICJocGdsMDY2M19mb3J3YXJkLmZhc3RxLmd6IiBdXTsgdGhlbgogIGlmIFtbIC1yICJzZXF1ZW5jZXMvaHBnbDA2NjNfZm9yd2FyZC5mYXN0cS54eiIgXV07IHRoZW4KICAgIG12IHNlcXVlbmNlcy9ocGdsMDY2M19mb3J3YXJkLmZhc3RxLnh6IC4gJiYgcHh6IC1kIGhwZ2wwNjYzX2ZvcndhcmQuZmFzdHEueHogJiYgcGlneiBocGdsMDY2M19mb3J3YXJkLmZhc3RxICYmIG12IHNlcXVlbmNlcy9ocGdsMDY2M19yZXZlcnNlLmZhc3RxLnh6IC4gJiYKIHB4eiAtZCBocGdsMDY2M19yZXZlcnNlLmZhc3RxLnh6ICYmIHBpZ3ogaHBnbDA2NjNfcmV2ZXJzZS5mYXN0cQogIGVsc2UKICAgIGVjaG8gIk1pc3NpbmcgZmlsZXMuIERpZCBub3QgZmluZCBocGdsMDY2M19mb3J3YXJkLmZhc3RxLmd6IG5vciBzZXF1ZW5jZXMvaHBnbDA2NjNfZm9yd2FyZC5mYXN0cS54eiIKICAgIGV4aXQgMQogIGZpCmZpCnRyaW1vbWF0aWMgUEUgLXRocmVhZHMgMSAtcGhyZWQzMyBocGdsMDY2M19mb3J3YXJkLmZhc3RxLmd6IGhwZ2wwNjYzX3JldmVyc2UuZmFzdHEuZ3ogaHBnbDA2NjNfZm9yd2FyZC10cmltbWVkX3BhaXJlZC5mYXN0cS5neiBocGdsMDY2M19mb3J3YXJkLXRyaW1tZWRfdW5wYWlyCmVkLmZhc3RxLmd6IGhwZ2wwNjYzX3JldmVyc2UtdHJpbW1lZF9wYWlyZWQuZmFzdHEuZ3ogaHBnbDA2NjNfcmV2ZXJzZS10cmltbWVkX3VucGFpcmVkLmZhc3RxLmd6IElMTFVNSU5BQ0xJUDovY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvYWRhcHRlcnMuZmE6MjoyMDo0IFNMCklESU5HV0lORE9XOjQ6MjUgMT5vdXRwdXRzL2hwZ2wwNjYzLXRyaW1vbWF0aWMub3V0IDI+JjEKZXhjZXB0ZWQ9JChncmVwICJFeGNlcHRpb24iIG91dHB1dHMvaHBnbDA2NjMtdHJpbW9tYXRpYy5vdXQpCiMjIFRoZSBmb2xsb3dpbmcgaXMgaW4gY2FzZSB0aGUgaWxsdW1pbmEgY2xpcHBpbmcgZmFpbHMsIHdoaWNoIGl0IGRvZXMgaWYgdGhpcyBoYXMgYWxyZWFkeSBiZWVuIHJ1biBJIHRoaW5rLgppZiBbWyAiJHtleGNlcHRlZH0iICE9ICIiIF1dOyB0aGVuCiAgdHJpbW9tYXRpYyBQRSAtdGhyZWFkcyAxIC1waHJlZDMzIGhwZ2wwNjYzX2ZvcndhcmQuZmFzdHEuZ3ogaHBnbDA2NjNfcmV2ZXJzZS5mYXN0cS5neiBocGdsMDY2M19mb3J3YXJkLXRyaW1tZWRfcGFpcmVkLmZhc3RxLmd6IGhwZ2wwNjYzX2ZvcndhcmQtdHJpbW1lZF91bnBhCmlyZWQuZmFzdHEuZ3ogaHBnbDA2NjNfcmV2ZXJzZS10cmltbWVkX3BhaXJlZC5mYXN0cS5neiBocGdsMDY2M19yZXZlcnNlLXRyaW1tZWRfdW5wYWlyZWQuZmFzdHEuZ3ogU0xJRElOR1dJTkRPVzo0OjI1IDE+Pm91dHB1dHMvaHBnbDA2NjMtdHJpbW9tYXRpYy5vdXQgMj4mMQpmaQpzbGVlcCAxMAptdiBocGdsMDY2M19mb3J3YXJkLXRyaW1tZWRfcGFpcmVkLmZhc3RxLmd6IGhwZ2wwNjYzX2ZvcndhcmQtdHJpbW1lZC5mYXN0cS5neiAmJiBtdiBocGdsMDY2M19yZXZlcnNlLXRyaW1tZWRfcGFpcmVkLmZhc3RxLmd6IGhwZ2wwNjYzX3JldmVyc2UtdHJpbW1lZC5mYXN0cS5negpgYGAKClRoZSBlbmQgcmVzdWx0IHNob3VsZCBiZSBhIHNldCBvZiBmaWxlcyB3aXRoIHRyaW1tZWQsIHBhaXJlZCBzZXF1ZW5jZXMgc2VwYXJhdGVkIGZyb20gdW5wYWlyZWQKc2VxdWVuY2VzLgoKIyBUb3BoYXQKClRoZSB0b3BoYXQgcHJvY2VzcyBpcyBhY3R1YWxseSBhIGNvdXBsZSBvZiBzdGVwcyByb2xsZWQgaW50byBvbmUsIHRoZSB0cmltbWVkL3BhaXJlZCByZWFkcyBhcmUgZmVkCnRvIHRvcGhhdCwgdGhlbiB0aGUgYWNjZXB0ZWRfaGl0cy5iYW0gaXMgdGVzdGVkIGZvciBwcm9wZXJseSBwYWlyZWQgcmVhZHMgYW5kIHRob3NlIHJlYWRzIGFyZQpzZXBhcmF0ZWQgaW50byBhY2NlcHRlZF9wYWlyZWQuYmFtLiAgVGhlc2UgMiBiYW0gZmlsZXMgYXJlIHNvcnRlZCBhbmQgaW5kZXhlZCwgYW5kIGZpbmFsbHkgcGFzc2VkIHRvCmh0c2VxLiAgVGh1cyB0aGUgdG9waGF0IHNjcmlwdHMgbG9vayBsaWtlOgoKVGhlc2Ugc2NyaXB0cyBob3dldmVyLCBkbyBub3QgaW5jbHVkZSB0aGUgYWRkaXRpb25hbCBwcm9jZXNzaW5nIHN0ZXAgd2hpY2ggc3BsaXQgdGhlCmFjY2VwdGVkX2hpdHMuYmFtIGludG8gYWNjZXB0ZWRfcGFpcmVkLmJhbSAgSSBhbSBub3Qgc3VyZSB3aHksIGJ1dCB0aGVzZSBzY3JpcHRzIGFyZSBtaXNzaW5nIHRoZQpmb2xsb3dpbmcgc3RlcCB3aGljaCB3YXMgcGVyZm9ybWVkIGJ1dCBub3QgcHJvcGVybHkgbG9nZ2VkOgoKYGBge3IgcGFpcmVkX2hpdHMsIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CmlmIFsgLXIgIiR7dG9waGF0X2Rpcn0vYWNjZXB0ZWRfaGl0cy5iYW0iIF07IHRoZW4KICBzYW10b29scyB2aWV3IC1iIC1mIDIgJHt0b3BoYXRfZGlyfS9hY2NlcHRlZF9oaXRzLmJhbSA+ICR7dG9waGF0X2Rpcn0vYWNjZXB0ZWRfcGFpcmVkLmJhbSAmJiBzYW10b29scyBpbmRleCAke3RvcGhhdF9kaXJ9L2FjY2VwdGVkX3BhaXJlZC5iYW0KZmkKYGBgCgpJIGtub3cgdGhpcyBzdGVwIHdhcyBwZXJmb3JtZWQsIGJlY2F1c2UgdGhlIGZpbGVzIGFjY2VwdGVkX3BhaXJlZC5iYW0gZXhpc3RzIGZvciBlYWNoIGRpcmVjdG9yeSwgYnV0CnRoZSBvcHRpb24gLWYgMiBzYXlzIHRoYXQgdGhlICcyJyBmbGFnIG11c3QgYmUgc2V0LCB3aGljaCBpcyB0aGUgZmxhZyBmb3IgYW4gYWxpZ25tZW50IHdoaWNoIGlzCnBhaXJlZC4KCmBgYHtyIHRvcGhhdF9ydW5zLCBlbmdpbmU9J2Jhc2gnLCBldmFsPUZBTFNFfQojIyBzY3JpcHRzL3RoX2xicmF6aWxpZW5zaXMtaHBnbDA2NjMuc2gKbWtkaXIgLXAgb3V0cHV0cy90b3BoYXRfbGJyYXppbGllbnNpcyAmJiB0b3BoYXQgIC1nIDEgIFwKICAtRyAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL2xicmF6aWxpZW5zaXMuZ2ZmIFwKICAtLWIyLXZlcnktc2Vuc2l0aXZlIC1wIDQgLW8gb3V0cHV0cy90b3BoYXRfbGJyYXppbGllbnNpcyBcCi9jYmNiaG9tZXMvYWJlbGV3L2xpYnJhcmllcy9nZW5vbWUvaW5kZXhlcy9sYnJhemlsaWVuc2lzIFwKICBocGdsMDY2M19mb3J3YXJkLXRyaW1tZWQuZmFzdHEuZ3ogaHBnbDA2NjNfcmV2ZXJzZS10cmltbWVkLmZhc3RxLmd6ICYmIFwKICBzYW10b29scyBzb3J0IC1sIDkgLW4gb3V0cHV0cy90b3BoYXRfbGJyYXppbGllbnNpcy9hY2NlcHRlZF9oaXRzLmJhbSBvdXRwdXRzL3RvcGhhdF9sYnJhemlsaWVuc2lzL2FjY2VwdGVkX3NvcnRlZCAmJiBcCiAgbXYgb3V0cHV0cy90b3BoYXRfbGJyYXppbGllbnNpcy9hY2NlcHRlZF9zb3J0ZWQuYmFtIG91dHB1dHMvdG9waGF0X2xicmF6aWxpZW5zaXMvYWNjZXB0ZWRfaGl0cy5iYW0gJiYgXAogIHNhbXRvb2xzIGluZGV4IG91dHB1dHMvdG9waGF0X2xicmF6aWxpZW5zaXMvYWNjZXB0ZWRfaGl0cy5iYW0gJiYgXAogIHNhbXRvb2xzIHNvcnQgLWwgOSAtbiBvdXRwdXRzL3RvcGhhdF9sYnJhemlsaWVuc2lzL3VubWFwcGVkLmJhbSBvdXRwdXRzL3RvcGhhdF9sYnJhemlsaWVuc2lzL3VubWFwcGVkX3NvcnRlZCAmJiBcCiAgbXYgb3V0cHV0cy90b3BoYXRfbGJyYXppbGllbnNpcy91bm1hcHBlZF9zb3J0ZWQuYmFtIG91dHB1dHMvdG9waGF0X2xicmF6aWxpZW5zaXMvdW5tYXBwZWQuYmFtICYmIFwKICBzYW10b29scyBpbmRleCBvdXRwdXRzL3RvcGhhdF9sYnJhemlsaWVuc2lzL3VubWFwcGVkLmJhbQoKIyMgc2NyaXB0cy90aF9scGFuYW1lbnNpcy1ocGdsMDY2My5zaApta2RpciAtcCBvdXRwdXRzL3RvcGhhdF9scGFuYW1lbnNpcyAmJiB0b3BoYXQgIC1nIDEgIFwKICAtRyAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL2xwYW5hbWVuc2lzLmdmZiBcCiAgLS1iMi12ZXJ5LXNlbnNpdGl2ZSAtcCA0IC1vIG91dHB1dHMvdG9waGF0X2xwYW5hbWVuc2lzIFwKL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9pbmRleGVzL2xwYW5hbWVuc2lzIFwKICBocGdsMDY2M19mb3J3YXJkLXRyaW1tZWQuZmFzdHEuZ3ogaHBnbDA2NjNfcmV2ZXJzZS10cmltbWVkLmZhc3RxLmd6ICYmIFwKICBzYW10b29scyBzb3J0IC1sIDkgLW4gb3V0cHV0cy90b3BoYXRfbHBhbmFtZW5zaXMvYWNjZXB0ZWRfaGl0cy5iYW0gb3V0cHV0cy90b3BoYXRfbHBhbmFtZW5zaXMvYWNjZXB0ZWRfc29ydGVkICYmIFwKICBtdiBvdXRwdXRzL3RvcGhhdF9scGFuYW1lbnNpcy9hY2NlcHRlZF9zb3J0ZWQuYmFtIG91dHB1dHMvdG9waGF0X2xwYW5hbWVuc2lzL2FjY2VwdGVkX2hpdHMuYmFtICYmIFwKICBzYW10b29scyBpbmRleCBvdXRwdXRzL3RvcGhhdF9scGFuYW1lbnNpcy9hY2NlcHRlZF9oaXRzLmJhbSAmJiBcCiAgc2FtdG9vbHMgc29ydCAtbCA5IC1uIG91dHB1dHMvdG9waGF0X2xwYW5hbWVuc2lzL3VubWFwcGVkLmJhbSBvdXRwdXRzL3RvcGhhdF9scGFuYW1lbnNpcy91bm1hcHBlZF9zb3J0ZWQgJiYgXAogIG12IG91dHB1dHMvdG9waGF0X2xwYW5hbWVuc2lzL3VubWFwcGVkX3NvcnRlZC5iYW0gb3V0cHV0cy90b3BoYXRfbHBhbmFtZW5zaXMvdW5tYXBwZWQuYmFtICYmIFwKICBzYW10b29scyBpbmRleCBvdXRwdXRzL3RvcGhhdF9scGFuYW1lbnNpcy91bm1hcHBlZC5iYW0KCiMjIHNjcmlwdHMvdGhfaHNhcGllbnMtaHBnbDA2MzMuc2gKbWtkaXIgLXAgb3V0cHV0cy90b3BoYXRfaHNhcGllbnMgJiYgdG9waGF0ICAtZyAxICBcCiAgLUcgL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9oc2FwaWVucy5ndGYgXAogIC0tYjItdmVyeS1zZW5zaXRpdmUgLXAgNCAtbyBvdXRwdXRzL3RvcGhhdF9oc2FwaWVucyBcCi9jYmNiaG9tZXMvYWJlbGV3L2xpYnJhcmllcy9nZW5vbWUvaW5kZXhlcy9oc2FwaWVucyBcCiAgaHBnbDAyNDFfZm9yd2FyZC10cmltbWVkLmZhc3RxIGhwZ2wwMjQxX3JldmVyc2UtdHJpbW1lZC5mYXN0cSAmJiBcCiAgc2FtdG9vbHMgc29ydCAtbCA5IC1uIG91dHB1dHMvdG9waGF0X2hzYXBpZW5zL2FjY2VwdGVkX2hpdHMuYmFtIG91dHB1dHMvdG9waGF0X2hzYXBpZW5zL2FjY2VwdGVkX3NvcnRlZCAmJiBcCiAgbXYgb3V0cHV0cy90b3BoYXRfaHNhcGllbnMvYWNjZXB0ZWRfc29ydGVkLmJhbSBvdXRwdXRzL3RvcGhhdF9oc2FwaWVucy9hY2NlcHRlZF9oaXRzLmJhbSAmJiBcCiAgc2FtdG9vbHMgaW5kZXggb3V0cHV0cy90b3BoYXRfaHNhcGllbnMvYWNjZXB0ZWRfaGl0cy5iYW0KYGBgCgojIFJ1biBodHNlcQoKVGhlIGFib3ZlIHNjcmlwdHMgY3JlYXRlIHNvcnRlZCBhY2NlcHRlZF9oaXRzLmJhbSBmaWxlcywgSSB0aGluayB0aGF0IEkgbWFudWFsbHkgbWFkZSB0aGUKYWNjZXB0ZWRfcGFpcmVkLmJhbSBmaWxlcyBhbmQgYWRkZWQgdGhvc2Ugc3RlcHMgdG8gdGhlIGN5b2Egc2NyaXB0IHBvc3QtZmFjdG8sIGJ1dCB0aGUgZW5kIHJlc3VsdCBpcwp0aGUgc2FtZSBhbmQgc28gSSBuZWVkZWQgdG8gcnVuIGh0c2VxIG9uIGJvdGg6CgpgYGB7ciBodHNlcV9pbnZvY2F0aW9ucywgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KIyMgc2NyaXB0cy90aF9scGFuYW1lbnNpcy1ocGdsMDI0MS5zaAojIyBDb3VudGluZyB0aGUgbnVtYmVyIG9mIGhpdHMgaW4gb3V0cHV0cy90b3BoYXRfbHBhbmFtZW5zaXMvYWNjZXB0ZWRfaGl0cy5iYW0gZm9yIGVhY2ggZmVhdHVyZSBmb3VuZCBpbiAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL2xwYW5hbWVuc2lzLmdmZgojIyBJcyB0aGlzIHN0cmFuZGVkPyBuby4gIFRoZSBkZWZhdWx0cyBvZiBodHNlcSBhcmU6CiMjICAtLW9yZGVyPW5hbWUgLS1pZGF0dHI9Z2VuZV9pZCAtLW1pbmFxdWFsPTEwIC0tdHlwZT1leG9uIC0tc3RyYW5kZWQ9eWVzIC0tbW9kZT11bmlvbgpodHNlcS1jb3VudCAtcSAtZiBiYW0gLXMgbm8gIC1pIElEICBcCiAgb3V0cHV0cy90b3BoYXRfbHBhbmFtZW5zaXMvYWNjZXB0ZWRfaGl0cy5iYW0gL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9scGFuYW1lbnNpcy5nZmYgXAogIDE+b3V0cHV0cy90b3BoYXRfbHBhbmFtZW5zaXMvYWNjZXB0ZWRfaGl0cy5jb3VudCAyPm91dHB1dHMvdG9waGF0X2xwYW5hbWVuc2lzL2FjY2VwdGVkX2hpdHMuZXJyb3IgJiYgXAogICAgeHogLTllIG91dHB1dHMvdG9waGF0X2xwYW5hbWVuc2lzL2FjY2VwdGVkX2hpdHMuY291bnQKIyMgSSBhbSBub3QgZ29pbmcgdG8gYmVsYWJvciB0aGUgcG9pbnQgYW5kIHByaW50IHRoZSBodHNlcSBjb21tYW5kcyBmb3IgYWxsIHNwZWNpZXMuCmBgYAoKIyBSdW4gS2FsbGlzdG8KCkEgbmV3IGFsaWdubWVudCB0b29sIGlzIGthbGxpc3RvLCB3aGljaCBza2lwcyBhbGwgdGhlIGludGVybWVkaWF0ZSBzdGVwcyBhbmQgZ2VuZXJhdGVzIGEgc2V0IG9mCnBzZXVkby1jb3VudHMgdXNpbmcgYSBkYXRhYmFzZSBvZiBhbGwgcG9zc2libGUgdHJhbnNjcmlwdHMgYXMgdGhlIGluZGV4LiAgVGhlIGZvbGxvd2luZyBkZXNjcmliZXMKb25lIHN1Y2ggaW52b2NhdGlvbjoKCmBgYHtyIGthbGxpc3RvX2ludm9jYXRpb24sIGVuZ2luZT0nYmFzaCcsIGV2YWw9RkFMU0V9CiMjIHNjcmlwdHMva2FsbF9oc2FwaWVucy1ocGdsMDI0MS5zaAojIyBUaGlzIGlzIGEga2FsbGlzdG8gcHNldWRvYWxpZ25tZW50IG9mIEhQR0wwMjQxX1IxX2ZpbHRlcmVkX2FkYXB0ZXJ0cmltLmZhc3RxLnh6IEhQR0wwMjQxX1IyX2ZpbHRlcmVkX2FkYXB0ZXJ0cmltLmZhc3RxIGFnYWluc3QKIyMgL2NiY2Job21lcy9hYmVsZXcvbGlicmFyaWVzL2dlbm9tZS9pbmRleGVzL2hzYXBpZW5zLmlkeC4KIyMgVGhpcyBqb2JzIGRlcGVuZGVkIG9uOiA2ODU4ODMuY2JjYnNydi51bWlhY3MudW1kLmVkdQojIyBJIGFtIG5vdCBzdXJlIHdoeSBJIGhhdmUgdGhhdCBzbGVlcC4uLgpta2RpciAtcCBvdXRwdXRzL2thbGxpc3RvX2hzYXBpZW5zICYmIHNsZWVwIDEwICYmIFwKa2FsbGlzdG8gcXVhbnQgLS1wbGFpbnRleHQgLXQgNCAtYiAxMDAgLW8gb3V0cHV0cy9rYWxsaXN0b19oc2FwaWVucyAtaSAvY2JjYmhvbWVzL2FiZWxldy9saWJyYXJpZXMvZ2Vub21lL2luZGV4ZXMvaHNhcGllbnMuaWR4IFwKICBIUEdMMDI0MV9SMV9maWx0ZXJlZF9hZGFwdGVydHJpbS5mYXN0cS54eiBIUEdMMDI0MV9SMl9maWx0ZXJlZF9hZGFwdGVydHJpbS5mYXN0cSAyPm91dHB1dHMva2FsbGlzdG8vSFBHTDAyNDFfUjFfZmlsdGVyZWRfYWRhcHRlcnRyaW0uZmFzdHEueHo6SFBHTDAyNDFfUjJfZmlsdGVyZWRfYWRhcHRlcnRyaW0ta2FsbGlzdG8uZXJyIDE+b3V0cHV0cy9rYWxsaXN0by9IUEdMMDI0MV9SMV9maWx0ZXJlZF9hZGFwdGVydHJpbS5mYXN0cS54ejpIUEdMMDI0MV9SMl9maWx0ZXJlZF9hZGFwdGVydHJpbS1rYWxsaXN0by5vdXQKYGBgCgpbaW5kZXguaHRtbF0oaW5kZXguaHRtbCkK