Purpose
This pipeline is intended to:
- trim and align paired-end RNAseq reads with UMIs (presumably produced by Lexogen CORALL library prep kit)
- deduplicate reads using UMIs
- calculate UMI duplication and rRNA contamination
- calculate unnormalized read coverage per feature for all samples (intended for use in DESeq2 analysis)
As the lab is beginning to shift towards running many of these libraries a simple python script was produced to automate much of the repetition in this process.
Requirements
This document assumes you ran paired-end RNAseq with UMIs and have access to the FASTQ files.
This document heavily focuses on using a small python script called Windchime to handle sbatch shell generation. When ran it will generate two sbatch shell scripts. The first script will align reads using STAR and deduplicate reads using UMI-tools. The second sbatch shell script uses bedtools genomecov to calculate read coverage for each genome feature.
Step zero - Set up environment
UMI-Tools For UMI-tools you will need to activate a python 3.8 environment with UMI-tools installed:
conda create -n umi_tools python=3.8
conda activate umi_tools
conda install -c bioconda umi_tools
Windchime You will also need the windchime script which is available here:
git clone https://github.com/pspealman/windchime.git
cd windchime
pwd
This is a standalone script which requires only the standard python (3.6+) packages. You can always use it by pointing to the directory printed out above or by copying the script into a preferred folder.
srun Steps 3, 4, and 6 can consume significant computational resources in order to preserve these resources on the login nodes you should enter an interactive session on a computational node using srun.
srun -c 1 -t 12:00:00 --mem 100000 --pty /bin/bash
NB these srun parameters may need to be modified for smaller or larger datasets. If you complete steps 3,4, and 6 you can close your session by typing exit
Step one - Setup configuration File
Windchime uses a tab delimited configuration file to define necessary parameters and samples for the run. These come in two varieties: samples with replicates (Table 1) and without (Table 2).
Each table requires the same kinds of run parameters (noted as ‘meta’ in column 1). Lines can be commented out by using a hash ‘#’ character at the start of the line.
set_name - user defined name
data_dir - where the fastq files are stored
work_dir - where the temporary and run files are stored
output_dir - where the final results are output
genome_fa - reference fasta file (you may need to copy it locally for indexing issues)
genome_features - either GFF, GFF3, or GTF format file
intron_max - size in nucleotides of maximum intron
adapter_seq_R1, adapter_seq_R2 - read 1 and read 2 adapter sequences
prefix - run id, usually supplied by the sequencing core (eg. HGG…, HGK…, etc.)
fastq_name_template - since the files generated by genore have all kinds of file name conventions there may be several ways your fastq files incorporate the information of the run id (prefix), strain or sample (strain) and replicate (replicate). This line allows you to set these parameters using a simple formatting option using curly brackets containing the keywords ‘prefix’, ‘strain’, or replicate (if you are using the replicate format).
qc_locus - locus coordinates for calculation of rRNA contamination (eg. chromosome:start-stop)
for Saccharomyces cerevisiae S288C R64: XII:451439-468985
for Candida albicans SC 5314 A22: Ca22chrRA_C_albicans_SC5314:1891108-1896912
sample - unique sample name (if replicates are being used the sample name and replicate ID combined must be unique)
Table 1 - Example of configuration file for samples with replicates
#data_type variable value
meta set_name Project_Windchime_HGG72DRXY
meta data_dir /scratch/cgsb/gencore/out/Gresham/2021-08-09_HGG72DRXY/merged/
meta work_dir /scratch/cgsb/gresham/LABSHARE/Data/HGG72DRXY/
meta output_dir /scratch/cgsb/gresham/LABSHARE/Data/HGG72DRXY/results/
meta genome_fa /scratch/cgsb/gresham/pieter/genome/ensembl_50/Saccharomyces_cerevisiae.R64-1-1.dna.toplevel.fa
meta genome_features /scratch/cgsb/gresham/pieter/genome/Saccharomyces_cerevisiae.R64-1-1.dna.toplevel.gtf
meta intron_max 100
meta adapter_seq_R1 AGATCGGAAGAGCACACGTCTGAACTCCAGTCA
meta adapter_seq_R2 AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT
meta prefix HGG72DRXY
meta fastq_name_template {prefix}_n01_{strain}_{replicate}
meta qc_locus XII:451439-468985
sample 1 1
sample 1 2
sample 1 3
sample 1222 1
sample 1222 2
sample 1222 3
Table 2 - Example of configuration file for samples without replicates
#data_type variable value
meta set_name Project_CAlbicans
meta data_dir /scratch/cgsb/gencore/out/Gresham/2021-10-25_HK7CCDRXY/merged/
meta work_dir /scratch/cgsb/gresham/LABSHARE/Data/HK7CCDRXY/
meta output_dir /scratch/cgsb/gresham/LABSHARE/Data/HK7CCDRXY/results/
meta genome_fa /scratch/cgsb/gresham/pieter/genome/Candida_albicans_sc5314/C_albicans_SC5314_A22_current_chromosomes.fasta
meta genome_features /scratch/cgsb/gresham/pieter/genome/Candida_albicans_sc5314/C_albicans_SC5314_A22_current_features.gff
meta intron_max 500
meta adapter_seq_R1 AGATCGGAAGAGCACACGTCTGAACTCCAGTCA
meta adapter_seq_R2 AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT
meta prefix HK7CCDRXY
meta fastq_name_template {prefix}_n01_{strain}
meta qc_locus Ca22chrRA_C_albicans_SC5314:1891108-1896912
sample CAWT1_C-LIM_2H
sample CAWT1_C-LIM_5H
Step two - Make STAR alignment sbatch file
python windchime.py -a -i cfg_file.tab -o run_windchime_star.sh
# -a 'alignment' flag
# [optional] -rep flag, include if you ar using replicates
# [optional] -mem flag, set sbatch memory allocation in GB. (Default 60GB)
# -i input configuration file name
# -o output STAR sbatch file name
sbatch run_windchime_star.sh
- The above code will generate a bash script “run_windchime_star.sh” using the information given in the -i input configuration file. If being used with replicates include the -rep flag
Step four - Calculate sequence rarefaction
python windchime.py -r -i ctrl_file.tab
# -r 'rarefaction' flag
# [optional] -rep flag, include if you ar using replicates
# [optional] -tol parameter, allows you to specify the percent tolerance point (default 50)
# -i input configuration file name
- The above code will perform a rarefaction calculation using the combination of UMI an aligned sequence. All rarefaction is calculated using random downsampling.
- This command will produce rarefaction curves saved as .pdf files in the output_dir directory specified in the configuration file.

