S4 classes are the perfect examples of the OO programming: - stricter structure - they have representations: a list of slots or arguments by name and class - the slots have to have the correct type - methods - they also inherit the methods from the classes of the arguments, but inheritence is between S4 classes as well. - has to be created with the new constructor - they have accessor methods as well.

setClass("Person", representation(name = "character", age = "numeric"))
setClass("Employee", representation(boss = "Person"), contains = "Person")

person1 <- new("Person", name="Peter", age=34)
boss1 <- new("Employee", boss=person1, name="Lisa", age=36)
person1
## An object of class "Person"
## Slot "name":
## [1] "Peter"
## 
## Slot "age":
## [1] 34
boss1
## An object of class "Employee"
## Slot "boss":
## An object of class "Person"
## Slot "name":
## [1] "Peter"
## 
## Slot "age":
## [1] 34
## 
## 
## Slot "name":
## [1] "Lisa"
## 
## Slot "age":
## [1] 36

Example class: SummarizedExperiment

Representation:

RangedSummarizedExperiment is an extension of SummarizedExperiment. It uses GRanges to define the genomic regions.

## Loading required package: MatrixGenerics
## Loading required package: matrixStats
## 
## Attaching package: 'MatrixGenerics'
## The following objects are masked from 'package:matrixStats':
## 
##     colAlls, colAnyNAs, colAnys, colAvgsPerRowSet, colCollapse,
##     colCounts, colCummaxs, colCummins, colCumprods, colCumsums,
##     colDiffs, colIQRDiffs, colIQRs, colLogSumExps, colMadDiffs,
##     colMads, colMaxs, colMeans2, colMedians, colMins, colOrderStats,
##     colProds, colQuantiles, colRanges, colRanks, colSdDiffs, colSds,
##     colSums2, colTabulates, colVarDiffs, colVars, colWeightedMads,
##     colWeightedMeans, colWeightedMedians, colWeightedSds,
##     colWeightedVars, rowAlls, rowAnyNAs, rowAnys, rowAvgsPerColSet,
##     rowCollapse, rowCounts, rowCummaxs, rowCummins, rowCumprods,
##     rowCumsums, rowDiffs, rowIQRDiffs, rowIQRs, rowLogSumExps,
##     rowMadDiffs, rowMads, rowMaxs, rowMeans2, rowMedians, rowMins,
##     rowOrderStats, rowProds, rowQuantiles, rowRanges, rowRanks,
##     rowSdDiffs, rowSds, rowSums2, rowTabulates, rowVarDiffs, rowVars,
##     rowWeightedMads, rowWeightedMeans, rowWeightedMedians,
##     rowWeightedSds, rowWeightedVars
## Loading required package: GenomicRanges
## Loading required package: stats4
## Loading required package: BiocGenerics
## Loading required package: parallel
## 
## Attaching package: 'BiocGenerics'
## The following objects are masked from 'package:parallel':
## 
##     clusterApply, clusterApplyLB, clusterCall, clusterEvalQ,
##     clusterExport, clusterMap, parApply, parCapply, parLapply,
##     parLapplyLB, parRapply, parSapply, parSapplyLB
## The following objects are masked from 'package:stats':
## 
##     IQR, mad, sd, var, xtabs
## The following objects are masked from 'package:base':
## 
##     anyDuplicated, append, as.data.frame, basename, cbind, colnames,
##     dirname, do.call, duplicated, eval, evalq, Filter, Find, get, grep,
##     grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget,
##     order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank,
##     rbind, Reduce, rownames, sapply, setdiff, sort, table, tapply,
##     union, unique, unsplit, which.max, which.min
## Loading required package: S4Vectors
## 
## Attaching package: 'S4Vectors'
## The following objects are masked from 'package:base':
## 
##     expand.grid, I, unname
## Loading required package: IRanges
## Loading required package: GenomeInfoDb
## Loading required package: Biobase
## Welcome to Bioconductor
## 
##     Vignettes contain introductory material; view with
##     'browseVignettes()'. To cite Bioconductor, see
##     'citation("Biobase")', and for packages 'citation("pkgname")'.
## 
## Attaching package: 'Biobase'
## The following object is masked from 'package:MatrixGenerics':
## 
##     rowMedians
## The following objects are masked from 'package:matrixStats':
## 
##     anyMissing, rowMedians
data("airway_small",  package="BasicR")

