%\VignetteDepends{ShortRead, GenomicFeatures, rtracklayer}
%\VignetteIndexEntry{Exercises: A Simple RNA-seq Use Case}
%\VignetteKeywords{RNAseq}
%\VignettePackage{HTSandGeneCentricLabs}

\documentclass{article}

\usepackage{BioconductorVignette}
\SweaveOpts{keep.source=TRUE, include=FALSE, eps=FALSE}

\title{Exercises: A Simple RNA-seq Use Case}

\author{Patrick Aboyoun \and
        Nicolas Delhomme \and
        Ismael Padioleau}

\date{29-30 July, 2010}

\begin{document}

\bibliographystyle{plain}

<<setup, echo=FALSE>>=
options(width = 60)
olocale=Sys.setlocale(locale="C")
@ 

\maketitle

\tableofcontents

\section{Introduction}

This file describes an RNA-seq analysis use-case.
RNA-seq\cite{Mortazavi:2008p740} was introduced as a new
method to perform Gene Expression Analysis, using the advantages of the
high throughput of Next-Generation Sequencing machines.

The goal of this use-case is to generate a count table for the selected
genetic features of interest, i.e. exons, transcripts, gene models, etc.
In the first part, we will use Bioconductor packages
\Biocpkg{ShortRead}\cite{Morgan:2009p739} and \Biocpkg{GenomicFeatures}
to define the counts for genetic features. This information will then be
exported into a wig formatted file for visualization in the UCSC
genome browser or a stand-alone genome browser like IGB.

\newpage
 
\section{Single sample use case}

In this section, we will demonstrate how to generate a count table containing
the number of sequencing reads that can be assigned to given genetic features.
An expressed genetic feature can be anything from an exon to a gene-model and,
as recently published, enhancers\cite{Kim:2010p572}. In this section, we will
generate such a count table for a single sample.

\subsection{Reading the data}

We read the export file, using the \Biocpkg{ShortRead} package and
have a look at its contents.

<<load-ShortRead>>=
library(ShortRead)
@
<<read-subset-export>>=
aln <-
  readAligned(system.file("extdata", "subset_export.txt.gz",
                          package = "HTSandGeneCentricLabs"),
              type = "SolexaExport")
aln
@


\subsection{Filtering the data}

Illumina uses a built-in chastity filter that describes whether a read
cluster could be successfully sequenced, with \texttt{Y} representing
yes and \texttt{N} representing no.

<<chastity-filter>>=
table(chastity = alignData(aln)[["filtering"]],
      aligned = is.na(position(aln)),
      useNA = "ifany")
@

In this sample, roughly 36\% of the reads do not pass the chastity filter
and an additional 7.3\% do not align to the genome. Also, some of these
reads contain many ``N''s, which occurs whenever Bustard, the Illumina base
caller, could not produce a valid base call. All these reads are questionable
and can be filtered out.

We will use three types of filters on our data:
\begin{enumerate}
  \item Keep reads with at most 2 Ns.
  \item Keep only the alignments to chromosomes chr2L, chr2R, chr3L, chr3R,
    and chr4.
  \item Use Illumina's chastity filter.
\end{enumerate}

<<filter-subset-export>>=
nFilt <- nFilter(2)
chrFilt <- chromosomeFilter(regex = "chr[0-9]")
library(HTSandGeneCentricLabs)
cFilt <- alignDataFilter(expression(filtering=="Y"))
filt <- compose(nFilt, chrFilt, cFilt)
aln <- aln[filt(aln)]
aln
@

We are now left with 46,070 ``valid'' alignments, which we want to
assign to their respective exon. For this we need to get the proper
genomic and genetic information.

The \Rclass{AlignedRead} contain is not idea for performing interval
overlap calculations, so we will create a \Rclass{GRanges} instance
that contains the alignment locations. Since this RNA-seq protocol
could not discern strand information, we will set all strand locations
to the wildcard \texttt{*}.

<<alnRanges>>=
alnRanges <- as(aln, "GRanges")
strand(alnRanges) <- "*"
@


\subsection{Obtaining the transcript annotation}

To assign the alignments to their respective exons, we
need to know the genome composition of the model organism
``Drosophila melanogaster''. We can obtain this information using
the \Biocpkg{GenomicFeatures}, which can create annotation databases
using either Biomart or UCSC as a resource. For the purposes of our
analysis, we will use Biomart.

<<load-GenomicFeatures>>=
library(GenomicFeatures)
@

The code to make this from Biomart is

<<make-TxDb-from-Biomart, eval=FALSE>>=
dmTxDb <-
  makeTranscriptDbFromBiomart(biomart = "ensembl",
                              dataset =
                              "dmelanogaster_gene_ensembl")
@

\noindent
but we will load a local copy for expediency.

<<load-TxDb>>=
dmTxDb <-
  loadFeatures(system.file("extdata", "dmTxDb.sqlite",
                           package = "HTSandGeneCentricLabs"))
dmTxDb
@

