In this module, we will learn:
- the concept of splice-aware alignments
- the two steps needed to run RSEM+STAR
- details of SAM and BAM files, and RSEM outputs
Differential Expression Workflow
We’ll discuss the alignment and gene quantification steps which
gather the necessary data that we will need prior to testing for
differential expression, the topic of Day 2.
Alignment and Gene Quantification
The FASTQ files of raw sequenced reads are untethered from any notion
of where they came from in the genome, and which transcribed genes the
sequence belongs to. The alignment and gene quantification steps fill in
that gap and allow us to proceed with the question we are really
interested in: Which genes are differentially expressed between groups
of samples?
We will use RSEM (paper
and GitHub) combined with
STAR Aligner (paper
and GitHub) to
accomplish the task of read mapping and gene quantifcation
simultaneously.
STAR
The “Spliced Transcripts Alignment to a Reference” (STAR) Aligner is
aware of splice-sites of transcripts and is able to align reads that
span them. The figure below illustrates the difference between
splice-unaware aligners (e.g. Bowtie2) and splice-aware aligners
(e.g. STAR).
Some benefits of splice-aware aligners include:
- Fewer reads are discarded for lack of alignments, leading to more
accurate gene quantification.
- Direct evidence of isoform usage is possible.
We should note that the default parameters for STAR are optimized for
mammalian genomes.
Splice-aware alignment
Credit: https://raw.githubusercontent.com/hbctraining/Intro-to-rnaseq-hpc-O2/master/lectures/Sequence_alignment.pdf
RSEM
RSEM (RNA-seq by Expectation Maximization) determines gene and
isoform abundance using an expectation maximization (EM) algorithm to
determine the probability that any particular read originated from a
particular transcript. From there, gene-level quantification is reported
by effectively collapsing the isoform quantifications over all isoforms
belonging to the gene.
The primary issue that RSEM attempts to solve is that reads can align
to multiple isoforms (when, for example, they share an exon), and that
creates ambiguity in deciding which isoform a read gets assigned to for
quantification. RSEM uses the EM algorithm described above to handle
this ambiguity appropriately.
Running RSEM+STAR
RSEM can be run with just two commands: the first
rsem-prepare-reference
(manual)
builds an index for STAR and RSEM to use, and the second
rsem-calculate-expression
(manual)
does the alignment and gene quantification.
We’ll explore the expected outputs from these commands and discuss
their contents, before creating our own reference and aligning reads
with our example data.
rsem-prepare-reference
Details
The purpose of rsem-prepare-reference
is to create a
reference index for alignment. A reference index is essentially a lookup
table that speeds up the finding of sequence matches for alignment. In
the case of a splice-aware aligner, the reference index is also aware of
the various splice junctions at locations in the gene model, and a
subset of reads will map across these. This allows us to infer isoform
usage later on.
rsem-prepare-reference
will use a FASTA file and a GTF
as inputs, and it will produce a number of large files which make up the
index. RSEM has the flexible capability of supporting multiple different
aligners. We’ll be using STAR. The output files therefore contain items
from the indexing process of STAR and RSEM. These files allow for the
fast and efficient search and retrieval of sequence and gene-model
information during alignment and quantification. The outputs will look
like the following:
GRCm38.102.chr19reduced.chrlist
GRCm38.102.chr19reduced.grp
GRCm38.102.chr19reduced.idx.fa
GRCm38.102.chr19reduced.n2g.idx.fa
GRCm38.102.chr19reduced.seq
GRCm38.102.chr19reduced.ti
GRCm38.102.chr19reduced.transcripts.fa
Genome
Log.out
SA
SAindex
chrLength.txt
chrName.txt
chrNameLength.txt
chrStart.txt
exonGeTrInfo.tab
exonInfo.tab
geneInfo.tab
genomeParameters.txt
sjdbInfo.txt
sjdbList.fromGTF.out.tab
sjdbList.out.tab
transcriptInfo.tab
rsem-calculate-expression
Details
After preparing the reference index, we can do alignment and
quantification with the rsem-calculate-expression
command
(here
is a link to the manual). For our inputs, we will be using our FASTQ
reads and the path to the reference index that we create.
There are numerous outputs, which are laid out in the following
table:
sample_N.genome.bam |
The alignments in genomic coordinates. Used for visualization in a
genome browser such as IGV. |
sample_N.transcript.bam |
The alignments in transcriptomic coordinates. Not used for this
workshop. |
sample_N.genes.results |
Gene-level results to be used in downstream DE analysis. |
sample_N.isoforms.results |
Isoform-level results. Not used for this workshop. |
The two results we will use most often from RSEM+STAR are the
gene-level quantifications (sample_N.genes.results
) and the
alignments in genome-coordinates (sample_N.genome.bam
).
Each sample for which we run RSEM+STAR will have these output files
named after the sample.
Genome Alignments
The sample_N.genome.bam
alignments file is a special,
compressed, version of a SAM file (sequence alignment/map). In order to
view it, we have to use a special program called samtools
.
If we were to peek inside of sample_N.genome.bam
, we
would see many columns of data. By using samtools
, we will
be able to view the columns in plain text (SAM format). The mandatory
columns in SAM format are shown in the following table from the official SAM/BAM
format specification.
The SAM format gives information about where each read maps to in the
genome (one read per line), and has information about that mapping.
Gene-level Quantification
If we were to look at the top 3 lines of
sample_N.genes.results
, we see it is a plain-text file
separated by tabs where each row is a gene, and the columns are
described the first row.
gene_id |
The ID from the gene model GTF. |
transcript_id(s) |
The transcript IDs corresponding to the gene in the gene model
GTF. |
length |
The weighted average of its transcripts’ lengths. |
effective_length |
The weighted average, over its transcripts, of the mean number of
positions from which a fragment may start within the sequence of
transcript. |
expected_count |
The sum, over all transcripts, of the estimated counts from the EM
algorithm. |
TPM |
Transcript per million, a relative measure of transcript abundance
where the sum of all TPMs is 1 million. |
FPKM |
Fragments per kilobase of transcript per million mapped reads. |
The genes.results
files for each sample can be directly
imported into DESeq2 using the tximport
R Bioconductor package.
Alternatively, we can combine these results into a count matrix. The
count matrix can be very useful, since it contains summary-level data in
a widely supported format, this makes it great for sharing and as input
into different analyses.
RSEM Prepare Reference Exercise:
- View the help page for rsem-prepare-reference
- Create a command that will index our example genome, but do not run
it
# View the help file
rsem-prepare-reference -h
# Create/execute the prepare-reference command
rsem-prepare-reference --gtf ../refs/GRCm38.102.chr19reduced.gtf --star --num-threads 1 ../refs/GRCm38.102.chr19reduced.fa ../refs/GRCm38.102.chr19reduced
RSEM Calculate Expression Exercise:
- View the help page for rsem-calculate-expression
- Create a command to execute RSEM / STAR alignment and quantification
for one of our samples
# First create a directory for the aligned results
mkdir out_rsem
# Construct an RSEM command to align sample_A to our reference
rsem-calculate-expression --star --num-threads 1 --star-gzipped-read-file --star-output-genome-bam --keep-intermediate-files out_trimmed/sample_A_R1.trimmed.fastq.gz ../refs/GRCm38.102.chr19reduced out_rsem/sample_A
LS0tCnRpdGxlOiAiQWxpZ25tZW50IgphdXRob3I6ICJVTSBCaW9pbmZvcm1hdGljcyBDb3JlIgpvdXRwdXQ6CiAgICAgICAgaHRtbF9kb2N1bWVudDoKICAgICAgICAgICAgaW5jbHVkZXM6CiAgICAgICAgICAgICAgICBpbl9oZWFkZXI6IGhlYWRlci5odG1sCiAgICAgICAgICAgIHRoZW1lOiBwYXBlcgogICAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgICAgdG9jX2RlcHRoOiA0CiAgICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogICAgICAgICAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICAgICAgICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICAgICAgICAgIG1hcmtkb3duOiBHRk0KICAgICAgICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keXsgLyogTm9ybWFsICAqLwogICAgICBmb250LXNpemU6IDE0cHQ7CiAgfQpwcmUgewogIGZvbnQtc2l6ZTogMTJwdAp9Cjwvc3R5bGU+CgpJbiB0aGlzIG1vZHVsZSwgd2Ugd2lsbCBsZWFybjoKCiogdGhlIGNvbmNlcHQgb2Ygc3BsaWNlLWF3YXJlIGFsaWdubWVudHMKKiB0aGUgdHdvIHN0ZXBzIG5lZWRlZCB0byBydW4gUlNFTStTVEFSCiogZGV0YWlscyBvZiBTQU0gYW5kIEJBTSBmaWxlcywgYW5kIFJTRU0gb3V0cHV0cwoKIyBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbiBXb3JrZmxvdwoKV2UnbGwgZGlzY3VzcyB0aGUgYWxpZ25tZW50IGFuZCBnZW5lIHF1YW50aWZpY2F0aW9uIHN0ZXBzIHdoaWNoIGdhdGhlciB0aGUgbmVjZXNzYXJ5IGRhdGEgdGhhdCB3ZSB3aWxsIG5lZWQgcHJpb3IgdG8gdGVzdGluZyBmb3IgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24sIHRoZSB0b3BpYyBvZiBEYXkgMi4KCiFbXShpbWFnZXMvd2F5ZmluZGVyL3dheWZpbmRlci1BbGlnbm1lbnQucG5nKQo8YnI+Cjxicj4KPGJyPgo8YnI+CgojIEFsaWdubWVudCBhbmQgR2VuZSBRdWFudGlmaWNhdGlvbgoKVGhlIEZBU1RRIGZpbGVzIG9mIHJhdyBzZXF1ZW5jZWQgcmVhZHMgYXJlIHVudGV0aGVyZWQgZnJvbSBhbnkgbm90aW9uIG9mIHdoZXJlIHRoZXkgY2FtZSBmcm9tIGluIHRoZSBnZW5vbWUsIGFuZCB3aGljaCB0cmFuc2NyaWJlZCBnZW5lcyB0aGUgc2VxdWVuY2UgYmVsb25ncyB0by4gVGhlIGFsaWdubWVudCBhbmQgZ2VuZSBxdWFudGlmaWNhdGlvbiBzdGVwcyBmaWxsIGluIHRoYXQgZ2FwIGFuZCBhbGxvdyB1cyB0byBwcm9jZWVkIHdpdGggdGhlIHF1ZXN0aW9uIHdlIGFyZSByZWFsbHkgaW50ZXJlc3RlZCBpbjogV2hpY2ggZ2VuZXMgYXJlIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBiZXR3ZWVuIGdyb3VwcyBvZiBzYW1wbGVzPwoKV2Ugd2lsbCB1c2UgUlNFTSAoW3BhcGVyXShodHRwczovL2JtY2Jpb2luZm9ybWF0aWNzLmJpb21lZGNlbnRyYWwuY29tL2FydGljbGVzLzEwLjExODYvMTQ3MS0yMTA1LTEyLTMyMykgYW5kIFtHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9kZXdleWxhYi9SU0VNKSkgY29tYmluZWQgd2l0aCBTVEFSIEFsaWduZXIgKFtwYXBlcl0oaHR0cHM6Ly9hY2FkZW1pYy5vdXAuY29tL2Jpb2luZm9ybWF0aWNzL2FydGljbGUvMjkvMS8xNS8yNzI1MzcpIGFuZCBbR2l0SHViXShodHRwczovL2dpdGh1Yi5jb20vYWxleGRvYmluL1NUQVIpKSB0byBhY2NvbXBsaXNoIHRoZSB0YXNrIG9mIHJlYWQgbWFwcGluZyBhbmQgZ2VuZSBxdWFudGlmY2F0aW9uIHNpbXVsdGFuZW91c2x5LgoKIyMgU1RBUgoKVGhlICJTcGxpY2VkIFRyYW5zY3JpcHRzIEFsaWdubWVudCB0byBhIFJlZmVyZW5jZSIgKFNUQVIpIEFsaWduZXIgaXMgYXdhcmUgb2Ygc3BsaWNlLXNpdGVzIG9mIHRyYW5zY3JpcHRzIGFuZCBpcyBhYmxlIHRvIGFsaWduIHJlYWRzIHRoYXQgc3BhbiB0aGVtLiBUaGUgZmlndXJlIGJlbG93IGlsbHVzdHJhdGVzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gc3BsaWNlLXVuYXdhcmUgYWxpZ25lcnMgKGUuZy4gQm93dGllMikgYW5kIHNwbGljZS1hd2FyZSBhbGlnbmVycyAoZS5nLiBTVEFSKS4KClNvbWUgYmVuZWZpdHMgb2Ygc3BsaWNlLWF3YXJlIGFsaWduZXJzIGluY2x1ZGU6CgoqIEZld2VyIHJlYWRzIGFyZSBkaXNjYXJkZWQgZm9yIGxhY2sgb2YgYWxpZ25tZW50cywgbGVhZGluZyB0byBtb3JlIGFjY3VyYXRlIGdlbmUgcXVhbnRpZmljYXRpb24uCiogRGlyZWN0IGV2aWRlbmNlIG9mIGlzb2Zvcm0gdXNhZ2UgaXMgcG9zc2libGUuCgpXZSBzaG91bGQgbm90ZSB0aGF0IHRoZSBkZWZhdWx0IHBhcmFtZXRlcnMgZm9yIFNUQVIgYXJlIG9wdGltaXplZCBmb3IgKiptYW1tYWxpYW4gZ2Vub21lcyoqLgoKPGNlbnRlcj4KCiFbU3BsaWNlLWF3YXJlIGFsaWdubWVudF0oaW1hZ2VzL3NwbGljZV9hd2FyZS5wbmcpCgpDcmVkaXQ6IGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9oYmN0cmFpbmluZy9JbnRyby10by1ybmFzZXEtaHBjLU8yL21hc3Rlci9sZWN0dXJlcy9TZXF1ZW5jZV9hbGlnbm1lbnQucGRmCgo8L2NlbnRlcj4KCiMjIFJTRU0KClJTRU0gKFJOQS1zZXEgYnkgRXhwZWN0YXRpb24gTWF4aW1pemF0aW9uKSBkZXRlcm1pbmVzIGdlbmUgYW5kIGlzb2Zvcm0gYWJ1bmRhbmNlIHVzaW5nIGFuIGV4cGVjdGF0aW9uIG1heGltaXphdGlvbiAoRU0pIGFsZ29yaXRobSB0byBkZXRlcm1pbmUgdGhlIHByb2JhYmlsaXR5IHRoYXQgYW55IHBhcnRpY3VsYXIgcmVhZCBvcmlnaW5hdGVkIGZyb20gYSBwYXJ0aWN1bGFyIHRyYW5zY3JpcHQuIEZyb20gdGhlcmUsIGdlbmUtbGV2ZWwgcXVhbnRpZmljYXRpb24gaXMgcmVwb3J0ZWQgYnkgZWZmZWN0aXZlbHkgY29sbGFwc2luZyB0aGUgaXNvZm9ybSBxdWFudGlmaWNhdGlvbnMgb3ZlciBhbGwgaXNvZm9ybXMgYmVsb25naW5nIHRvIHRoZSBnZW5lLgoKVGhlIHByaW1hcnkgaXNzdWUgdGhhdCBSU0VNIGF0dGVtcHRzIHRvIHNvbHZlIGlzIHRoYXQgcmVhZHMgY2FuIGFsaWduIHRvIG11bHRpcGxlIGlzb2Zvcm1zICh3aGVuLCBmb3IgZXhhbXBsZSwgdGhleSBzaGFyZSBhbiBleG9uKSwgYW5kIHRoYXQgY3JlYXRlcyBhbWJpZ3VpdHkgaW4gZGVjaWRpbmcgd2hpY2ggaXNvZm9ybSBhIHJlYWQgZ2V0cyBhc3NpZ25lZCB0byBmb3IgcXVhbnRpZmljYXRpb24uIFJTRU0gdXNlcyB0aGUgRU0gYWxnb3JpdGhtIGRlc2NyaWJlZCBhYm92ZSB0byBoYW5kbGUgdGhpcyBhbWJpZ3VpdHkgYXBwcm9wcmlhdGVseS4KCiMgUnVubmluZyBSU0VNK1NUQVIKClJTRU0gY2FuIGJlIHJ1biB3aXRoIGp1c3QgdHdvIGNvbW1hbmRzOiB0aGUgZmlyc3QgYHJzZW0tcHJlcGFyZS1yZWZlcmVuY2VgIChbbWFudWFsXShodHRwczovL2Rld2V5bGFiLmdpdGh1Yi5pby9SU0VNL3JzZW0tcHJlcGFyZS1yZWZlcmVuY2UuaHRtbCkpIGJ1aWxkcyBhbiBpbmRleCBmb3IgU1RBUiBhbmQgUlNFTSB0byB1c2UsIGFuZCB0aGUgc2Vjb25kIGByc2VtLWNhbGN1bGF0ZS1leHByZXNzaW9uYCAoW21hbnVhbF0oaHR0cHM6Ly9kZXdleWxhYi5naXRodWIuaW8vUlNFTS9yc2VtLWNhbGN1bGF0ZS1leHByZXNzaW9uLmh0bWwpKSBkb2VzIHRoZSBhbGlnbm1lbnQgYW5kIGdlbmUgcXVhbnRpZmljYXRpb24uCgpXZSdsbCBleHBsb3JlIHRoZSBleHBlY3RlZCBvdXRwdXRzIGZyb20gdGhlc2UgY29tbWFuZHMgYW5kIGRpc2N1c3MgdGhlaXIgY29udGVudHMsIGJlZm9yZSBjcmVhdGluZyBvdXIgb3duIHJlZmVyZW5jZSBhbmQgYWxpZ25pbmcgcmVhZHMgd2l0aCBvdXIgZXhhbXBsZSBkYXRhLgoKIyMgYHJzZW0tcHJlcGFyZS1yZWZlcmVuY2VgIERldGFpbHMKCiBUaGUgcHVycG9zZSBvZiBgcnNlbS1wcmVwYXJlLXJlZmVyZW5jZWAgaXMgdG8gY3JlYXRlIGEgcmVmZXJlbmNlIGluZGV4IGZvciBhbGlnbm1lbnQuIEEgcmVmZXJlbmNlIGluZGV4IGlzIGVzc2VudGlhbGx5IGEgbG9va3VwIHRhYmxlIHRoYXQgc3BlZWRzIHVwIHRoZSBmaW5kaW5nIG9mIHNlcXVlbmNlIG1hdGNoZXMgZm9yIGFsaWdubWVudC4gSW4gdGhlIGNhc2Ugb2YgYSBzcGxpY2UtYXdhcmUgYWxpZ25lciwgdGhlIHJlZmVyZW5jZSBpbmRleCBpcyBhbHNvIGF3YXJlIG9mIHRoZSB2YXJpb3VzIHNwbGljZSBqdW5jdGlvbnMgYXQgbG9jYXRpb25zIGluIHRoZSBnZW5lIG1vZGVsLCBhbmQgYSBzdWJzZXQgb2YgcmVhZHMgd2lsbCBtYXAgYWNyb3NzIHRoZXNlLiBUaGlzIGFsbG93cyB1cyB0byBpbmZlciBpc29mb3JtIHVzYWdlIGxhdGVyIG9uLgoKYHJzZW0tcHJlcGFyZS1yZWZlcmVuY2VgIHdpbGwgdXNlIGEgRkFTVEEgZmlsZSBhbmQgYSBHVEYgYXMgaW5wdXRzLCBhbmQgaXQgd2lsbCBwcm9kdWNlIGEgbnVtYmVyIG9mIGxhcmdlIGZpbGVzIHdoaWNoIG1ha2UgdXAgdGhlIGluZGV4LiBSU0VNIGhhcyB0aGUgZmxleGlibGUgY2FwYWJpbGl0eSBvZiBzdXBwb3J0aW5nIG11bHRpcGxlIGRpZmZlcmVudCBhbGlnbmVycy4gV2UnbGwgYmUgdXNpbmcgU1RBUi4gVGhlIG91dHB1dCBmaWxlcyB0aGVyZWZvcmUgY29udGFpbiBpdGVtcyBmcm9tIHRoZSBpbmRleGluZyBwcm9jZXNzIG9mIFNUQVIgYW5kIFJTRU0uIFRoZXNlIGZpbGVzIGFsbG93IGZvciB0aGUgZmFzdCBhbmQgZWZmaWNpZW50IHNlYXJjaCBhbmQgcmV0cmlldmFsIG9mIHNlcXVlbmNlIGFuZCBnZW5lLW1vZGVsIGluZm9ybWF0aW9uIGR1cmluZyBhbGlnbm1lbnQgYW5kIHF1YW50aWZpY2F0aW9uLiBUaGUgb3V0cHV0cyB3aWxsIGxvb2sgbGlrZSB0aGUgZm9sbG93aW5nOgoKICAgIEdSQ20zOC4xMDIuY2hyMTlyZWR1Y2VkLmNocmxpc3QKICAgIEdSQ20zOC4xMDIuY2hyMTlyZWR1Y2VkLmdycAogICAgR1JDbTM4LjEwMi5jaHIxOXJlZHVjZWQuaWR4LmZhCiAgICBHUkNtMzguMTAyLmNocjE5cmVkdWNlZC5uMmcuaWR4LmZhCiAgICBHUkNtMzguMTAyLmNocjE5cmVkdWNlZC5zZXEKICAgIEdSQ20zOC4xMDIuY2hyMTlyZWR1Y2VkLnRpCiAgICBHUkNtMzguMTAyLmNocjE5cmVkdWNlZC50cmFuc2NyaXB0cy5mYQogICAgR2Vub21lCiAgICBMb2cub3V0CiAgICBTQQogICAgU0FpbmRleAogICAgY2hyTGVuZ3RoLnR4dAogICAgY2hyTmFtZS50eHQKICAgIGNock5hbWVMZW5ndGgudHh0CiAgICBjaHJTdGFydC50eHQKICAgIGV4b25HZVRySW5mby50YWIKICAgIGV4b25JbmZvLnRhYgogICAgZ2VuZUluZm8udGFiCiAgICBnZW5vbWVQYXJhbWV0ZXJzLnR4dAogICAgc2pkYkluZm8udHh0CiAgICBzamRiTGlzdC5mcm9tR1RGLm91dC50YWIKICAgIHNqZGJMaXN0Lm91dC50YWIKICAgIHRyYW5zY3JpcHRJbmZvLnRhYgoKIyMgYHJzZW0tY2FsY3VsYXRlLWV4cHJlc3Npb25gIERldGFpbHMKCkFmdGVyIHByZXBhcmluZyB0aGUgcmVmZXJlbmNlIGluZGV4LCB3ZSBjYW4gZG8gYWxpZ25tZW50IGFuZCBxdWFudGlmaWNhdGlvbiB3aXRoIHRoZSBgcnNlbS1jYWxjdWxhdGUtZXhwcmVzc2lvbmAgY29tbWFuZCAoW2hlcmVdKGh0dHBzOi8vZGV3ZXlsYWIuZ2l0aHViLmlvL1JTRU0vcnNlbS1jYWxjdWxhdGUtZXhwcmVzc2lvbi5odG1sKSBpcyBhIGxpbmsgdG8gdGhlIG1hbnVhbCkuIEZvciBvdXIgaW5wdXRzLCB3ZSB3aWxsIGJlIHVzaW5nIG91ciBGQVNUUSByZWFkcyBhbmQgdGhlIHBhdGggdG8gdGhlIHJlZmVyZW5jZSBpbmRleCB0aGF0IHdlIGNyZWF0ZS4KClRoZXJlIGFyZSBudW1lcm91cyBvdXRwdXRzLCB3aGljaCBhcmUgbGFpZCBvdXQgaW4gdGhlIGZvbGxvd2luZyB0YWJsZToKCnwgRmlsZSB8IERlc2NyaXB0aW9uIHwKfCAtLS0tIHwgLS0tLS0tLS0tLS0gfAp8IGBzYW1wbGVfTi5nZW5vbWUuYmFtYCB8IFRoZSBhbGlnbm1lbnRzIGluIGdlbm9taWMgY29vcmRpbmF0ZXMuIFVzZWQgZm9yIHZpc3VhbGl6YXRpb24gaW4gYSBnZW5vbWUgYnJvd3NlciBzdWNoIGFzIFtJR1ZdKGh0dHBzOi8vc29mdHdhcmUuYnJvYWRpbnN0aXR1dGUub3JnL3NvZnR3YXJlL2lndi8pLiB8CnwgYHNhbXBsZV9OLnRyYW5zY3JpcHQuYmFtYCB8IFRoZSBhbGlnbm1lbnRzIGluIHRyYW5zY3JpcHRvbWljIGNvb3JkaW5hdGVzLiBOb3QgdXNlZCBmb3IgdGhpcyB3b3Jrc2hvcC4gfAp8IGBzYW1wbGVfTi5nZW5lcy5yZXN1bHRzYCB8IEdlbmUtbGV2ZWwgcmVzdWx0cyB0byBiZSB1c2VkIGluIGRvd25zdHJlYW0gREUgYW5hbHlzaXMuIHwKfCBgc2FtcGxlX04uaXNvZm9ybXMucmVzdWx0c2AgfCBJc29mb3JtLWxldmVsIHJlc3VsdHMuIE5vdCB1c2VkIGZvciB0aGlzIHdvcmtzaG9wLiB8CgoKVGhlIHR3byByZXN1bHRzIHdlIHdpbGwgdXNlIG1vc3Qgb2Z0ZW4gZnJvbSBSU0VNK1NUQVIgYXJlIHRoZSBnZW5lLWxldmVsIHF1YW50aWZpY2F0aW9ucyAoYHNhbXBsZV9OLmdlbmVzLnJlc3VsdHNgKSBhbmQgdGhlIGFsaWdubWVudHMgaW4gZ2Vub21lLWNvb3JkaW5hdGVzIChgc2FtcGxlX04uZ2Vub21lLmJhbWApLiBFYWNoIHNhbXBsZSBmb3Igd2hpY2ggd2UgcnVuIFJTRU0rU1RBUiB3aWxsIGhhdmUgdGhlc2Ugb3V0cHV0IGZpbGVzIG5hbWVkIGFmdGVyIHRoZSBzYW1wbGUuCgojIyMgR2Vub21lIEFsaWdubWVudHMKClRoZSBgc2FtcGxlX04uZ2Vub21lLmJhbWAgYWxpZ25tZW50cyBmaWxlIGlzIGEgc3BlY2lhbCwgY29tcHJlc3NlZCwgdmVyc2lvbiBvZiBhIFNBTSBmaWxlIChzZXF1ZW5jZSBhbGlnbm1lbnQvbWFwKS4gSW4gb3JkZXIgdG8gdmlldyBpdCwgd2UgaGF2ZSB0byB1c2UgYSBzcGVjaWFsIHByb2dyYW0gY2FsbGVkIFtgc2FtdG9vbHNgXShodHRwczovL3d3dy5odHNsaWIub3JnL2RvYy9zYW10b29scy5odG1sKS4KCklmIHdlIHdlcmUgdG8gcGVlayBpbnNpZGUgb2YgYHNhbXBsZV9OLmdlbm9tZS5iYW1gLCB3ZSB3b3VsZCBzZWUgbWFueSBjb2x1bW5zIG9mIGRhdGEuIEJ5IHVzaW5nIGBzYW10b29sc2AsIHdlIHdpbGwgYmUgYWJsZSB0byB2aWV3IHRoZSBjb2x1bW5zIGluIHBsYWluIHRleHQgKFNBTSBmb3JtYXQpLiBUaGUgbWFuZGF0b3J5IGNvbHVtbnMgaW4gU0FNIGZvcm1hdCBhcmUgc2hvd24gaW4gdGhlIGZvbGxvd2luZyB0YWJsZSBmcm9tIHRoZSBbb2ZmaWNpYWwgU0FNL0JBTSBmb3JtYXQgc3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9zYW10b29scy5naXRodWIuaW8vaHRzLXNwZWNzL1NBTXYxLnBkZikuCgo8aW1nIHNyYz0iaW1hZ2VzL3NhbV9jb2x1bW5zLnBuZyIgd2lkdGg9IjgwMCIgLz4KClRoZSBTQU0gZm9ybWF0IGdpdmVzIGluZm9ybWF0aW9uIGFib3V0IHdoZXJlIGVhY2ggcmVhZCBtYXBzIHRvIGluIHRoZSBnZW5vbWUgKG9uZSByZWFkIHBlciBsaW5lKSwgYW5kIGhhcyBpbmZvcm1hdGlvbiBhYm91dCB0aGF0IG1hcHBpbmcuCgo8YnI+PGJyPgohW0FsaWdubWVudCBkYXRhIGFuaW1hdGlvbl0oaW1hZ2VzL3NhbS1iYW0tYW5pbWF0ZWQuZ2lmKQo8YnI+PGJyPgoKIyMjIEdlbmUtbGV2ZWwgUXVhbnRpZmljYXRpb24KCklmIHdlIHdlcmUgdG8gbG9vayBhdCB0aGUgdG9wIDMgbGluZXMgb2YgYHNhbXBsZV9OLmdlbmVzLnJlc3VsdHNgLCB3ZSBzZWUgaXQgaXMgYSBwbGFpbi10ZXh0IGZpbGUgc2VwYXJhdGVkIGJ5IHRhYnMgd2hlcmUgZWFjaCByb3cgaXMgYSBnZW5lLCBhbmQgdGhlIGNvbHVtbnMgYXJlIGRlc2NyaWJlZCB0aGUgZmlyc3Qgcm93LgoKCnwgQ29sdW1uIHwgRGVzY3JpcHRpb24gfAp8IC0tLS0gfCAtLS0tLS0tLS0tLSB8CnwgZ2VuZV9pZCB8IFRoZSBJRCBmcm9tIHRoZSBnZW5lIG1vZGVsIEdURi4gfAp8IHRyYW5zY3JpcHRfaWQocykgfCBUaGUgdHJhbnNjcmlwdCBJRHMgY29ycmVzcG9uZGluZyB0byB0aGUgZ2VuZSBpbiB0aGUgZ2VuZSBtb2RlbCBHVEYuIHwKfCBsZW5ndGggfCBUaGUgd2VpZ2h0ZWQgYXZlcmFnZSBvZiBpdHMgdHJhbnNjcmlwdHMnIGxlbmd0aHMuIHwKfCBlZmZlY3RpdmVfbGVuZ3RoIHwgVGhlIHdlaWdodGVkIGF2ZXJhZ2UsIG92ZXIgaXRzIHRyYW5zY3JpcHRzLCBvZiB0aGUgbWVhbiBudW1iZXIgb2YgcG9zaXRpb25zIGZyb20gd2hpY2ggYSBmcmFnbWVudCBtYXkgc3RhcnQgd2l0aGluIHRoZSBzZXF1ZW5jZSBvZiB0cmFuc2NyaXB0LiB8CnwgZXhwZWN0ZWRfY291bnQgfCBUaGUgc3VtLCBvdmVyIGFsbCB0cmFuc2NyaXB0cywgb2YgdGhlIGVzdGltYXRlZCBjb3VudHMgZnJvbSB0aGUgRU0gYWxnb3JpdGhtLiB8CnwgVFBNIHwgVHJhbnNjcmlwdCBwZXIgbWlsbGlvbiwgYSByZWxhdGl2ZSBtZWFzdXJlIG9mIHRyYW5zY3JpcHQgYWJ1bmRhbmNlIHdoZXJlIHRoZSBzdW0gb2YgYWxsIFRQTXMgaXMgMSBtaWxsaW9uLiB8CnwgRlBLTSB8IEZyYWdtZW50cyBwZXIga2lsb2Jhc2Ugb2YgdHJhbnNjcmlwdCBwZXIgbWlsbGlvbiBtYXBwZWQgcmVhZHMuIHwKCgpUaGUgYGdlbmVzLnJlc3VsdHNgIGZpbGVzIGZvciBlYWNoIHNhbXBsZSBjYW4gYmUgZGlyZWN0bHkgaW1wb3J0ZWQgaW50byBERVNlcTIgdXNpbmcgdGhlIFtgdHhpbXBvcnRgXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL3ZpZ25ldHRlcy90eGltcG9ydC9pbnN0L2RvYy90eGltcG9ydC5odG1sI3JzZW0pIFIgQmlvY29uZHVjdG9yIHBhY2thZ2UuCgpBbHRlcm5hdGl2ZWx5LCB3ZSBjYW4gY29tYmluZSB0aGVzZSByZXN1bHRzIGludG8gYSBjb3VudCBtYXRyaXguIFRoZSBjb3VudCBtYXRyaXggY2FuIGJlIHZlcnkgdXNlZnVsLCBzaW5jZSBpdCBjb250YWlucyBzdW1tYXJ5LWxldmVsIGRhdGEgaW4gYSB3aWRlbHkgc3VwcG9ydGVkIGZvcm1hdCwgdGhpcyBtYWtlcyBpdCBncmVhdCBmb3Igc2hhcmluZyBhbmQgYXMgaW5wdXQgaW50byBkaWZmZXJlbnQgYW5hbHlzZXMuCgoKIyMgUlNFTSBQcmVwYXJlIFJlZmVyZW5jZSBFeGVyY2lzZToKCjEuIFZpZXcgdGhlIGhlbHAgcGFnZSBmb3IgcnNlbS1wcmVwYXJlLXJlZmVyZW5jZQoyLiBDcmVhdGUgYSBjb21tYW5kIHRoYXQgd2lsbCBpbmRleCBvdXIgZXhhbXBsZSBnZW5vbWUsIGJ1dCBkbyBub3QgcnVuIGl0CgpgYGAKIyBWaWV3IHRoZSBoZWxwIGZpbGUKcnNlbS1wcmVwYXJlLXJlZmVyZW5jZSAtaAojIENyZWF0ZS9leGVjdXRlIHRoZSBwcmVwYXJlLXJlZmVyZW5jZSBjb21tYW5kCnJzZW0tcHJlcGFyZS1yZWZlcmVuY2UgLS1ndGYgLi4vcmVmcy9HUkNtMzguMTAyLmNocjE5cmVkdWNlZC5ndGYgLS1zdGFyIC0tbnVtLXRocmVhZHMgMSAuLi9yZWZzL0dSQ20zOC4xMDIuY2hyMTlyZWR1Y2VkLmZhIC4uL3JlZnMvR1JDbTM4LjEwMi5jaHIxOXJlZHVjZWQKYGBgCgoKIyMgUlNFTSBDYWxjdWxhdGUgRXhwcmVzc2lvbiBFeGVyY2lzZToKCjEuIFZpZXcgdGhlIGhlbHAgcGFnZSBmb3IgcnNlbS1jYWxjdWxhdGUtZXhwcmVzc2lvbgoyLiBDcmVhdGUgYSBjb21tYW5kIHRvIGV4ZWN1dGUgUlNFTSAvIFNUQVIgYWxpZ25tZW50IGFuZCBxdWFudGlmaWNhdGlvbiBmb3Igb25lIG9mIG91ciBzYW1wbGVzCgpgYGAKIyBGaXJzdCBjcmVhdGUgYSBkaXJlY3RvcnkgZm9yIHRoZSBhbGlnbmVkIHJlc3VsdHMKbWtkaXIgb3V0X3JzZW0KIyBDb25zdHJ1Y3QgYW4gUlNFTSBjb21tYW5kIHRvIGFsaWduIHNhbXBsZV9BIHRvIG91ciByZWZlcmVuY2UKcnNlbS1jYWxjdWxhdGUtZXhwcmVzc2lvbiAtLXN0YXIgLS1udW0tdGhyZWFkcyAxIC0tc3Rhci1nemlwcGVkLXJlYWQtZmlsZSAtLXN0YXItb3V0cHV0LWdlbm9tZS1iYW0gLS1rZWVwLWludGVybWVkaWF0ZS1maWxlcyBvdXRfdHJpbW1lZC9zYW1wbGVfQV9SMS50cmltbWVkLmZhc3RxLmd6IC4uL3JlZnMvR1JDbTM4LjEwMi5jaHIxOXJlZHVjZWQgb3V0X3JzZW0vc2FtcGxlX0EKYGBgCjxicj4KPGJyPgoKIyMgQWxpZ25pbmcgQWxsIFNhbXBsZXMgRXhlcmNpc2U6CgpCZWZvcmUgc3RhcnRpbmcgb3VyIGFsaWdubWVudCBleGVyY2lzZSwgd2Ugc2hvdWxkIG1ha2Ugc3VyZSB0aGF0IHdlIGFyZSBvbiB0aGUgc2FtZSBwYWdlLiBGb2xsb3cgdGhlIGxpbmsgYmVsb3c6CgpbTGluayB0byBhbGlnbm1lbnQgZXhlcmNpc2VdKE1vZHVsZTAzYl9icmVha291dDAyX2V4Lmh0bWwpCgo8YnI+Cjxicj4KCi0tLQoKVGhlc2UgbWF0ZXJpYWxzIGhhdmUgYmVlbiBhZGFwdGVkIGFuZCBleHRlbmRlZCBmcm9tIG1hdGVyaWFscyBjcmVhdGVkIGJ5IHRoZSBbSGFydmFyZCBDaGFuIEJpb2luZm9ybWF0aWNzIENvcmUgKEhCQyldKGh0dHA6Ly9iaW9pbmZvcm1hdGljcy5zcGguaGFydmFyZC5lZHUvKS4gVGhlc2UgYXJlIG9wZW4gYWNjZXNzIG1hdGVyaWFscyBkaXN0cmlidXRlZCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIFtDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uIGxpY2Vuc2UgKENDIEJZIDQuMCldKGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LzQuMC8pLCB3aGljaCBwZXJtaXRzIHVucmVzdHJpY3RlZCB1c2UsIGRpc3RyaWJ1dGlvbiwgYW5kIHJlcHJvZHVjdGlvbiBpbiBhbnkgbWVkaXVtLCBwcm92aWRlZCB0aGUgb3JpZ2luYWwgYXV0aG9yIGFuZCBzb3VyY2UgYXJlIGNyZWRpdGVkLgoKPGJyLz4KPGJyLz4KPGhyLz4KfCBbUHJldmlvdXMgbGVzc29uXShNb2R1bGUwM2FfUmVmZXJlbmNlX0dlbm9tZXMuaHRtbCkgfCBbVG9wIG9mIHRoaXMgbGVzc29uXSgjdG9wKSB8IFtOZXh0IGxlc3Nvbl0oTW9kdWxlMDRfQWxpZ25tZW50X1FDX2FuZF9RdWFudGlmaWNhdGlvbi5odG1sKSB8CnwgOi0tLSB8IDotLS0tOiB8IC0tLTogfAo=