-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrhythmicity.Rmd
More file actions
110 lines (81 loc) · 4.05 KB
/
Copy pathrhythmicity.Rmd
File metadata and controls
110 lines (81 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
---
title: "Quantifying rhythmicity in one condition"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Quantifying rhythmicity in one condition}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = '#>',
message = FALSE,
fig.align = 'center',
fig.retina = 2)
```
## Introduction
Here we show how to use `limorhyde2` to quantify rhythmicity in data from one condition. The data are based on mouse liver samples from the [circadian gene expression atlas in mammals](https://doi.org/10.1073/pnas.1408886111) ([GSE54650](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE54650)).
## Load packages
```{r load_packages}
library('data.table')
library('ggplot2')
library('limorhyde2')
# doParallel::registerDoParallel() # register a parallel backend to minimize runtime
theme_set(theme_bw())
```
## Load the data
The expression data are in a matrix with one row per gene and one column per sample. The metadata are in a table with one row per sample. To save time and space, the expression data include only a subset of genes.
```{r load_data}
y = GSE54650$y
y[1:5, 1:5]
metadata = GSE54650$metadata
metadata
```
## Fit linear models
The first step is to fit a series of linear models based on periodic splines for each genomic feature, in this case each gene, using [limma](https://doi.org/doi:10.18129/B9.bioc.limma). `getModelFit()` takes several arguments besides the expression data and metadata, but here we just use the defaults. For example, the data are from one condition, so we leave `condColname` as `NULL`. Also, the expression data are from microarrays and already log-transformed, so we leave `method` as `'trend'`.
```{r model_fit}
fit = getModelFit(y, metadata)
```
## Get posterior fits
The next step is obtain posterior estimates of the model coefficients using [multivariate adaptive shrinkage](https://doi.org/10.1038/s41588-018-0268-8) ([mashr](https://stephenslab.github.io/mashr/index.html)), which learns patterns in the data and accounts for noise in the original fits.
```{r posterior_fit}
fit = getPosteriorFit(fit)
```
## Get rhythm statistics
We can now use the posterior fits to compute rhythm statistics, i.e. properties of the curve, for each gene.
```{r rhythm_stats}
rhyStats = getRhythmStats(fit)
```
We can examine the distributions of the statistics in various ways, such as ranking genes by peak-to-trough amplitude (no p-values necessary) or plotting peak-to-trough amplitude vs. peak phase.
```{r plot_stats, fig.width = 5, fig.height = 4}
print(rhyStats[order(-peak_trough_amp)], nrows = 10L)
ggplot(rhyStats) +
geom_point(aes(x = peak_phase, y = peak_trough_amp), alpha = 0.2) +
xlab('Peak phase (h)') +
ylab('Peak-to-trough amplitude (norm.)') +
scale_x_continuous(breaks = seq(0, 24, 4))
```
## Get observed and fitted time-courses
We can also compute the expected measurements for one or more genes at one or more time-points, which correspond to the fitted curves. Here we plot the posterior fits and observed expression for three of the top rhythmic genes (converting from gene id to gene symbol).
```{r expected_meas}
genes = data.table(
id = c('13088', '13170', '13869'),
symbol = c('Cyp2b10', 'Dbp', 'Erbb4'))
measFit = getExpectedMeas(fit, times = seq(0, 24, 0.5), features = genes$id)
measFit[genes, symbol := i.symbol, on = .(feature = id)]
print(measFit, nrows = 10L)
```
Next we combine the observed expression data and metadata. The curves show how `limorhyde2` is able to fit non-sinusoidal rhythms.
```{r plot_timecourse, fig.width = 7, fig.height = 2.25}
measObs = mergeMeasMeta(y, metadata, features = genes$id)
measObs[genes, symbol := i.symbol, on = .(feature = id)]
print(measObs, nrows = 10L)
ggplot() +
facet_wrap(vars(symbol), scales = 'free_y', nrow = 1) +
geom_line(aes(x = time, y = value), data = measFit) +
geom_point(aes(x = time %% 24, y = meas), shape = 21, size = 1.5,
data = measObs) +
labs(x = 'Circadian time (h)', y = 'Expression (norm.)') +
scale_x_continuous(breaks = seq(0, 24, 4))
```