As is typical, the coding for the sequence names differ between
the experiment data and the annotation metadata, so we will
recode the \texttt{seqnames} in the alignments to coincide with
those in the transcript database.

<<renames-seqs>>=
levels(seqnames(alnRanges))
seqnames(dmTxDb)
seqnames(alnRanges) <- sub("^chr", "", seqnames(alnRanges))
seqlengths(alnRanges) <-
  seqlengths(dmTxDb)[names(seqlengths(alnRanges))]
head(alnRanges, 3)
@


\subsection{Analysis of gene models}

Now that we have the alignment locations and the transcript
annotations, we can begin with a coarse model of a gene. For
simplicity we will start with the boundaries for each gene
based upon the transcripts in the \Robject{dmTxDb} object.
The \Rpackage{HTSandGeneCentricLabs} package contains the function
\Rfunction{geneBounds} for this purpose. Since we have limited
our examination to chromosomes 2L, 2R, 3L, 3R, and 4 in fly.

<<gene-model-counts>>=
dmGeneBounds <- HTSandGeneCentricLabs::geneBounds(dmTxDb)
dmGeneBounds <-
  dmGeneBounds[seqnames(dmGeneBounds) %in%
               levels(seqnames(alnRanges))]
head(dmGeneBounds, 3)
@

In order to determine expression levels for each of these
genes we will count the number of interval overlaps that
occur with the aligned ranges. This can be achieved using the
\Rfunction{countOverlaps} method from the \Biocpkg{GenomicRanges}
package.

<<gene-model-counts, fig=TRUE>>=
dmGeneCounts <- countOverlaps(dmGeneBounds, alnRanges)
names(dmGeneCounts) <- names(dmGeneBounds)
hist(log10(dmGeneCounts+1))
@

\begin{figure}
  \centering
  \includegraphics[width=.8\textwidth]{Exercises-SimpleRNAseqUseCase-gene-model-counts}
  \caption{Distribution of gene model interval overlaps count on the log
    scale.}
  \label{fig:gene-model-counts}
\end{figure}


\subsection{Normalizing counts}

A common way to normalize reads is to convert them to RPKM: reads per
million reads in the library per kb of transcripts. This implies
normalizing the read counts depending on the genic feature size (exon,
transcript, gene model,...) and depending on the total number of reads
sequenced for that library. \Rpackage{HTSandGeneCentricLabs} count tables
can be easily transformed into RPKM, by using the \Rfunction{rpkm} method:

<<gene-model-rpkm, fig=TRUE>>=
dmRPKM <- HTSandGeneCentricLabs::rpkm(dmGeneCounts, dmGeneBounds)
hist(log10(dmRPKM+1))
@

\begin{figure}
  \centering
  \includegraphics[width=.8\textwidth]{Exercises-SimpleRNAseqUseCase-gene-model-rpkm}
  \caption{Distribution of RPKM on the log scale.}
  \label{fig:gene-model-rpkm}
\end{figure}

\noindent
But such a count normalization is sub-optimal, as you would ``limit''
your dynamic range to the one of the library having the lowest number
of reads. A better way of normalizing the data is to use either
the \Biocpkg{edgeR}\cite{Robinson:2010p775} or
\Biocpkg{DESeq}\cite{Anders:2010p741} packages. The approaches taken
by this packages are explained in their respective vignettes.


\subsection{Differentiating amongst isoforms}

Once we have used other packages such as \Biocpkg{edgeR} and
\Biocpkg{DESeq}, we can use basic Bioconductor tools to find the
interval overlap counts for each of the exons within the known
isoforms of the annotated genes. This counting activity can be
achieved using the \Rfunction{countExonIdsByTxOverlaps} function
within the \Rpackage{HTSandGeneCentricLabs} package.

<<isoforms>>=
dmExonIdsByTxCounts <-
  HTSandGeneCentricLabs::countExonIdsByTxOverlaps(dmTxDb,
                                                  alnRanges)
dmExonIdsByTxCounts
@

The output of \Rfunction{countExonIdsByTxOverlaps} is more complex
than the typical R object. It returns a
\Rclass{CompressedSplitDataFrameList} that is split by gene ID,
where each row in the split represent a transcript. These data rows
are comprised of three columns: the transcipt id, the number of
interval overlaps for each exon within the spliced transcript, and
the total number of interval overlaps across the entire spliced
transcript. The elements in this \Rclass{CompressedSplitDataFrameList}
object are sorted in descending order by the transcript with the
largest total interval overlaps.


\subsection{\emph{De novo} transcript identification}

In theory, RNA-seq experiments can be used to identify any transcribed
molecule, since the technique is not dependent on a predefined sets of
probes like micro-arrays are. Therefore, RNA-seq is a potential useful
tool in finding unknown transcripts and isoforms, as well as regulatory
transcribed elements. To that end, several methods are available to
recreate and annotate transcripts, e.g. Oases,
Velvet\cite{Zerbino:2008p749,Zerbino:2009p743},
TopHat\cite{Trapnell:2009p156}, to cite some of them (see
\cite{Ameur:2010p280} as well), but few have been done for other
regulatory transcribed elements such as eRNAs \cite{Kim:2010p572}.
We can use Bioconductor tools to identify locus and quantify counts
without prior annotation knowledge. 

