For this workshop, we’ve provided a few things to ensure that our
experience goes smoothly. In this module, we will discuss in more detail
each the things needed to perform an RNAseq analysis on your own.
Building Blocks
The Compute Environment
Here we’re referring to all of the hardware, software, and
configuration details of the system where we perform our analysis.
Hardware
CPU
CPU stands for Central Processing Unit. In shorthand, people often
refer to “the processor”. This retrieves and executes instructions, and
is one of the core components of a computing system.
Single vs Multi-Threaded
Many of the most heavily-used bioinformatics software can use
multiple threads. This way they can do parallel processing, which can
drastically cut down the time to receive results.
There are also plenty of single-threaded bioinformatics programs.
Simple python scripts, niche tools, etc. will often not need parallel
processing. In these cases, the cost/benefit tradeoff may be too
great.
Multi-threaded programs we’ve used:
Single-threaded programs we’ve used:
What about clock speed?
You may be familiar with clock speed of a processor from your
experience while buying personal computers. You may’ve seen specs listed
such as 3.3 GHz
, which refers to the CPU’s clock speed.
Clock speeds on all modern processors are sufficient for basically all
bioinformatics software. Clock speed is generally not a major
consideration in choices today.
Memory
Here we’re referring to Random Access Memory, or RAM. RAM provides a
limited amount of very fast storage that a process will use within a
short time frame.
The memory requirements of various tools vary widely, and many
bioinformatics programs require fairly high amounts. This is true for
aligners. In the case of the STAR aligner, a very large data structure
is loaded into RAM. This allows extremely fast and accurate alignments
e.g. to a vertebrate genome, but requires very large amounts of RAM.
Cutadapt, fastQC, and multiQC have more modest memory requirements,
so we won’t have to consider memory as much in those cases.
Storage
Here we’re referring to disk storage, or persistent storage. This
stores large amounts of data for the long term - the information remains
even when there is no power to the device. You may sometimes use the
phrase “save [the file] to your hard drive”, which is referring to
persistent storage.
Consider:
- Storage for input files, output files
- Storage during processing
Some input and output files can be quite large. Additionally, several
large intermediates are produced during processing, requiring (sometimes
considerable) additional storage.
Software
The software we’ve been using is free, open-source, and openly
licensed. We can inspect the source code, use the program as we wish,
modify it, contribute to it, etc. This is the case for many
bioinformatics tools. We can appreciate the benefits of community-driven
software.
There are tools available for various kinds of bioinformatics tasks.
Today we’ve focused on a few important tasks for RNA sequencing, and
used a subset of quality tools for this purpose. Here is a summary of
the tasks we’ve performed and the tools we’ve used today.
System Configuration
Operating System
The Operating System (OS) is a software layer that handles
communication between the hardware devices and with the end user.
In this workshop we’ve used a Linux operating system. Linux is free
and open source. It’s widely used in bioinformatics; as you’ve learned,
it can be very powerful.
Examples of Operating Systems?
Examples:
Some software is specific to an operating system - developers may
focus their time and attention on developing for certain configurations
over others, depending on the niche or goal. Often, releases may be
limited to certain OS / hardware configurations.
Local vs Remote
In this workshop, we’ve used remote computing systems for our
analysis. We’ve seen how we can connect to a remote computer and use it
for our purposes. You’re likely most familiar with local computing,
using a machine that is physically in the same room as you. However, now
we can recognize some benefits of remote computing.
Why Use Remote Computing?
Remote computing is sensible in many situations - for economies of
scale it’s best to have many machines in physical locations that are
built and designed for that purpose. This is what it means if you’ve
heard of cloud computing - a type of remote computing, often with
convenience services or products built on top of the remote machines. By
using remote computing, we can rent powerful hardware that would not be
practical for us to buy. We can also scale this up or down to our exact
needs, providing great flexibility.
How to Efficiently Manage Remote Computing Resources
This is a broad topic - job scheduling is a common method for
allocating shared compute resources. Consider a job as an individual
call to a piece of software. There are many ways to manage resources at
the job level.
Resource management and job scheduling at the UMich HPC is handled by
SLURM. Quite a large topic of its own, you can read more about these
resources here.
Another large topic which we won’t dive into, are workflow managers.
These allow similar job management capabilities, but are more flexible
since they are not tied to a specific type of system. Snakemake is an
example of this.
Today we’ve been aiming for simplicity and transparency, so managed
our jobs manually and sequentially. In other words, we wrote and
submitted the commands by hand, in order, for illustrative purposes. You
can imagine that for large-scale processing, it is incredibly useful to
allow software to automate some of these processes for us.
Software Management
There are many methods for managing software. As a system accumulates
changes over time, and as the resulting software installations become
more complex (esp. across multi-user systems), the need for software
management systems becomes more apparent.
Today we’ve been using miniconda.
This provides a good balance of simplicity, flexibility, and utility for
software management.
Conda is an open-source, cross-platform, package management and
environment management software. It’s widely used for packaging and
distributing software, particularly in the python community. Note: it is
also used for software of many different software languages; it is
language-agnostic.
Miniconda is a minimal installation of conda, that provides a
lightweight option to get started with.
Summary
Things that we have learned:
- Important aspects of hardware, software, and compute environments to
consider
- Important file formats and their contents
- Reference files necessary / where to find
- How to use FastQC, assess quality of reads
- How to transfer files from remote to local computer
- How to prepare a reference for alignment and quantification with
RSEM + STAR
- How to combine expression results across samples into a count
matrix
- How to use MultiQC to summarize large volumes of QC data.
Results Summary
Conda Exercises
Environment recap:
By default you will usually have a single compute environment - one
set up specifically for your user. You’ll have a set of programs, some
configuration details, etc. that are set up according to your
preferences.
As mentioned above, when doing data analysis tasks, it can become
onerous to create and maintain one environment that satisfies all of
your needs. It is good practice to create separate environments
according to the specific needs of a project. A metaphor would be
putting on different outfits for different occasions or tasks in your
life.
Conda is a tool that we’ve used for managing our software environment
for this workshop. We’re all currently using the same conda environment
that we (the instructors) built ahead of time.
Conda must-know:
- A tool for managing software environments
- Create an environment
- Activate and deactivate an environment
Conda Activate / Deactivate Exercise
- Learn about the
which
command - use to reveal the path
to a specific software
- Try
which python
- Deactivate our current shared environment with
conda deactivate
- Try
which python
again - Is it different now?
- Activate the environment again with
conda activate /workshop/conda/rsd
Conda Create Simple Exercise
- Check which python version we have in our current environment
- Create a simple conda environment named
py36
that
contains python 3.6 - use the bioconda
channel
- Activate the new
py36
environment and verify that you
now have python 3.6
- Deactivate our
py36
environment
# Check which python version we're using in our current environment
python --version
# Create a conda environment with python version 3.6, using the bioconda channel
conda create -n py36 -c bioconda python=3.6
# Activate our new conda environment
conda activate py36
# Check our python version now (it should be 3.6)
python --version
# Deactivate our environment
conda deactivate
LS0tCnRpdGxlOiAiQWRkaXRpb25hbCBEZXRhaWxzIgphdXRob3I6ICJVTSBCaW9pbmZvcm1hdGljcyBDb3JlIgpvdXRwdXQ6CiAgICAgICAgaHRtbF9kb2N1bWVudDoKICAgICAgICAgICAgaW5jbHVkZXM6CiAgICAgICAgICAgICAgICBpbl9oZWFkZXI6IGhlYWRlci5odG1sCiAgICAgICAgICAgIHRoZW1lOiBwYXBlcgogICAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgICAgdG9jX2RlcHRoOiA0CiAgICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogICAgICAgICAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICAgICAgICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICAgICAgICAgIG1hcmtkb3duOiBHRk0KICAgICAgICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keXsgLyogTm9ybWFsICAqLwogICAgICBmb250LXNpemU6IDE0cHQ7CiAgfQpwcmUgewogIGZvbnQtc2l6ZTogMTJwdAp9Cjwvc3R5bGU+CgpGb3IgdGhpcyB3b3Jrc2hvcCwgd2UndmUgcHJvdmlkZWQgYSBmZXcgdGhpbmdzIHRvIGVuc3VyZSB0aGF0IG91ciBleHBlcmllbmNlIGdvZXMgc21vb3RobHkuIEluIHRoaXMgbW9kdWxlLCB3ZSB3aWxsIGRpc2N1c3MgaW4gbW9yZSBkZXRhaWwgZWFjaCB0aGUgdGhpbmdzIG5lZWRlZCB0byBwZXJmb3JtIGFuIFJOQXNlcSBhbmFseXNpcyBvbiB5b3VyIG93bi4KCiFbQnVpbGRpbmcgQmxvY2tzXShpbWFnZXMvYnVpbGRpbmctYmxvY2tzLnBuZykKCgojIFRoZSBDb21wdXRlIEVudmlyb25tZW50CgpIZXJlIHdlJ3JlIHJlZmVycmluZyB0byBhbGwgb2YgdGhlIGhhcmR3YXJlLCBzb2Z0d2FyZSwgYW5kIGNvbmZpZ3VyYXRpb24gZGV0YWlscyBvZiB0aGUgc3lzdGVtIHdoZXJlIHdlIHBlcmZvcm0gb3VyIGFuYWx5c2lzLgoKIyMgSGFyZHdhcmUKCi0gQ1BVCi0gTWVtb3J5Ci0gU3RvcmFnZQoKIyMjIENQVQoKQ1BVIHN0YW5kcyBmb3IgQ2VudHJhbCBQcm9jZXNzaW5nIFVuaXQuIEluIHNob3J0aGFuZCwgcGVvcGxlIG9mdGVuIHJlZmVyIHRvICJ0aGUgcHJvY2Vzc29yIi4gVGhpcyAgcmV0cmlldmVzIGFuZCBleGVjdXRlcyBpbnN0cnVjdGlvbnMsIGFuZCBpcyBvbmUgb2YgdGhlIGNvcmUgY29tcG9uZW50cyBvZiBhIGNvbXB1dGluZyBzeXN0ZW0uCgpTaW5nbGUgdnMgTXVsdGktVGhyZWFkZWQKCk1hbnkgb2YgdGhlIG1vc3QgaGVhdmlseS11c2VkIGJpb2luZm9ybWF0aWNzIHNvZnR3YXJlIGNhbiB1c2UgbXVsdGlwbGUgdGhyZWFkcy4gVGhpcyB3YXkgdGhleSBjYW4gZG8gcGFyYWxsZWwgcHJvY2Vzc2luZywgd2hpY2ggY2FuIGRyYXN0aWNhbGx5IGN1dCBkb3duIHRoZSB0aW1lIHRvIHJlY2VpdmUgcmVzdWx0cy4KClRoZXJlIGFyZSBhbHNvIHBsZW50eSBvZiBzaW5nbGUtdGhyZWFkZWQgYmlvaW5mb3JtYXRpY3MgcHJvZ3JhbXMuIFNpbXBsZSBweXRob24gc2NyaXB0cywgbmljaGUgdG9vbHMsIGV0Yy4gd2lsbCBvZnRlbiBub3QgbmVlZCBwYXJhbGxlbCBwcm9jZXNzaW5nLiBJbiB0aGVzZSBjYXNlcywgdGhlIGNvc3QvYmVuZWZpdCB0cmFkZW9mZiBtYXkgYmUgdG9vIGdyZWF0LgoKTXVsdGktdGhyZWFkZWQgcHJvZ3JhbXMgd2UndmUgdXNlZDoKCi0gQ3V0YWRhcHQKLSBTVEFSIC8gUlNFTQoKU2luZ2xlLXRocmVhZGVkIHByb2dyYW1zIHdlJ3ZlIHVzZWQ6CgotIEZhc3RRQwotIE11bHRpUUMKCjxkZXRhaWxzPgo8c3VtbWFyeT5XaGF0IGFib3V0IGNsb2NrIHNwZWVkPzwvc3VtbWFyeT4KCllvdSBtYXkgYmUgZmFtaWxpYXIgd2l0aCBjbG9jayBzcGVlZCBvZiBhIHByb2Nlc3NvciBmcm9tIHlvdXIgZXhwZXJpZW5jZSB3aGlsZSBidXlpbmcgcGVyc29uYWwgY29tcHV0ZXJzLiBZb3UgbWF5J3ZlIHNlZW4gc3BlY3MgbGlzdGVkIHN1Y2ggYXMgYDMuMyBHSHpgLCB3aGljaCByZWZlcnMgdG8gdGhlIENQVSdzIGNsb2NrIHNwZWVkLgoKQ2xvY2sgc3BlZWRzIG9uIGFsbCBtb2Rlcm4gcHJvY2Vzc29ycyBhcmUgc3VmZmljaWVudCBmb3IgYmFzaWNhbGx5IGFsbCBiaW9pbmZvcm1hdGljcyBzb2Z0d2FyZS4gQ2xvY2sgc3BlZWQgaXMgZ2VuZXJhbGx5IG5vdCBhIG1ham9yIGNvbnNpZGVyYXRpb24gaW4gY2hvaWNlcyB0b2RheS4KPC9kZXRhaWxzPgoKPGJyPgo8YnI+CgojIyMgTWVtb3J5CgpIZXJlIHdlJ3JlIHJlZmVycmluZyB0byBSYW5kb20gQWNjZXNzIE1lbW9yeSwgb3IgUkFNLiBSQU0gcHJvdmlkZXMgYSBsaW1pdGVkIGFtb3VudCBvZiB2ZXJ5IGZhc3Qgc3RvcmFnZSB0aGF0IGEgcHJvY2VzcyB3aWxsIHVzZSB3aXRoaW4gYSBzaG9ydCB0aW1lIGZyYW1lLgoKVGhlIG1lbW9yeSByZXF1aXJlbWVudHMgb2YgdmFyaW91cyB0b29scyB2YXJ5IHdpZGVseSwgYW5kIG1hbnkgYmlvaW5mb3JtYXRpY3MgcHJvZ3JhbXMgcmVxdWlyZSBmYWlybHkgaGlnaCBhbW91bnRzLiBUaGlzIGlzIHRydWUgZm9yIGFsaWduZXJzLiBJbiB0aGUgY2FzZSBvZiB0aGUgU1RBUiBhbGlnbmVyLCBhIHZlcnkgbGFyZ2UgZGF0YSBzdHJ1Y3R1cmUgaXMgbG9hZGVkIGludG8gUkFNLiBUaGlzIGFsbG93cyBleHRyZW1lbHkgZmFzdCBhbmQgYWNjdXJhdGUgYWxpZ25tZW50cyBlLmcuIHRvIGEgdmVydGVicmF0ZSBnZW5vbWUsIGJ1dCByZXF1aXJlcyB2ZXJ5IGxhcmdlIGFtb3VudHMgb2YgUkFNLgoKQ3V0YWRhcHQsIGZhc3RRQywgYW5kIG11bHRpUUMgaGF2ZSBtb3JlIG1vZGVzdCBtZW1vcnkgcmVxdWlyZW1lbnRzLCBzbyB3ZSB3b24ndCBoYXZlIHRvIGNvbnNpZGVyIG1lbW9yeSBhcyBtdWNoIGluIHRob3NlIGNhc2VzLgoKIyMjIFN0b3JhZ2UKCkhlcmUgd2UncmUgcmVmZXJyaW5nIHRvIGRpc2sgc3RvcmFnZSwgb3IgcGVyc2lzdGVudCBzdG9yYWdlLiBUaGlzIHN0b3JlcyBsYXJnZSBhbW91bnRzIG9mIGRhdGEgZm9yIHRoZSBsb25nIHRlcm0gLSB0aGUgaW5mb3JtYXRpb24gcmVtYWlucyBldmVuIHdoZW4gdGhlcmUgaXMgbm8gcG93ZXIgdG8gdGhlIGRldmljZS4gWW91IG1heSBzb21ldGltZXMgdXNlIHRoZSBwaHJhc2UgInNhdmUgW3RoZSBmaWxlXSB0byB5b3VyIGhhcmQgZHJpdmUiLCB3aGljaCBpcyByZWZlcnJpbmcgdG8gcGVyc2lzdGVudCBzdG9yYWdlLgoKQ29uc2lkZXI6CgotIFN0b3JhZ2UgZm9yIGlucHV0IGZpbGVzLCBvdXRwdXQgZmlsZXMKLSBTdG9yYWdlIGR1cmluZyBwcm9jZXNzaW5nCgpTb21lIGlucHV0IGFuZCBvdXRwdXQgZmlsZXMgY2FuIGJlIHF1aXRlIGxhcmdlLiBBZGRpdGlvbmFsbHksIHNldmVyYWwgbGFyZ2UgaW50ZXJtZWRpYXRlcyBhcmUgcHJvZHVjZWQgZHVyaW5nIHByb2Nlc3NpbmcsIHJlcXVpcmluZyAoc29tZXRpbWVzIGNvbnNpZGVyYWJsZSkgYWRkaXRpb25hbCBzdG9yYWdlLgoKIyMgU29mdHdhcmUKClRoZSBzb2Z0d2FyZSB3ZSd2ZSBiZWVuIHVzaW5nIGlzIGZyZWUsIG9wZW4tc291cmNlLCBhbmQgb3Blbmx5IGxpY2Vuc2VkLiBXZSBjYW4gaW5zcGVjdCB0aGUgc291cmNlIGNvZGUsIHVzZSB0aGUgcHJvZ3JhbSBhcyB3ZSB3aXNoLCBtb2RpZnkgaXQsIGNvbnRyaWJ1dGUgdG8gaXQsIGV0Yy4gVGhpcyBpcyB0aGUgY2FzZSBmb3IgbWFueSBiaW9pbmZvcm1hdGljcyB0b29scy4gV2UgY2FuIGFwcHJlY2lhdGUgdGhlIGJlbmVmaXRzIG9mIGNvbW11bml0eS1kcml2ZW4gc29mdHdhcmUuCgpUaGVyZSBhcmUgdG9vbHMgYXZhaWxhYmxlIGZvciB2YXJpb3VzIGtpbmRzIG9mIGJpb2luZm9ybWF0aWNzIHRhc2tzLiBUb2RheSB3ZSd2ZSBmb2N1c2VkIG9uIGEgZmV3IGltcG9ydGFudCB0YXNrcyBmb3IgUk5BIHNlcXVlbmNpbmcsIGFuZCB1c2VkIGEgc3Vic2V0IG9mIHF1YWxpdHkgdG9vbHMgZm9yIHRoaXMgcHVycG9zZS4gSGVyZSBpcyBhIHN1bW1hcnkgb2YgdGhlIHRhc2tzIHdlJ3ZlIHBlcmZvcm1lZCBhbmQgdGhlIHRvb2xzIHdlJ3ZlIHVzZWQgdG9kYXkuCgp8IFRhc2sgfCBUb29sIHwKfCA6LS06IHwgLS0tLSB8CnwgUXVhbGl0eSBDb250cm9sIHwgW0Zhc3RRQ10oaHR0cHM6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvcHJvamVjdHMvZmFzdHFjL0hlbHAvKSB8CnwgUXVhbGl0eSBDb250cm9sIHwgW011bHRpUUNdKGh0dHBzOi8vbXVsdGlxYy5pbmZvL2RvY3MvKSB8CnwgUmVhZCBUcmltbWluZyB8IFtDdXRhZGFwdF0oaHR0cHM6Ly9jdXRhZGFwdC5yZWFkdGhlZG9jcy5pby9lbi9zdGFibGUvKSB8CnwgQWxpZ25tZW50IHwgW1NUQVJdKGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4ZG9iaW4vU1RBUi9ibG9iL21hc3Rlci9kb2MvU1RBUm1hbnVhbC5wZGYpIHwKfCBHZW5lIFF1YW50aWZpY2F0aW9uIHwgW1JTRU1dKGh0dHA6Ly9kZXdleWxhYi5naXRodWIuaW8vUlNFTS8pIHwKCiMjIFN5c3RlbSBDb25maWd1cmF0aW9uCgojIyMgT3BlcmF0aW5nIFN5c3RlbQoKVGhlIE9wZXJhdGluZyBTeXN0ZW0gKE9TKSBpcyBhIHNvZnR3YXJlIGxheWVyIHRoYXQgaGFuZGxlcyBjb21tdW5pY2F0aW9uIGJldHdlZW4gdGhlIGhhcmR3YXJlIGRldmljZXMgYW5kIHdpdGggdGhlIGVuZCB1c2VyLgoKSW4gdGhpcyB3b3Jrc2hvcCB3ZSd2ZSB1c2VkIGEgTGludXggb3BlcmF0aW5nIHN5c3RlbS4gTGludXggaXMgZnJlZSBhbmQgb3BlbiBzb3VyY2UuIEl0J3Mgd2lkZWx5IHVzZWQgaW4gYmlvaW5mb3JtYXRpY3M7IGFzIHlvdSd2ZSBsZWFybmVkLCBpdCBjYW4gYmUgdmVyeSBwb3dlcmZ1bC4KCjxkZXRhaWxzPgo8c3VtbWFyeT5FeGFtcGxlcyBvZiBPcGVyYXRpbmcgU3lzdGVtcz88L3N1bW1hcnk+CgpFeGFtcGxlczoKCi0gTWljcm9zb2Z0IC0gW1dpbmRvd3NdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01pY3Jvc29mdF9XaW5kb3dzKQotIEFwcGxlIC0gW01hY09TXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NYWNPUykKLSBbRk9TU10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRnJlZV9hbmRfb3Blbi1zb3VyY2Vfc29mdHdhcmUpIC0gW0dOVV0oaHR0cDovL3d3dy5nbnUub3JnKSAvIFtMSU5VWF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGludXgpCi0gR29vZ2xlIC0gW0FuZHJvaWRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FuZHJvaWRfKG9wZXJhdGluZ19zeXN0ZW0pKQotIEFwcGxlIC0gW2lPU10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSU9TKQoKU29tZSBzb2Z0d2FyZSBpcyBzcGVjaWZpYyB0byBhbiBvcGVyYXRpbmcgc3lzdGVtIC0gZGV2ZWxvcGVycyBtYXkgZm9jdXMgdGhlaXIgdGltZSBhbmQgYXR0ZW50aW9uIG9uIGRldmVsb3BpbmcgZm9yIGNlcnRhaW4gY29uZmlndXJhdGlvbnMgb3ZlciBvdGhlcnMsIGRlcGVuZGluZyBvbiB0aGUgbmljaGUgb3IgZ29hbC4gT2Z0ZW4sIHJlbGVhc2VzIG1heSBiZSBsaW1pdGVkIHRvIGNlcnRhaW4gT1MgLyBoYXJkd2FyZSBjb25maWd1cmF0aW9ucy4KCjwvZGV0YWlscz4KCjxicj4KPGJyPgoKIyMjIExvY2FsIHZzIFJlbW90ZQoKSW4gdGhpcyB3b3Jrc2hvcCwgd2UndmUgdXNlZCByZW1vdGUgY29tcHV0aW5nIHN5c3RlbXMgZm9yIG91ciBhbmFseXNpcy4gV2UndmUgc2VlbiBob3cgd2UgY2FuIGNvbm5lY3QgdG8gYSByZW1vdGUgY29tcHV0ZXIgYW5kIHVzZSBpdCBmb3Igb3VyIHB1cnBvc2VzLiBZb3UncmUgbGlrZWx5IG1vc3QgZmFtaWxpYXIgd2l0aCBsb2NhbCBjb21wdXRpbmcsIHVzaW5nIGEgbWFjaGluZSB0aGF0IGlzIHBoeXNpY2FsbHkgaW4gdGhlIHNhbWUgcm9vbSBhcyB5b3UuIEhvd2V2ZXIsIG5vdyB3ZSBjYW4gcmVjb2duaXplIHNvbWUgYmVuZWZpdHMgb2YgcmVtb3RlIGNvbXB1dGluZy4KCjxkZXRhaWxzPgo8c3VtbWFyeT5XaHkgVXNlIFJlbW90ZSBDb21wdXRpbmc/PC9zdW1tYXJ5PgoKUmVtb3RlIGNvbXB1dGluZyBpcyBzZW5zaWJsZSBpbiBtYW55IHNpdHVhdGlvbnMgLSBmb3IgZWNvbm9taWVzIG9mIHNjYWxlIGl0J3MgYmVzdCB0byBoYXZlIG1hbnkgbWFjaGluZXMgaW4gcGh5c2ljYWwgbG9jYXRpb25zIHRoYXQgYXJlIGJ1aWx0IGFuZCBkZXNpZ25lZCBmb3IgdGhhdCBwdXJwb3NlLiBUaGlzIGlzIHdoYXQgaXQgbWVhbnMgaWYgeW91J3ZlIGhlYXJkIG9mIGNsb3VkIGNvbXB1dGluZyAtIGEgdHlwZSBvZiByZW1vdGUgY29tcHV0aW5nLCBvZnRlbiB3aXRoIGNvbnZlbmllbmNlIHNlcnZpY2VzIG9yIHByb2R1Y3RzIGJ1aWx0IG9uIHRvcCBvZiB0aGUgcmVtb3RlIG1hY2hpbmVzLiBCeSB1c2luZyByZW1vdGUgY29tcHV0aW5nLCB3ZSBjYW4gcmVudCBwb3dlcmZ1bCBoYXJkd2FyZSB0aGF0IHdvdWxkIG5vdCBiZSBwcmFjdGljYWwgZm9yIHVzIHRvIGJ1eS4gV2UgY2FuIGFsc28gc2NhbGUgdGhpcyB1cCBvciBkb3duIHRvIG91ciBleGFjdCBuZWVkcywgcHJvdmlkaW5nIGdyZWF0IGZsZXhpYmlsaXR5LgoKPC9kZXRhaWxzPgoKPGRldGFpbHM+CjxzdW1tYXJ5PkhvdyB0byBFZmZpY2llbnRseSBNYW5hZ2UgUmVtb3RlIENvbXB1dGluZyBSZXNvdXJjZXM8L3N1bW1hcnk+CgpUaGlzIGlzIGEgYnJvYWQgdG9waWMgLSBqb2Igc2NoZWR1bGluZyBpcyBhIGNvbW1vbiBtZXRob2QgZm9yIGFsbG9jYXRpbmcgc2hhcmVkIGNvbXB1dGUgcmVzb3VyY2VzLiBDb25zaWRlciBhIGpvYiBhcyBhbiBpbmRpdmlkdWFsIGNhbGwgdG8gYSBwaWVjZSBvZiBzb2Z0d2FyZS4gVGhlcmUgYXJlIG1hbnkgd2F5cyB0byBtYW5hZ2UgcmVzb3VyY2VzIGF0IHRoZSBqb2IgbGV2ZWwuCgpSZXNvdXJjZSBtYW5hZ2VtZW50IGFuZCBqb2Igc2NoZWR1bGluZyBhdCB0aGUgVU1pY2ggSFBDIGlzIGhhbmRsZWQgYnkgU0xVUk0uIFF1aXRlIGEgbGFyZ2UgdG9waWMgb2YgaXRzIG93biwgeW91IGNhbiByZWFkIG1vcmUgYWJvdXQgdGhlc2UgcmVzb3VyY2VzIFtoZXJlXShodHRwczovL2FyYy51bWljaC5lZHUvZ3JlYXRsYWtlcy9zbHVybS11c2VyLWd1aWRlLykuCgpBbm90aGVyIGxhcmdlIHRvcGljIHdoaWNoIHdlIHdvbid0IGRpdmUgaW50bywgYXJlIHdvcmtmbG93IG1hbmFnZXJzLiBUaGVzZSBhbGxvdyBzaW1pbGFyIGpvYiBtYW5hZ2VtZW50IGNhcGFiaWxpdGllcywgYnV0IGFyZSBtb3JlIGZsZXhpYmxlIHNpbmNlIHRoZXkgYXJlIG5vdCB0aWVkIHRvIGEgc3BlY2lmaWMgdHlwZSBvZiBzeXN0ZW0uIFtTbmFrZW1ha2VdKGh0dHBzOi8vc25ha2VtYWtlLnJlYWR0aGVkb2NzLmlvL2VuL3N0YWJsZS8pIGlzIGFuIGV4YW1wbGUgb2YgdGhpcy4KClRvZGF5IHdlJ3ZlIGJlZW4gYWltaW5nIGZvciBzaW1wbGljaXR5IGFuZCB0cmFuc3BhcmVuY3ksIHNvIG1hbmFnZWQgb3VyIGpvYnMgbWFudWFsbHkgYW5kIHNlcXVlbnRpYWxseS4gSW4gb3RoZXIgd29yZHMsIHdlIHdyb3RlIGFuZCBzdWJtaXR0ZWQgdGhlIGNvbW1hbmRzIGJ5IGhhbmQsIGluIG9yZGVyLCBmb3IgaWxsdXN0cmF0aXZlIHB1cnBvc2VzLiBZb3UgY2FuIGltYWdpbmUgdGhhdCBmb3IgbGFyZ2Utc2NhbGUgcHJvY2Vzc2luZywgaXQgaXMgaW5jcmVkaWJseSB1c2VmdWwgdG8gYWxsb3cgc29mdHdhcmUgdG8gYXV0b21hdGUgc29tZSBvZiB0aGVzZSBwcm9jZXNzZXMgZm9yIHVzLgoKPC9kZXRhaWxzPgoKPGJyPgo8YnI+CgojIyMgU29mdHdhcmUgTWFuYWdlbWVudAoKVGhlcmUgYXJlIG1hbnkgbWV0aG9kcyBmb3IgbWFuYWdpbmcgc29mdHdhcmUuIEFzIGEgc3lzdGVtIGFjY3VtdWxhdGVzIGNoYW5nZXMgb3ZlciB0aW1lLCBhbmQgYXMgdGhlIHJlc3VsdGluZyBzb2Z0d2FyZSBpbnN0YWxsYXRpb25zIGJlY29tZSBtb3JlIGNvbXBsZXggKGVzcC4gYWNyb3NzIG11bHRpLXVzZXIgc3lzdGVtcyksIHRoZSBuZWVkIGZvciBzb2Z0d2FyZSBtYW5hZ2VtZW50IHN5c3RlbXMgYmVjb21lcyBtb3JlIGFwcGFyZW50LgoKVG9kYXkgd2UndmUgYmVlbiB1c2luZyBbbWluaWNvbmRhXShodHRwczovL2RvY3MuY29uZGEuaW8vZW4vbGF0ZXN0L21pbmljb25kYS5odG1sKS4gVGhpcyBwcm92aWRlcyBhIGdvb2QgYmFsYW5jZSBvZiBzaW1wbGljaXR5LCBmbGV4aWJpbGl0eSwgYW5kIHV0aWxpdHkgZm9yIHNvZnR3YXJlIG1hbmFnZW1lbnQuCgpDb25kYSBpcyBhbiBvcGVuLXNvdXJjZSwgY3Jvc3MtcGxhdGZvcm0sIHBhY2thZ2UgbWFuYWdlbWVudCBhbmQgZW52aXJvbm1lbnQgbWFuYWdlbWVudCBzb2Z0d2FyZS4gSXQncyB3aWRlbHkgdXNlZCBmb3IgcGFja2FnaW5nIGFuZCBkaXN0cmlidXRpbmcgc29mdHdhcmUsIHBhcnRpY3VsYXJseSBpbiB0aGUgcHl0aG9uIGNvbW11bml0eS4gTm90ZTogaXQgaXMgYWxzbyB1c2VkIGZvciBzb2Z0d2FyZSBvZiBtYW55IGRpZmZlcmVudCBzb2Z0d2FyZSBsYW5ndWFnZXM7IGl0IGlzIGxhbmd1YWdlLWFnbm9zdGljLgoKTWluaWNvbmRhIGlzIGEgbWluaW1hbCBpbnN0YWxsYXRpb24gb2YgY29uZGEsIHRoYXQgcHJvdmlkZXMgYSBsaWdodHdlaWdodCBvcHRpb24gdG8gZ2V0IHN0YXJ0ZWQgd2l0aC4KCgo8YnI+Cjxicj4KCgojIFN1bW1hcnkKClRoaW5ncyB0aGF0IHdlIGhhdmUgbGVhcm5lZDoKCi0gSW1wb3J0YW50IGFzcGVjdHMgb2YgaGFyZHdhcmUsIHNvZnR3YXJlLCBhbmQgY29tcHV0ZSBlbnZpcm9ubWVudHMgdG8gY29uc2lkZXIKLSBJbXBvcnRhbnQgZmlsZSBmb3JtYXRzIGFuZCB0aGVpciBjb250ZW50cwotIFJlZmVyZW5jZSBmaWxlcyBuZWNlc3NhcnkgLyB3aGVyZSB0byBmaW5kCi0gSG93IHRvIHVzZSBGYXN0UUMsIGFzc2VzcyBxdWFsaXR5IG9mIHJlYWRzCi0gSG93IHRvIHRyYW5zZmVyIGZpbGVzIGZyb20gcmVtb3RlIHRvIGxvY2FsIGNvbXB1dGVyCi0gSG93IHRvIHByZXBhcmUgYSByZWZlcmVuY2UgZm9yIGFsaWdubWVudCBhbmQgcXVhbnRpZmljYXRpb24gd2l0aCBSU0VNICsgU1RBUgotIEhvdyB0byBjb21iaW5lIGV4cHJlc3Npb24gcmVzdWx0cyBhY3Jvc3Mgc2FtcGxlcyBpbnRvIGEgY291bnQgbWF0cml4Ci0gSG93IHRvIHVzZSBNdWx0aVFDIHRvIHN1bW1hcml6ZSBsYXJnZSB2b2x1bWVzIG9mIFFDIGRhdGEuCgo8YnI+Cjxicj4KCiFbUmVzdWx0cyBTdW1tYXJ5XShpbWFnZXMvcmVzdWx0cy1zdW1tYXJ5LnBuZykKCjxicj4KPGJyPgoKCiMgQ29uZGEgRXhlcmNpc2VzCgpFbnZpcm9ubWVudCByZWNhcDoKCkJ5IGRlZmF1bHQgeW91IHdpbGwgdXN1YWxseSBoYXZlIGEgc2luZ2xlIGNvbXB1dGUgZW52aXJvbm1lbnQgLSBvbmUgc2V0IHVwIHNwZWNpZmljYWxseSBmb3IgeW91ciB1c2VyLiBZb3UnbGwgaGF2ZSBhIHNldCBvZiBwcm9ncmFtcywgc29tZSBjb25maWd1cmF0aW9uIGRldGFpbHMsIGV0Yy4gdGhhdCBhcmUgc2V0IHVwIGFjY29yZGluZyB0byB5b3VyIHByZWZlcmVuY2VzLgoKQXMgbWVudGlvbmVkIGFib3ZlLCB3aGVuIGRvaW5nIGRhdGEgYW5hbHlzaXMgdGFza3MsIGl0IGNhbiBiZWNvbWUgb25lcm91cyB0byBjcmVhdGUgYW5kIG1haW50YWluIG9uZSBlbnZpcm9ubWVudCB0aGF0IHNhdGlzZmllcyBhbGwgb2YgeW91ciBuZWVkcy4gSXQgaXMgZ29vZCBwcmFjdGljZSB0byBjcmVhdGUgc2VwYXJhdGUgZW52aXJvbm1lbnRzIGFjY29yZGluZyB0byB0aGUgc3BlY2lmaWMgbmVlZHMgb2YgYSBwcm9qZWN0LiBBIG1ldGFwaG9yIHdvdWxkIGJlIHB1dHRpbmcgb24gZGlmZmVyZW50IG91dGZpdHMgZm9yIGRpZmZlcmVudCBvY2Nhc2lvbnMgb3IgdGFza3MgaW4geW91ciBsaWZlLgoKQ29uZGEgaXMgYSB0b29sIHRoYXQgd2UndmUgdXNlZCBmb3IgbWFuYWdpbmcgb3VyIHNvZnR3YXJlIGVudmlyb25tZW50IGZvciB0aGlzIHdvcmtzaG9wLiBXZSdyZSBhbGwgY3VycmVudGx5IHVzaW5nIHRoZSBzYW1lIGNvbmRhIGVudmlyb25tZW50IHRoYXQgd2UgKHRoZSBpbnN0cnVjdG9ycykgYnVpbHQgYWhlYWQgb2YgdGltZS4KCkNvbmRhIG11c3Qta25vdzoKCi0gQSB0b29sIGZvciBtYW5hZ2luZyBzb2Z0d2FyZSBlbnZpcm9ubWVudHMKLSBDcmVhdGUgYW4gZW52aXJvbm1lbnQKLSBBY3RpdmF0ZSBhbmQgZGVhY3RpdmF0ZSBhbiBlbnZpcm9ubWVudAoKIyMgQ29uZGEgQWN0aXZhdGUgLyBEZWFjdGl2YXRlIEV4ZXJjaXNlCgoxLiBMZWFybiBhYm91dCB0aGUgYHdoaWNoYCBjb21tYW5kIC0gdXNlIHRvIHJldmVhbCB0aGUgcGF0aCB0byBhIHNwZWNpZmljIHNvZnR3YXJlCjIuIFRyeSBgd2hpY2ggcHl0aG9uYAozLiBEZWFjdGl2YXRlIG91ciBjdXJyZW50IHNoYXJlZCBlbnZpcm9ubWVudCB3aXRoIGBjb25kYSBkZWFjdGl2YXRlYAo0LiBUcnkgYHdoaWNoIHB5dGhvbmAgYWdhaW4gLSBJcyBpdCBkaWZmZXJlbnQgbm93Pwo1LiBBY3RpdmF0ZSB0aGUgZW52aXJvbm1lbnQgYWdhaW4gd2l0aCBgY29uZGEgYWN0aXZhdGUgL3dvcmtzaG9wL2NvbmRhL3JzZGAKCgojIyBDb25kYSBDcmVhdGUgU2ltcGxlIEV4ZXJjaXNlCgoxLiBDaGVjayB3aGljaCBweXRob24gdmVyc2lvbiB3ZSBoYXZlIGluIG91ciBjdXJyZW50IGVudmlyb25tZW50CjIuIENyZWF0ZSBhIHNpbXBsZSBjb25kYSBlbnZpcm9ubWVudCBuYW1lZCBgcHkzNmAgdGhhdCBjb250YWlucyBweXRob24gMy42IC0gdXNlIHRoZSBgYmlvY29uZGFgIGNoYW5uZWwKMy4gQWN0aXZhdGUgdGhlIG5ldyBgcHkzNmAgZW52aXJvbm1lbnQgYW5kIHZlcmlmeSB0aGF0IHlvdSBub3cgaGF2ZSBweXRob24gMy42CjQuIERlYWN0aXZhdGUgb3VyIGBweTM2YCBlbnZpcm9ubWVudAoKYGBgCiMgQ2hlY2sgd2hpY2ggcHl0aG9uIHZlcnNpb24gd2UncmUgdXNpbmcgaW4gb3VyIGN1cnJlbnQgZW52aXJvbm1lbnQKcHl0aG9uIC0tdmVyc2lvbgojIENyZWF0ZSBhIGNvbmRhIGVudmlyb25tZW50IHdpdGggcHl0aG9uIHZlcnNpb24gMy42LCB1c2luZyB0aGUgYmlvY29uZGEgY2hhbm5lbApjb25kYSBjcmVhdGUgLW4gcHkzNiAtYyBiaW9jb25kYSBweXRob249My42CiMgQWN0aXZhdGUgb3VyIG5ldyBjb25kYSBlbnZpcm9ubWVudApjb25kYSBhY3RpdmF0ZSBweTM2CiMgQ2hlY2sgb3VyIHB5dGhvbiB2ZXJzaW9uIG5vdyAoaXQgc2hvdWxkIGJlIDMuNikKcHl0aG9uIC0tdmVyc2lvbgojIERlYWN0aXZhdGUgb3VyIGVudmlyb25tZW50CmNvbmRhIGRlYWN0aXZhdGUKYGBgCgo8YnI+CgojIyBDb25kYSBDcmVhdGUgRXhlcmNpc2UKCkJlZm9yZSBzdGFydGluZyBvdXIgY29uZGEgZXhlcmNpc2UsIHdlIHNob3VsZCBtYWtlIHN1cmUgdGhhdCB3ZSBhcmUgb24gdGhlIHNhbWUgcGFnZS4gRm9sbG93IHRoZSBsaW5rIGJlbG93OgoKW0NvbmRhIGNyZWF0ZSBleGVyY2lzZV0oTW9kdWxlMDVfYnJlYWtvdXQwNF9leC5odG1sKQoKPGJyPgo8YnI+CgotLS0KClRoZXNlIG1hdGVyaWFscyBoYXZlIGJlZW4gYWRhcHRlZCBhbmQgZXh0ZW5kZWQgZnJvbSBtYXRlcmlhbHMgY3JlYXRlZCBieSB0aGUgW0hhcnZhcmQgQ2hhbiBCaW9pbmZvcm1hdGljcyBDb3JlIChIQkMpXShodHRwOi8vYmlvaW5mb3JtYXRpY3Muc3BoLmhhcnZhcmQuZWR1LykuIFRoZXNlIGFyZSBvcGVuIGFjY2VzcyBtYXRlcmlhbHMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBbQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbiBsaWNlbnNlIChDQyBCWSA0LjApXShodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS80LjAvKSwgd2hpY2ggcGVybWl0cyB1bnJlc3RyaWN0ZWQgdXNlLCBkaXN0cmlidXRpb24sIGFuZCByZXByb2R1Y3Rpb24gaW4gYW55IG1lZGl1bSwgcHJvdmlkZWQgdGhlIG9yaWdpbmFsIGF1dGhvciBhbmQgc291cmNlIGFyZSBjcmVkaXRlZC4KCjxici8+Cjxici8+Cjxoci8+CnwgW1ByZXZpb3VzIGxlc3Nvbl0oTW9kdWxlMDRfQWxpZ25tZW50X1FDX2FuZF9RdWFudGlmaWNhdGlvbi5odG1sKSB8IFtUb3Agb2YgdGhpcyBsZXNzb25dKCN0b3ApIHwgW05leHQgbGVzc29uXShNb2R1bGUwNl9ERUFuYWx5c2lzU2V0dXAuaHRtbCkgfAp8IDotLS0gfCA6LS0tLTogfCAtLS06IHwK