se <- airway_small

Accessors

To know all this, look for the help and the vignette.

## DataFrame with 8 rows and 9 columns
##            SampleName     cell      dex    albut        Run avgLength
##              <factor> <factor> <factor> <factor>   <factor> <integer>
## SRR1039508 GSM1275862  N61311     untrt    untrt SRR1039508       126
## SRR1039509 GSM1275863  N61311     trt      untrt SRR1039509       126
## SRR1039512 GSM1275866  N052611    untrt    untrt SRR1039512       126
## SRR1039513 GSM1275867  N052611    trt      untrt SRR1039513        87
## SRR1039516 GSM1275870  N080611    untrt    untrt SRR1039516       120
## SRR1039517 GSM1275871  N080611    trt      untrt SRR1039517       126
## SRR1039520 GSM1275874  N061011    untrt    untrt SRR1039520       101
## SRR1039521 GSM1275875  N061011    trt      untrt SRR1039521        98
##            Experiment    Sample    BioSample
##              <factor>  <factor>     <factor>
## SRR1039508  SRX384345 SRS508568 SAMN02422669
## SRR1039509  SRX384346 SRS508567 SAMN02422675
## SRR1039512  SRX384349 SRS508571 SAMN02422678
## SRR1039513  SRX384350 SRS508572 SAMN02422670
## SRR1039516  SRX384353 SRS508575 SAMN02422682
## SRR1039517  SRX384354 SRS508576 SAMN02422673
## SRR1039520  SRX384357 SRS508579 SAMN02422683
## SRR1039521  SRX384358 SRS508580 SAMN02422677
## DataFrame with 4001 rows and 0 columns
#assay(se)
rowRanges(se)
## GRangesList object of length 4001:
## $ENSG00000000003
## GRanges object with 17 ranges and 2 metadata columns:
##        seqnames            ranges strand |   exon_id       exon_name
##           <Rle>         <IRanges>  <Rle> | <integer>     <character>
##    [1]        X 99883667-99884983      - |    667145 ENSE00001459322
##    [2]        X 99885756-99885863      - |    667146 ENSE00000868868
##    [3]        X 99887482-99887565      - |    667147 ENSE00000401072
##    [4]        X 99887538-99887565      - |    667148 ENSE00001849132
##    [5]        X 99888402-99888536      - |    667149 ENSE00003554016
##    ...      ...               ...    ... .       ...             ...
##   [13]        X 99890555-99890743      - |    667156 ENSE00003512331
##   [14]        X 99891188-99891686      - |    667158 ENSE00001886883
##   [15]        X 99891605-99891803      - |    667159 ENSE00001855382
##   [16]        X 99891790-99892101      - |    667160 ENSE00001863395
##   [17]        X 99894942-99894988      - |    667161 ENSE00001828996
##   -------
##   seqinfo: 722 sequences (1 circular) from an unspecified genome
## 
## ...
## <4000 more elements>
#assays(se)[[1]]
head(assays(se)$counts)
##                 SRR1039508 SRR1039509 SRR1039512 SRR1039513 SRR1039516
## ENSG00000000003        679        448        873        408       1138
## ENSG00000000005          0          0          0          0          0
## ENSG00000000419        467        515        621        365        587
## ENSG00000000457        260        211        263        164        245
## ENSG00000000460         60         55         40         35         78
## ENSG00000000938          0          0          2          0          1
##                 SRR1039517 SRR1039520 SRR1039521
## ENSG00000000003       1047        770        572
## ENSG00000000005          0          0          0
## ENSG00000000419        799        417        508
## ENSG00000000457        331        233        229
## ENSG00000000460         63         76         60
## ENSG00000000938          0          0          0
head(metadata(airway_small))
## [[1]]
## Experiment data
##   Experimenter name: Himes BE 
##   Laboratory: NA 
##   Contact information:  
##   Title: RNA-Seq transcriptome profiling identifies CRISPLD2 as a glucocorticoid responsive gene that modulates cytokine function in airway smooth muscle cells. 
##   URL: http://www.ncbi.nlm.nih.gov/pubmed/24926665 
##   PMIDs: 24926665 
## 
##   Abstract: A 226 word abstract is available. Use 'abstract' method.