The process begins with calculating the coverage, using the method
from the \Biocpkg{GenomicRanges} package.

<<coverage>>=
cover <- coverage(alnRanges)
head(cover, 2)
@

Next the islands can be formed using the \Rfunction{slice} function.
The peak height for the islands can be found using the
\Rfunction{viewMaxs} function and the island widths can be found using
the \Rfunction{width} function.

<<islands>>=
islands <- slice(cover, 1)
islandPeakHeight <- viewMaxs(islands)
islandWidth <- width(islands)
median(islandPeakHeight)
median(islandWidth)
@

While some sophisticated bioinformatic approaches can be taken to
find exons \emph{de novo} from the RNA-seq sample, we can use a simple
approach whereby we select islands whose maximum peak height is 2 or
more and whose width is 54 bp or more. The \Rfunction{elementLengths}
function calls shows how many of these candidate exons appear on each
chromosome.

<<select-islands>>=
candidateExons <-
  islands[islandPeakHeight >= 1L & islandWidth >= 54L]
elementLengths(candidateExons)
@


\subsection{Exporting the coverage}

If we wish to visualize the coverage of the reads on the genome
in a genome browser, we can use the \Biocpkg{rtracklayer} package
to export the coverage to a wig file.

<<load-rtracklayer>>=
library(rtracklayer)
@

<<export-coverage, eval=FALSE>>=
names(cover) <- paste("chr", names(cover), sep="")
export(cover["chr4"], con = "chr4.wig")
@

You can now visualize it in a genome browser of your choice. This
is a common way to assess if the raw data you are looking at agrees
with the experimental design that was performed. However, this is still
far from being able to normalize and call differential expression between
different conditions, which is usually the goal of RNA-seq
experiments. For more information on the analysis issues, see the
\Biocpkg{DESeq}\cite{Anders:2010p741} Bioconductor package.


\section{De-multiplexing sample use case}

Nowadays, NGS machines produces so many ``raw'' reads (40M for
Illumina, 100M for SOLiD), that the coverage obtained per lane for
the transcriptome of ``small'' genome-sized organisms, is way too
big. Therefore, techniques to have several samples running as part
of the same library have been
created\cite{Lefrancois:2009p778,Smith:2010p777}, using 6bp barcodes
to uniquely identify the sample. This is called multiplexing and one
can today with an average Illumina GenomeAnalyzer GAIIx average run,
multiplex 12 yeast samples and even 2 drosophila samples in a single
lane. Actually, if the lane is very good (30M aligning reads), one can
multiplex 4 of them. This approach is very advantageous for researchers,
especially in term of costs, but it adds an additional layer of
pre-processing that is not as trivial to process as one would have
thought. Extracting the barcodes is fairly straightforward, however
the average 1 percent sequencing error rate introduces a lot of
multiplicity in the actual barcodes present in the samples and this
needs to be sorted out accordingly. A proper design of the barcodes,
maximizing the Hamming distance
(\url{http://en.wikipedia.org/wiki/Hamming\_distance}) is an essential
step for a proper de-multiplexing. 

There are two kinds of barcoding, the one described in Lefrancois
\emph{et al.} \cite{Lefrancois:2009p778} where the barcode is part of
the read sequence and the one developed by Illumina, where the
barcode is read in a separate sequencing reaction after the first
mate sequencing.

<<demultiplexing>>=
alns <-
  readAligned(system.file("extdata", "multiplex_export.txt.gz",
                          package = "HTSandGeneCentricLabs"),
              filter =
              compose(alignDataFilter(expression(filtering=="Y")),
                      nFilter(2),
                      chromosomeFilter(regex = "chr[0-9]")),
              type = "SolexaExport",
              withAll = TRUE)
indexes <- c("ACACTG", "ACTAGC", "ATGGCT", "TTGCGA")
demultAlns <-
  demultiplex(alns, indexes=indexes, edit.dist=2, indexes.qty=4,
              type="within")
@


\section{You are done, but still there is more to come...}

It is known that the standard Illumina RNA-seq protocol shows a bias
in the first 12 nucleotides of every read. It is still unclear where
this bias comes from (fragmentation, random hexamer priming, RNase H
sequence specificity), but there has been a couple of publication
recently that proposes corrections for that bias
\cite{Li:2010p732,Hansen:2010p495}. We anticipate creating some
Bioconductor functionality to correct this bias in the near future.


\section{Session Information}

The version number of R\cite{ref:R} and packages loaded for generating
the vignette were:

<<sessionInfo, results=tex, print=TRUE>>=
toLatex(sessionInfo())
@


\bibliography{Exercises-SimpleRNAseqUseCase}


\end{document}