- The plot will show both the ideal case (red, dashed line), the observed case (blue solid curve), and the approximate tolerance point if present (black solid lines).
- The tolerance point, by default 50%, is the point at which the rate of adding a novel sequence drops below 50% (this can be changed by using the -tol parameter). In the above example, a 75% tolerance point is crossed very early in the run (~0.7e8 reads).
Step five - Calculate coverage of aligned reads to genome features
python windchime.py -c -i cfg_file.tab -o coverage_run.sh
# -c 'coverage' flag
# [optional] -rep flag, include if you ar using replicates
# [optional] -mem flag, set sbatch memory allocation in GB. (Default 60GB)
# -i input configuration file name
# -o output coverage sbatch file name
sbatch coverage_run.sh
- The above code will generate a bash script “coverage_run.sh” using the information given in the -i input configuration file.
- Coverage is calculated using bedtools -genomecoverage command with default settings. The feature file specified by ‘genome_features’ in the configuration file will be used for all calculations.
Step six - combine feature coverage counts into a single table
python windchime.py -t -i cfg_file.tab -o coverage_table.txt
# -t 'table' flag
# [optional] -rep flag, include if you ar using replicates
# -i input configuration file name
# -o output combined coverage table file name
This will produce a tab-delimited file where columns are the sample identifier and rows are the feature (eg. gene) name. All values are uncorrected, unnormalized, deduplicated reads. Both paired reads must be 100% within the same feature in order to be counted. This table is compatible with downstream analysis by DESeq2
gene DGY1-1 DGY1-2 DGY1-3 ...
YAL001C 737 894 677
YAL002W 825 1067 878
YAL003W 4268 4369 6463
...
Conclusion
After a successful run you should have the following files:
- In the configuration specified output directory (eg. output_dir):
- Aligned, sorted, indexed bam files
- Rarefaction curve plots
- Raw coverage count files
- Command line specified locations (eg. -o):
- Quality control evaluation
- Combined coverage table
LS0tDQp0aXRsZTogIldpbmRjaGltZSBwaXBlbGluZSINCmF1dGhvcjogIlBpZXRlciBTcGVhbG1hbiINCmRhdGU6ICIxMS8yMS8yMDIxIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQoNCmBgYA0KIyMjIyBQdXJwb3NlDQpUaGlzIHBpcGVsaW5lIGlzIGludGVuZGVkIHRvOiANCg0KKiB0cmltIGFuZCBhbGlnbiBwYWlyZWQtZW5kIFJOQXNlcSByZWFkcyB3aXRoIFVNSXMgKHByZXN1bWFibHkgcHJvZHVjZWQgYnkgTGV4b2dlbiBDT1JBTEwgbGlicmFyeSBwcmVwIGtpdCkNCiogZGVkdXBsaWNhdGUgcmVhZHMgdXNpbmcgVU1Jcw0KKiBjYWxjdWxhdGUgVU1JIGR1cGxpY2F0aW9uIGFuZCByUk5BIGNvbnRhbWluYXRpb24NCiogY2FsY3VsYXRlIHVubm9ybWFsaXplZCByZWFkIGNvdmVyYWdlIHBlciBmZWF0dXJlIGZvciBhbGwgc2FtcGxlcyAoaW50ZW5kZWQgZm9yIHVzZSBpbiBERVNlcTIgYW5hbHlzaXMpIA0KDQpBcyB0aGUgbGFiIGlzIGJlZ2lubmluZyB0byBzaGlmdCB0b3dhcmRzIHJ1bm5pbmcgbWFueSBvZiB0aGVzZSBsaWJyYXJpZXMgYSBzaW1wbGUgcHl0aG9uIHNjcmlwdCB3YXMgcHJvZHVjZWQgdG8gYXV0b21hdGUgbXVjaCBvZiB0aGUgcmVwZXRpdGlvbiBpbiB0aGlzIHByb2Nlc3MuDQoNCiMjIyMgUmVxdWlyZW1lbnRzDQpUaGlzIGRvY3VtZW50IGFzc3VtZXMgeW91IHJhbiBwYWlyZWQtZW5kIFJOQXNlcSB3aXRoIFVNSXMgYW5kIGhhdmUgYWNjZXNzIHRvIHRoZSBGQVNUUSBmaWxlcy4gDQoNClRoaXMgZG9jdW1lbnQgaGVhdmlseSBmb2N1c2VzIG9uIHVzaW5nIGEgc21hbGwgcHl0aG9uIHNjcmlwdCBjYWxsZWQgV2luZGNoaW1lIHRvIGhhbmRsZSBzYmF0Y2ggc2hlbGwgZ2VuZXJhdGlvbi4gV2hlbiByYW4gaXQgd2lsbCBnZW5lcmF0ZSB0d28gc2JhdGNoIHNoZWxsIHNjcmlwdHMuIFRoZSBmaXJzdCBzY3JpcHQgd2lsbCBhbGlnbiByZWFkcyB1c2luZyBTVEFSIGFuZCBkZWR1cGxpY2F0ZSByZWFkcyB1c2luZyBVTUktdG9vbHMuIFRoZSBzZWNvbmQgc2JhdGNoIHNoZWxsIHNjcmlwdCB1c2VzIGJlZHRvb2xzIGdlbm9tZWNvdiB0byBjYWxjdWxhdGUgcmVhZCBjb3ZlcmFnZSBmb3IgZWFjaCBnZW5vbWUgZmVhdHVyZS4gDQoNCiMjIyMgU3RlcCB6ZXJvIC0gU2V0IHVwIGVudmlyb25tZW50DQoqIF9fVU1JLVRvb2xzX18gRm9yIFVNSS10b29scyB5b3Ugd2lsbCBuZWVkIHRvIGFjdGl2YXRlIGEgcHl0aG9uIDMuOCBlbnZpcm9ubWVudCB3aXRoIFVNSS10b29scyBpbnN0YWxsZWQ6DQogIGBgYA0KICBjb25kYSBjcmVhdGUgLW4gdW1pX3Rvb2xzIHB5dGhvbj0zLjgNCiAgY29uZGEgYWN0aXZhdGUgdW1pX3Rvb2xzDQogIGNvbmRhIGluc3RhbGwgLWMgYmlvY29uZGEgdW1pX3Rvb2xzDQogIGBgYA0KDQoqIF9fV2luZGNoaW1lX18gWW91IHdpbGwgYWxzbyBuZWVkIHRoZSB3aW5kY2hpbWUgc2NyaXB0IHdoaWNoIGlzIGF2YWlsYWJsZSBoZXJlOg0KICBgYGANCiAgZ2l0IGNsb25lIGh0dHBzOi8vZ2l0aHViLmNvbS9wc3BlYWxtYW4vd2luZGNoaW1lLmdpdA0KICBjZCB3aW5kY2hpbWUNCiAgcHdkDQogIGBgYA0KICBUaGlzIGlzIGEgc3RhbmRhbG9uZSBzY3JpcHQgd2hpY2ggcmVxdWlyZXMgb25seSB0aGUgc3RhbmRhcmQgcHl0aG9uICgzLjYrKSBwYWNrYWdlcy4gWW91IGNhbiBhbHdheXMgdXNlIGl0IGJ5IHBvaW50aW5nIHRvIHRoZSBkaXJlY3RvcnkgcHJpbnRlZCBvdXQgYWJvdmUgb3IgYnkgY29weWluZyB0aGUgc2NyaXB0IGludG8gYSBwcmVmZXJyZWQgZm9sZGVyLiANCg0KKiBfX3NydW5fXyBTdGVwcyAzLCA0LCBhbmQgNiBjYW4gY29uc3VtZSBzaWduaWZpY2FudCBjb21wdXRhdGlvbmFsIHJlc291cmNlcyBpbiBvcmRlciB0byBwcmVzZXJ2ZSB0aGVzZSByZXNvdXJjZXMgb24gdGhlIGxvZ2luIG5vZGVzIHlvdSBzaG91bGQgZW50ZXIgYW4gaW50ZXJhY3RpdmUgc2Vzc2lvbiBvbiBhIGNvbXB1dGF0aW9uYWwgbm9kZSB1c2luZyBzcnVuLiANCiAgYGBgDQogIHNydW4gLWMgMSAtdCAxMjowMDowMCAtLW1lbSAxMDAwMDAgLS1wdHkgL2Jpbi9iYXNoDQogIGBgYA0KICBfX05CX18gdGhlc2Ugc3J1biBwYXJhbWV0ZXJzIG1heSBuZWVkIHRvIGJlIG1vZGlmaWVkIGZvciBzbWFsbGVyIG9yIGxhcmdlciBkYXRhc2V0cy4gSWYgeW91IGNvbXBsZXRlIHN0ZXBzIDMsNCwgYW5kIDYgeW91IGNhbiBjbG9zZSB5b3VyIHNlc3Npb24gYnkgdHlwaW5nIGBgYGV4aXRgYGANCg0KIyMjIyBTdGVwIG9uZSAtIFNldHVwIGNvbmZpZ3VyYXRpb24gRmlsZQ0KDQpXaW5kY2hpbWUgdXNlcyBhIF9fdGFiIGRlbGltaXRlZF9fIGNvbmZpZ3VyYXRpb24gZmlsZSB0byBkZWZpbmUgbmVjZXNzYXJ5IHBhcmFtZXRlcnMgYW5kIHNhbXBsZXMgZm9yIHRoZSBydW4uIFRoZXNlIGNvbWUgaW4gdHdvIHZhcmlldGllczogc2FtcGxlcyB3aXRoIHJlcGxpY2F0ZXMgKFRhYmxlIDEpIGFuZCB3aXRob3V0IChUYWJsZSAyKS4gDQoNCkVhY2ggdGFibGUgcmVxdWlyZXMgdGhlIHNhbWUga2luZHMgb2YgcnVuIHBhcmFtZXRlcnMgKG5vdGVkIGFzICdtZXRhJyBpbiBjb2x1bW4gMSkuIExpbmVzIGNhbiBiZSBjb21tZW50ZWQgb3V0IGJ5IHVzaW5nIGEgaGFzaCAnIycgY2hhcmFjdGVyIGF0IHRoZSBzdGFydCBvZiB0aGUgbGluZS4NCg0KKiBzZXRfbmFtZSAtIHVzZXIgZGVmaW5lZCBuYW1lDQoqIGRhdGFfZGlyIC0gd2hlcmUgdGhlIGZhc3RxIGZpbGVzIGFyZSBzdG9yZWQNCiogd29ya19kaXIgLSB3aGVyZSB0aGUgdGVtcG9yYXJ5IGFuZCBydW4gZmlsZXMgYXJlIHN0b3JlZA0KKiBvdXRwdXRfZGlyIC0gd2hlcmUgdGhlIGZpbmFsIHJlc3VsdHMgYXJlIG91dHB1dA0KKiBnZW5vbWVfZmEgLSByZWZlcmVuY2UgZmFzdGEgZmlsZSAoeW91IG1heSBuZWVkIHRvIGNvcHkgaXQgbG9jYWxseSBmb3IgaW5kZXhpbmcgaXNzdWVzKQ0KKiBnZW5vbWVfZmVhdHVyZXMgLSBlaXRoZXIgR0ZGLCBHRkYzLCBvciBHVEYgZm9ybWF0IGZpbGUNCiogaW50cm9uX21heCAtIHNpemUgaW4gbnVjbGVvdGlkZXMgb2YgbWF4aW11bSBpbnRyb24NCiogYWRhcHRlcl9zZXFfUjEsIGFkYXB0ZXJfc2VxX1IyIC0gcmVhZCAxIGFuZCByZWFkIDIgYWRhcHRlciBzZXF1ZW5jZXMNCiogcHJlZml4IC0gcnVuIGlkLCB1c3VhbGx5IHN1cHBsaWVkIGJ5IHRoZSBzZXF1ZW5jaW5nIGNvcmUgKGVnLiBIR0cuLi4sIEhHSy4uLiwgZXRjLikNCiogZmFzdHFfbmFtZV90ZW1wbGF0ZSAtIHNpbmNlIHRoZSBmaWxlcyBnZW5lcmF0ZWQgYnkgZ2Vub3JlIGhhdmUgYWxsIGtpbmRzIG9mIGZpbGUgbmFtZSBjb252ZW50aW9ucyB0aGVyZSBtYXkgYmUgc2V2ZXJhbCB3YXlzIHlvdXIgZmFzdHEgZmlsZXMgaW5jb3Jwb3JhdGUgdGhlIGluZm9ybWF0aW9uIG9mIHRoZSBydW4gaWQgKHByZWZpeCksIHN0cmFpbiBvciBzYW1wbGUgKHN0cmFpbikgYW5kIHJlcGxpY2F0ZSAocmVwbGljYXRlKS4gVGhpcyBsaW5lIGFsbG93cyB5b3UgdG8gc2V0IHRoZXNlIHBhcmFtZXRlcnMgdXNpbmcgYSBzaW1wbGUgZm9ybWF0dGluZyBvcHRpb24gdXNpbmcgY3VybHkgYnJhY2tldHMgY29udGFpbmluZyB0aGUga2V5d29yZHMgJ3ByZWZpeCcsICdzdHJhaW4nLCBvciByZXBsaWNhdGUgKGlmIHlvdSBhcmUgdXNpbmcgdGhlIHJlcGxpY2F0ZSBmb3JtYXQpLiANCiogcWNfbG9jdXMgLSBsb2N1cyBjb29yZGluYXRlcyBmb3IgY2FsY3VsYXRpb24gb2YgclJOQSBjb250YW1pbmF0aW9uIChlZy4gY2hyb21vc29tZTpzdGFydC1zdG9wKQ0KIA0KICBgYGANCiAgZm9yIFNhY2NoYXJvbXljZXMgY2VyZXZpc2lhZSBTMjg4QyBSNjQ6IFhJSTo0NTE0MzktNDY4OTg1DQogIGZvciBDYW5kaWRhIGFsYmljYW5zIFNDIDUzMTQgQTIyOiBDYTIyY2hyUkFfQ19hbGJpY2Fuc19TQzUzMTQ6MTg5MTEwOC0xODk2OTEyDQogIGBgYA0KKiBzYW1wbGUgLSB1bmlxdWUgc2FtcGxlIG5hbWUgKGlmIHJlcGxpY2F0ZXMgYXJlIGJlaW5nIHVzZWQgdGhlIHNhbXBsZSBuYW1lIGFuZCByZXBsaWNhdGUgSUQgY29tYmluZWQgbXVzdCBiZSB1bmlxdWUpDQogDQojIyMjIFRhYmxlIDEgLSBFeGFtcGxlIG9mIGNvbmZpZ3VyYXRpb24gZmlsZSBmb3Igc2FtcGxlcyB3aXRoIHJlcGxpY2F0ZXMNCmBgYA0KI2RhdGFfdHlwZQl2YXJpYWJsZQl2YWx1ZQ0KbWV0YQlzZXRfbmFtZQlQcm9qZWN0X1dpbmRjaGltZV9IR0c3MkRSWFkNCm1ldGEJZGF0YV9kaXIJL3NjcmF0Y2gvY2dzYi9nZW5jb3JlL291dC9HcmVzaGFtLzIwMjEtMDgtMDlfSEdHNzJEUlhZL21lcmdlZC8NCm1ldGEJd29ya19kaXIJL3NjcmF0Y2gvY2dzYi9ncmVzaGFtL0xBQlNIQVJFL0RhdGEvSEdHNzJEUlhZLw0KbWV0YQlvdXRwdXRfZGlyCS9zY3JhdGNoL2Nnc2IvZ3Jlc2hhbS9MQUJTSEFSRS9EYXRhL0hHRzcyRFJYWS9yZXN1bHRzLw0KbWV0YQlnZW5vbWVfZmEJL3NjcmF0Y2gvY2dzYi9ncmVzaGFtL3BpZXRlci9nZW5vbWUvZW5zZW1ibF81MC9TYWNjaGFyb215Y2VzX2NlcmV2aXNpYWUuUjY0LTEtMS5kbmEudG9wbGV2ZWwuZmENCm1ldGEJZ2Vub21lX2ZlYXR1cmVzCS9zY3JhdGNoL2Nnc2IvZ3Jlc2hhbS9waWV0ZXIvZ2Vub21lL1NhY2NoYXJvbXljZXNfY2VyZXZpc2lhZS5SNjQtMS0xLmRuYS50b3BsZXZlbC5ndGYNCm1ldGEJaW50cm9uX21heAkxMDANCm1ldGEJYWRhcHRlcl9zZXFfUjEJQUdBVENHR0FBR0FHQ0FDQUNHVENUR0FBQ1RDQ0FHVENBDQptZXRhCWFkYXB0ZXJfc2VxX1IyCUFHQVRDR0dBQUdBR0NHVENHVEdUQUdHR0FBQUdBR1RHVA0KbWV0YQlwcmVmaXgJSEdHNzJEUlhZDQptZXRhCWZhc3RxX25hbWVfdGVtcGxhdGUJe3ByZWZpeH1fbjAxX3tzdHJhaW59X3tyZXBsaWNhdGV9DQptZXRhCXFjX2xvY3VzICBYSUk6NDUxNDM5LTQ2ODk4NQ0Kc2FtcGxlCTEJMQ0Kc2FtcGxlCTEJMg0Kc2FtcGxlCTEJMw0Kc2FtcGxlCTEyMjIJMQ0Kc2FtcGxlCTEyMjIJMg0Kc2FtcGxlCTEyMjIJMw0KYGBgDQoNCiMjIyMgVGFibGUgMiAtIEV4YW1wbGUgb2YgY29uZmlndXJhdGlvbiBmaWxlIGZvciBzYW1wbGVzIHdpdGhvdXQgcmVwbGljYXRlcw0KYGBgDQojZGF0YV90eXBlCXZhcmlhYmxlCXZhbHVlDQptZXRhCXNldF9uYW1lCVByb2plY3RfQ0FsYmljYW5zDQptZXRhCWRhdGFfZGlyCS9zY3JhdGNoL2Nnc2IvZ2VuY29yZS9vdXQvR3Jlc2hhbS8yMDIxLTEwLTI1X0hLN0NDRFJYWS9tZXJnZWQvDQptZXRhCXdvcmtfZGlyCS9zY3JhdGNoL2Nnc2IvZ3Jlc2hhbS9MQUJTSEFSRS9EYXRhL0hLN0NDRFJYWS8NCm1ldGEJb3V0cHV0X2Rpcgkvc2NyYXRjaC9jZ3NiL2dyZXNoYW0vTEFCU0hBUkUvRGF0YS9ISzdDQ0RSWFkvcmVzdWx0cy8NCm1ldGEJZ2Vub21lX2ZhCS9zY3JhdGNoL2Nnc2IvZ3Jlc2hhbS9waWV0ZXIvZ2Vub21lL0NhbmRpZGFfYWxiaWNhbnNfc2M1MzE0L0NfYWxiaWNhbnNfU0M1MzE0X0EyMl9jdXJyZW50X2Nocm9tb3NvbWVzLmZhc3RhDQptZXRhCWdlbm9tZV9mZWF0dXJlcwkvc2NyYXRjaC9jZ3NiL2dyZXNoYW0vcGlldGVyL2dlbm9tZS9DYW5kaWRhX2FsYmljYW5zX3NjNTMxNC9DX2FsYmljYW5zX1NDNTMxNF9BMjJfY3VycmVudF9mZWF0dXJlcy5nZmYNCm1ldGEJaW50cm9uX21heAk1MDANCm1ldGEJYWRhcHRlcl9zZXFfUjEJQUdBVENHR0FBR0FHQ0FDQUNHVENUR0FBQ1RDQ0FHVENBDQptZXRhCWFkYXB0ZXJfc2VxX1IyCUFHQVRDR0dBQUdBR0NHVENHVEdUQUdHR0FBQUdBR1RHVA0KbWV0YQlwcmVmaXgJSEs3Q0NEUlhZDQptZXRhCWZhc3RxX25hbWVfdGVtcGxhdGUJe3ByZWZpeH1fbjAxX3tzdHJhaW59DQptZXRhCXFjX2xvY3VzCUNhMjJjaHJSQV9DX2FsYmljYW5zX1NDNTMxNDoxODkxMTA4LTE4OTY5MTINCnNhbXBsZQlDQVdUMV9DLUxJTV8ySA0Kc2FtcGxlCUNBV1QxX0MtTElNXzVIDQpgYGANCiMjIyMgU3RlcCB0d28gLSBNYWtlIFNUQVIgYWxpZ25tZW50IHNiYXRjaCBmaWxlDQpgYGANCnB5dGhvbiB3aW5kY2hpbWUucHkgLWEgLWkgY2ZnX2ZpbGUudGFiIC1vIHJ1bl93aW5kY2hpbWVfc3Rhci5zaA0KIyAtYSAnYWxpZ25tZW50JyBmbGFnDQojIFtvcHRpb25hbF0gLXJlcCBmbGFnLCBpbmNsdWRlIGlmIHlvdSBhciB1c2luZyByZXBsaWNhdGVzDQojIFtvcHRpb25hbF0gLW1lbSBmbGFnLCBzZXQgc2JhdGNoIG1lbW9yeSBhbGxvY2F0aW9uIGluIEdCLiAoRGVmYXVsdCA2MEdCKQ0KIyAtaSBpbnB1dCBjb25maWd1cmF0aW9uIGZpbGUgbmFtZQ0KIyAtbyBvdXRwdXQgU1RBUiBzYmF0Y2ggZmlsZSBuYW1lDQoNCnNiYXRjaCBydW5fd2luZGNoaW1lX3N0YXIuc2gNCmBgYA0KKiBUaGUgYWJvdmUgY29kZSB3aWxsIGdlbmVyYXRlIGEgX19iYXNoIHNjcmlwdCAicnVuX3dpbmRjaGltZV9zdGFyLnNoIl9fIHVzaW5nIHRoZSBpbmZvcm1hdGlvbiBnaXZlbiBpbiB0aGUgX18taV9fIGlucHV0IGNvbmZpZ3VyYXRpb24gZmlsZS4gX0lmIGJlaW5nIHVzZWQgd2l0aCByZXBsaWNhdGVzIGluY2x1ZGUgdGhlIC1yZXAgZmxhZ18NCg0KDQojIyMjIFN0ZXAgdGhyZWUgLSBFdmFsdWF0ZSBzdW1tYXJ5IHBlcmZvcm1hbmNlIHN0YXRpc3RpY3MNCmBgYA0KcHl0aG9uIHdpbmRjaGltZS5weSAtZSAtaSBjZmdfZmlsZS50YWIgLW8gZXZhbHVhdGVfcnVuLnR4dA0KIyAtZSAnZXZhbHVhdGUnIGZsYWcNCiMgW29wdGlvbmFsXSAtcmVwIGZsYWcsIGluY2x1ZGUgaWYgeW91IGFyIHVzaW5nIHJlcGxpY2F0ZXMNCiMgLWkgaW5wdXQgY29uZmlndXJhdGlvbiBmaWxlIG5hbWUNCiMgLW8gb3V0cHV0IGV2YWx1YXRpb24gc3RhdGlzdGljcyBmaWxlIG5hbWUNCmBgYA0KKiBUaGUgYWJvdmUgY29kZSB3aWxsIGNvbXBpbGUgdGhlIHFjIHN0YXRzIGdlbmVyYXRlZCBkdXJpbmcgX19zdGVwIHR3b19fIGFuZCBvdXRwdXQgdGhlbSBpbnRvIGEgdGFiIGRlbGltaXRlZCBzdW1tYXJ5IGZpbGUuDQoNCiogVGhpcyB3aWxsIG91dHB1dCBhIHRhYiBkZWxpbWl0ZWQgZmlsZSB3aXRoIHRoZSBmb2xsb3dpbmcgY29sdW1uczoNCiAgYGBgDQogIFN0cmFpbiAgUmVwbGljYXRlICBUb3RhbF9yZWFkcyAgVU1JX3VuaXF1ZV9yZWFkcyAgVU1JX3VuaXF1ZV9wY3QgIFFDX2xvY3VzX3JlYWRzICBRQ19sb2N1c19wY3QNCiAgREdZMSAgICAxICAgMzA5MDg4MzggICAgMTMwMzU3MTMgICAgMC40MjE3NDcxMDcgICA2MDA2Mzg5ICAgMC40NjA3NjQxMzMNCiAgREdZMSAgICAyICAgMzEyNzMxNDIgICAgMTMxNjY4MTEgICAgMC40MjEwMjYxNjQgICA0MjQ2NzI4ICAgMC4zMjI1MzI3NjgNCiAgLi4uDQogIGBgYA0KKiBVTUlfdW5pcXVlX3JlYWRzIGFyZSBjYWxjdWxhdGVkIGFmdGVyIGRlZHVwbGljYXRpb24gdXNpbmcgVU1JLXRvb2xzLCB0aGV5IHJlcHJlc2VudCB0aGUgX191bmlxdWUgcmVhZHNfXy4NCiogVU1JX3VuaXF1ZV9wY3QgaXMgKFVNSV91bmlxdWVfcmVhZHMgLyBUb3RhbF9yZWFkcykgKiAxMDANCiogUUNfbG9jdXNfcmVhZHMgYXJlIGNhbGN1bGF0ZWQgZnJvbSB0aGUgdW5pcXVlIHJlYWRzIGFsaWduZWQgdG8gdGhlIFFDX2xvY3VzIGRlZmluZWQgaW4gdGhlIGNvbmZpZ3VyYXRpb24gZmlsZSAoU3RlcCBvbmUpDQoqIFFDX2xvY3VzX3BjdCBpcyAoUUNfbG9jdXNfcmVhZHMgLyBVTUlfdW5pcXVlX3JlYWRzKSAqIDEwMA0KDQojIyMjIFN0ZXAgZm91ciAtIENhbGN1bGF0ZSBzZXF1ZW5jZSByYXJlZmFjdGlvbg0KYGBgDQpweXRob24gd2luZGNoaW1lLnB5IC1yIC1pIGN0cmxfZmlsZS50YWINCiMgLXIgJ3JhcmVmYWN0aW9uJyBmbGFnDQojIFtvcHRpb25hbF0gLXJlcCBmbGFnLCBpbmNsdWRlIGlmIHlvdSBhciB1c2luZyByZXBsaWNhdGVzDQojIFtvcHRpb25hbF0gLXRvbCBwYXJhbWV0ZXIsIGFsbG93cyB5b3UgdG8gc3BlY2lmeSB0aGUgcGVyY2VudCB0b2xlcmFuY2UgcG9pbnQgKGRlZmF1bHQgNTApDQojIC1pIGlucHV0IGNvbmZpZ3VyYXRpb24gZmlsZSBuYW1lDQpgYGANCiogVGhlIGFib3ZlIGNvZGUgd2lsbCBwZXJmb3JtIGEgcmFyZWZhY3Rpb24gY2FsY3VsYXRpb24gdXNpbmcgdGhlIGNvbWJpbmF0aW9uIG9mDQpVTUkgYW4gYWxpZ25lZCBzZXF1ZW5jZS4gQWxsIHJhcmVmYWN0aW9uIGlzIGNhbGN1bGF0ZWQgdXNpbmcgcmFuZG9tIGRvd25zYW1wbGluZy4gDQoqIFRoaXMgY29tbWFuZCB3aWxsIHByb2R1Y2UgcmFyZWZhY3Rpb24gY3VydmVzIHNhdmVkIGFzIC5wZGYgZmlsZXMgaW4gdGhlIF9fb3V0cHV0X2Rpcl9fIGRpcmVjdG9yeSBzcGVjaWZpZWQgaW4gdGhlIGNvbmZpZ3VyYXRpb24gZmlsZS4NCiFbUmFyZWZhY3Rpb24gY3VydmVdKGltYWdlcy9leGFtcGxlLnBuZykNCiogVGhlIHBsb3Qgd2lsbCBzaG93IGJvdGggdGhlIF9faWRlYWwgY2FzZV9fIChyZWQsIGRhc2hlZCBsaW5lKSwgdGhlIF9fb2JzZXJ2ZWQgY2FzZV9fIChibHVlIHNvbGlkIGN1cnZlKSwgYW5kIHRoZSBhcHByb3hpbWF0ZSBfX3RvbGVyYW5jZSBwb2ludF9fIGlmIHByZXNlbnQgKGJsYWNrIHNvbGlkIGxpbmVzKS4gDQoqIFRoZSB0b2xlcmFuY2UgcG9pbnQsIGJ5IGRlZmF1bHQgNTAlLCBpcyB0aGUgcG9pbnQgYXQgd2hpY2ggdGhlIHJhdGUgb2YgYWRkaW5nIGEgbm92ZWwgc2VxdWVuY2UgZHJvcHMgYmVsb3cgNTAlICh0aGlzIGNhbiBiZSBjaGFuZ2VkIGJ5IHVzaW5nIHRoZSBfXy10b2xfXyBwYXJhbWV0ZXIpLiBJbiB0aGUgYWJvdmUgZXhhbXBsZSwgYSA3NSUgdG9sZXJhbmNlIHBvaW50IGlzIGNyb3NzZWQgdmVyeSBlYXJseSBpbiB0aGUgcnVuICh+MC43ZTggcmVhZHMpLiANCg0KIyMjIyBTdGVwIGZpdmUgLSBDYWxjdWxhdGUgY292ZXJhZ2Ugb2YgYWxpZ25lZCByZWFkcyB0byBnZW5vbWUgZmVhdHVyZXMNCmBgYA0KcHl0aG9uIHdpbmRjaGltZS5weSAtYyAtaSBjZmdfZmlsZS50YWIgLW8gY292ZXJhZ2VfcnVuLnNoDQojIC1jICdjb3ZlcmFnZScgZmxhZw0KIyBbb3B0aW9uYWxdIC1yZXAgZmxhZywgaW5jbHVkZSBpZiB5b3UgYXIgdXNpbmcgcmVwbGljYXRlcw0KIyBbb3B0aW9uYWxdIC1tZW0gZmxhZywgc2V0IHNiYXRjaCBtZW1vcnkgYWxsb2NhdGlvbiBpbiBHQi4gKERlZmF1bHQgNjBHQikNCiMgLWkgaW5wdXQgY29uZmlndXJhdGlvbiBmaWxlIG5hbWUNCiMgLW8gb3V0cHV0IGNvdmVyYWdlIHNiYXRjaCBmaWxlIG5hbWUNCg0Kc2JhdGNoIGNvdmVyYWdlX3J1bi5zaA0KYGBgDQoqIFRoZSBhYm92ZSBjb2RlIHdpbGwgZ2VuZXJhdGUgYSBfX2Jhc2ggc2NyaXB0ICJjb3ZlcmFnZV9ydW4uc2giX18gdXNpbmcgdGhlIGluZm9ybWF0aW9uIGdpdmVuIGluIHRoZSBfXy1pX18gaW5wdXQgY29uZmlndXJhdGlvbiBmaWxlLg0KKiBDb3ZlcmFnZSBpcyBjYWxjdWxhdGVkIHVzaW5nIF9fYmVkdG9vbHMgLWdlbm9tZWNvdmVyYWdlX18gY29tbWFuZCB3aXRoIGRlZmF1bHQgc2V0dGluZ3MuIFRoZSBmZWF0dXJlIGZpbGUgc3BlY2lmaWVkIGJ5IF9fJ2dlbm9tZV9mZWF0dXJlcydfXyBpbiB0aGUgY29uZmlndXJhdGlvbiBmaWxlIHdpbGwgYmUgdXNlZCBmb3IgYWxsIGNhbGN1bGF0aW9ucy4NCg0KIyMjIyBTdGVwIHNpeCAtIGNvbWJpbmUgZmVhdHVyZSBjb3ZlcmFnZSBjb3VudHMgaW50byBhIHNpbmdsZSB0YWJsZQ0KYGBgDQpweXRob24gd2luZGNoaW1lLnB5IC10IC1pIGNmZ19maWxlLnRhYiAtbyBjb3ZlcmFnZV90YWJsZS50eHQNCiMgLXQgJ3RhYmxlJyBmbGFnDQojIFtvcHRpb25hbF0gLXJlcCBmbGFnLCBpbmNsdWRlIGlmIHlvdSBhciB1c2luZyByZXBsaWNhdGVzDQojIC1pIGlucHV0IGNvbmZpZ3VyYXRpb24gZmlsZSBuYW1lDQojIC1vIG91dHB1dCBjb21iaW5lZCBjb3ZlcmFnZSB0YWJsZSBmaWxlIG5hbWUNCmBgYA0KDQoqIFRoaXMgd2lsbCBwcm9kdWNlIGEgdGFiLWRlbGltaXRlZCBmaWxlIHdoZXJlIGNvbHVtbnMgYXJlIHRoZSBzYW1wbGUgaWRlbnRpZmllciBhbmQgcm93cyBhcmUgdGhlIGZlYXR1cmUgKGVnLiBnZW5lKSBuYW1lLiAgIEFsbCB2YWx1ZXMgYXJlIHVuY29ycmVjdGVkLCB1bm5vcm1hbGl6ZWQsIGRlZHVwbGljYXRlZCByZWFkcy4gQm90aCBwYWlyZWQgcmVhZHMgbXVzdCBiZSAxMDAlIHdpdGhpbiB0aGUgc2FtZSBmZWF0dXJlIGluIG9yZGVyIHRvIGJlIGNvdW50ZWQuIFRoaXMgdGFibGUgaXMgY29tcGF0aWJsZSB3aXRoIGRvd25zdHJlYW0gYW5hbHlzaXMgYnkgREVTZXEyDQoNCiAgYGBgDQogIGdlbmUJREdZMS0xCURHWTEtMglER1kxLTMgICAgLi4uDQogIFlBTDAwMUMJNzM3CTg5NAk2NzcNCiAgWUFMMDAyVwk4MjUJMTA2Nwk4NzgNCiAgWUFMMDAzVwk0MjY4CTQzNjkJNjQ2Mw0KICAuLi4NCiAgYGBgDQoNCiMjIyMgQ29uY2x1c2lvbiANCkFmdGVyIGEgc3VjY2Vzc2Z1bCBydW4geW91IHNob3VsZCBoYXZlIHRoZSBmb2xsb3dpbmcgZmlsZXM6DQoNCiogSW4gdGhlIGNvbmZpZ3VyYXRpb24gc3BlY2lmaWVkIG91dHB1dCBkaXJlY3RvcnkgKGVnLiBfX291dHB1dF9kaXJfXyk6DQogICsgQWxpZ25lZCwgc29ydGVkLCBpbmRleGVkIGJhbSBmaWxlcw0KICArIFJhcmVmYWN0aW9uIGN1cnZlIHBsb3RzDQogICsgUmF3IGNvdmVyYWdlIGNvdW50IGZpbGVzDQoNCiogQ29tbWFuZCBsaW5lIHNwZWNpZmllZCBsb2NhdGlvbnMgKGVnLiBfXy1vX18pOg0KICArIFF1YWxpdHkgY29udHJvbCBldmFsdWF0aW9uDQogICsgQ29tYmluZWQgY292ZXJhZ2UgdGFibGUNCg==