You can access each data “natively”, and even change it, but you shouldn’t do that. Why? It is easy to screw it up…

se@rowRanges
## GRangesList object of length 4001:
## $ENSG00000000003
## GRanges object with 17 ranges and 2 metadata columns:
##        seqnames            ranges strand |   exon_id       exon_name
##           <Rle>         <IRanges>  <Rle> | <integer>     <character>
##    [1]        X 99883667-99884983      - |    667145 ENSE00001459322
##    [2]        X 99885756-99885863      - |    667146 ENSE00000868868
##    [3]        X 99887482-99887565      - |    667147 ENSE00000401072
##    [4]        X 99887538-99887565      - |    667148 ENSE00001849132
##    [5]        X 99888402-99888536      - |    667149 ENSE00003554016
##    ...      ...               ...    ... .       ...             ...
##   [13]        X 99890555-99890743      - |    667156 ENSE00003512331
##   [14]        X 99891188-99891686      - |    667158 ENSE00001886883
##   [15]        X 99891605-99891803      - |    667159 ENSE00001855382
##   [16]        X 99891790-99892101      - |    667160 ENSE00001863395
##   [17]        X 99894942-99894988      - |    667161 ENSE00001828996
##   -------
##   seqinfo: 722 sequences (1 circular) from an unspecified genome
## 
## ...
## <4000 more elements>
se@metadata
## [[1]]
## Experiment data
##   Experimenter name: Himes BE 
##   Laboratory: NA 
##   Contact information:  
##   Title: RNA-Seq transcriptome profiling identifies CRISPLD2 as a glucocorticoid responsive gene that modulates cytokine function in airway smooth muscle cells. 
##   URL: http://www.ncbi.nlm.nih.gov/pubmed/24926665 
##   PMIDs: 24926665 
## 
##   Abstract: A 226 word abstract is available. Use 'abstract' method.
###don't do this:
se@rowRanges <- se@rowRanges[1:3000]
se
## class: RangedSummarizedExperiment 
## dim: 4001 8 
## metadata(1): ''
## assays(1): counts
## rownames(3000): ENSG00000000003 ENSG00000000005 ... ENSG00000162951
##   ENSG00000162959
## rowData names(0):
## colnames(8): SRR1039508 SRR1039509 ... SRR1039520 SRR1039521
## colData names(9): SampleName cell ... Sample BioSample
se@rowRanges
## GRangesList object of length 3000:
## $ENSG00000000003
## GRanges object with 17 ranges and 2 metadata columns:
##        seqnames            ranges strand |   exon_id       exon_name
##           <Rle>         <IRanges>  <Rle> | <integer>     <character>
##    [1]        X 99883667-99884983      - |    667145 ENSE00001459322
##    [2]        X 99885756-99885863      - |    667146 ENSE00000868868
##    [3]        X 99887482-99887565      - |    667147 ENSE00000401072
##    [4]        X 99887538-99887565      - |    667148 ENSE00001849132
##    [5]        X 99888402-99888536      - |    667149 ENSE00003554016
##    ...      ...               ...    ... .       ...             ...
##   [13]        X 99890555-99890743      - |    667156 ENSE00003512331
##   [14]        X 99891188-99891686      - |    667158 ENSE00001886883
##   [15]        X 99891605-99891803      - |    667159 ENSE00001855382
##   [16]        X 99891790-99892101      - |    667160 ENSE00001863395
##   [17]        X 99894942-99894988      - |    667161 ENSE00001828996
##   -------
##   seqinfo: 722 sequences (1 circular) from an unspecified genome
## 
## ...
## <2999 more elements>

Methods

subsetting

# subsetting is very easy, just like with a data.frame

se <- se[1:2000,]

se <- se[,1:3]

se
## class: RangedSummarizedExperiment 
## dim: 2000 3 
## metadata(1): ''
## assays(1): counts
## rownames(2000): ENSG00000000003 ENSG00000000005 ... ENSG00000092758
##   ENSG00000092820
## rowData names(0):
## colnames(3): SRR1039508 SRR1039509 SRR1039512
## colData names(9): SampleName cell ... Sample BioSample

Combining

rowbinded <- rbind(se, se)
rowbinded
## class: RangedSummarizedExperiment 
## dim: 4000 3 
## metadata(2): '' ''
## assays(1): counts
## rownames(4000): ENSG00000000003 ENSG00000000005 ... ENSG00000092758
##   ENSG00000092820
## rowData names(0):
## colnames(3): SRR1039508 SRR1039509 SRR1039512
## colData names(9): SampleName cell ... Sample BioSample
colbinded <- cbind(se, se)
colbinded
## class: RangedSummarizedExperiment 
## dim: 2000 6 
## metadata(2): '' ''
## assays(1): counts
## rownames(2000): ENSG00000000003 ENSG00000000005 ... ENSG00000092758
##   ENSG00000092820
## rowData names(0):
## colnames(6): SRR1039508 SRR1039509 ... SRR1039509 SRR1039512
## colData names(9): SampleName cell ... Sample BioSample
roi <- GRanges(seqnames="X", ranges=99800000:99850000)
se_1 <- subsetByOverlaps(se, roi)

Granges and GRangesList

GRanges objects store information about Genomic ranges with chromosome, position and additional information. Offers a wide range of functionality. GRangesList is a “grouped” version of GRnages, it is similar to a normal list, but with additional functionality. Both of them are able to handle strand information as well.

library(GenomicRanges)

gr1 <- GRanges(
    seqnames = "chr2",
    ranges = IRanges(103, 106),
    strand = "+",
    score = 5L, GC = 0.45)
gr2 <- GRanges(
    seqnames = c("chr1", "chr3"),
    ranges = IRanges(c(107, 113), width = 3),
    strand = c("+", "-"),
    score = 3:4, GC = c(0.3, 0.5))
gr3 <- GRanges("chr2:102-107")

gr4 <- makeGRangesFromDataFrame(data.frame(chr=c("chr1", "chr2"), 
                                           start=c(104, 104), end=c(108, 105),
                                           name=c("gene1", "gene2")), keep.extra.columns = T, ignore.strand = T)
grl <- GRangesList("txA" = gr1, "txB" = gr2)
grl
## GRangesList object of length 2:
## $txA
## GRanges object with 1 range and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr2   103-106      + |         5      0.45
##   -------
##   seqinfo: 3 sequences from an unspecified genome; no seqlengths
## 
## $txB
## GRanges object with 2 ranges and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr1   107-109      + |         3       0.3
##   [2]     chr3   113-115      - |         4       0.5
##   -------
##   seqinfo: 3 sequences from an unspecified genome; no seqlengths
#seqinfo(gr1) <- Seqinfo(genome="hg38")
#can have names for each row

Accessors

seqnames(gr1)
## factor-Rle of length 1 with 1 run
##   Lengths:    1
##   Values : chr2
## Levels(1): chr2
seqlevels(gr1)
## [1] "chr2"
ranges(gr1)
## IRanges object with 1 range and 0 metadata columns:
##           start       end     width
##       <integer> <integer> <integer>
##   [1]       103       106         4
start(gr1)
## [1] 103
end(gr1)
## [1] 106
strand(gr1)
## factor-Rle of length 1 with 1 run
##   Lengths: 1
##   Values : +
## Levels(3): + - *
width(gr1)
## [1] 4
length(gr1)
## [1] 1
mcols(gr4)
## DataFrame with 2 rows and 1 column
##          name
##   <character>
## 1       gene1
## 2       gene2
mcols(gr4)$name
## [1] "gene1" "gene2"

Subsetting

#data.frame-like

gr1[1,]
## GRanges object with 1 range and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr2   103-106      + |         5      0.45
##   -------
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths
gr4[1, "name"]
## GRanges object with 1 range and 1 metadata column:
##       seqnames    ranges strand |        name
##          <Rle> <IRanges>  <Rle> | <character>
##   [1]     chr1   104-108      * |       gene1
##   -------
##   seqinfo: 2 sequences from an unspecified genome; no seqlengths
# subset function
subset(gr1, strand == "+")
## GRanges object with 1 range and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr2   103-106      + |         5      0.45
##   -------
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths

Splitting and combining

sp <- split(gr2, 1:2)
split(gr4, ~ name)
## GRangesList object of length 2:
## $gene1
## GRanges object with 1 range and 1 metadata column:
##       seqnames    ranges strand |        name
##          <Rle> <IRanges>  <Rle> | <character>
##   [1]     chr1   104-108      * |       gene1
##   -------
##   seqinfo: 2 sequences from an unspecified genome; no seqlengths
## 
## $gene2
## GRanges object with 1 range and 1 metadata column:
##       seqnames    ranges strand |        name
##          <Rle> <IRanges>  <Rle> | <character>
##   [1]     chr2   104-105      * |       gene2
##   -------
##   seqinfo: 2 sequences from an unspecified genome; no seqlengths
c(sp[[1]], sp[[2]])
## GRanges object with 2 ranges and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr1   107-109      + |         3       0.3
##   [2]     chr3   113-115      - |         4       0.5
##   -------
##   seqinfo: 2 sequences from an unspecified genome; no seqlengths
stack(sp, index.var="name")
## GRanges object with 2 ranges and 3 metadata columns:
##       seqnames    ranges strand |  name     score        GC
##          <Rle> <IRanges>  <Rle> | <Rle> <integer> <numeric>
##   [1]     chr1   107-109      + |     1         3       0.3
##   [2]     chr3   113-115      - |     2         4       0.5
##   -------
##   seqinfo: 2 sequences from an unspecified genome; no seqlengths

Aggregating

aggregate(gr2, score ~ strand, mean)
## DataFrame with 2 rows and 2 columns
##     strand     score
##   <factor> <numeric>
## 1        +         3
## 2        -         4

Interval operations

flank(gr1, 10, both=T)
## GRanges object with 1 range and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr2    93-112      + |         5      0.45
##   -------
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths
shift(gr2, 5)
## GRanges object with 2 ranges and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr1   112-114      + |         3       0.3
##   [2]     chr3   118-120      - |         4       0.5
##   -------
##   seqinfo: 2 sequences from an unspecified genome; no seqlengths
resize(gr1, 20)
## GRanges object with 1 range and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr2   103-122      + |         5      0.45
##   -------
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths
c(gr1, gr3)
## GRanges object with 2 ranges and 2 metadata columns:
##       seqnames    ranges strand |     score        GC
##          <Rle> <IRanges>  <Rle> | <integer> <numeric>
##   [1]     chr2   103-106      + |         5      0.45
##   [2]     chr2   102-107      * |      <NA>        NA
##   -------
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths
 reduce(c(gr1, gr3)) # combines the overlapping ranges
## GRanges object with 2 ranges and 0 metadata columns:
##       seqnames    ranges strand
##          <Rle> <IRanges>  <Rle>
##   [1]     chr2   103-106      +
##   [2]     chr2   102-107      *
##   -------
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths
 reduce(c(gr1, gr3), ignore.strand=T)
## GRanges object with 1 range and 0 metadata columns:
##       seqnames    ranges strand
##          <Rle> <IRanges>  <Rle>
##   [1]     chr2   102-107      *
##   -------
##   seqinfo: 1 sequence from an unspecified genome; no seqlengths

Comapring 2 GRanges

#union(gr2, gr4)

#intersect(gr2, gr4)
#setdiff(gr2, gr4)

#hits <- findOverlaps(gr2, gr4, ignore.strand=TRUE)
#countOverlaps(gr2, gr4, ignore.strand=TRUE)
#subsetByOverlaps(gr2, gr4)

DeSeq2

library("pasilla")
pasCts <- system.file("extdata",
                      "pasilla_gene_counts.tsv",
                      package="pasilla", mustWork=TRUE)
pasAnno <- system.file("extdata",
                       "pasilla_sample_annotation.csv",
                       package="pasilla", mustWork=TRUE)
cts <- as.matrix(read.csv(pasCts,sep="\t",row.names="gene_id"))
coldata <- read.csv(pasAnno, row.names=1)
coldata <- coldata[,c("condition","type")]

rownames(coldata) <- sub("fb", "", rownames(coldata))
cts <- cts[, rownames(coldata)]

library("DESeq2")
dds <- DESeqDataSetFromMatrix(countData = cts,
                              colData = coldata,
                              design = ~ condition)
## Warning in DESeqDataSet(se, design = design, ignoreRank): some variables in
## design formula are characters, converting to factors
dds
## class: DESeqDataSet 
## dim: 14599 7 
## metadata(1): version
## assays(1): counts
## rownames(14599): FBgn0000003 FBgn0000008 ... FBgn0261574 FBgn0261575
## rowData names(0):
## colnames(7): treated1 treated2 ... untreated3 untreated4
## colData names(2): condition type
dds <- dds[1:200,]
dds <- DESeq(dds)
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
res <- results(dds)
res
## log2 fold change (MLE): condition untreated vs treated 
## Wald test p-value: condition untreated vs treated 
## DataFrame with 200 rows and 6 columns
##                baseMean log2FoldChange     lfcSE       stat      pvalue
##               <numeric>      <numeric> <numeric>  <numeric>   <numeric>
## FBgn0000003    0.172207     -0.9986796  3.806863 -0.2623366   0.7930619
## FBgn0000008   95.873798      0.0140036  0.219868  0.0636906   0.9492166
## FBgn0000014    1.090634      0.5233543  2.215680  0.2362048   0.8132737
## FBgn0000015    0.853818      1.8909340  2.149959  0.8795209   0.3791189
## FBgn0000017 4392.045082      0.2549107  0.116978  2.1791389   0.0293213
## ...                 ...            ...       ...        ...         ...
## FBgn0000567   263.99287       1.239187  0.166174   7.457181 8.83932e-14
## FBgn0000568  3655.58621       0.220186  0.210651   1.045263 2.95901e-01
## FBgn0000575  1435.99029      -0.300818  0.175862  -1.710531 8.71677e-02
## FBgn0000576     0.00000             NA        NA         NA          NA
## FBgn0000577     0.35367       1.822069  3.491008   0.521932 6.01718e-01
##                    padj
##               <numeric>
## FBgn0000003    0.994466
## FBgn0000008    0.996580
## FBgn0000014    0.994466
## FBgn0000015    0.817888
## FBgn0000017    0.189072
## ...                 ...
## FBgn0000567 8.26476e-12
## FBgn0000568 7.88180e-01
## FBgn0000575 3.97570e-01
## FBgn0000576          NA
## FBgn0000577 9.94466e-01

```