-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgvhdVignette.Rmd
185 lines (133 loc) · 7.11 KB
/
gvhdVignette.Rmd
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
---
title: "Transforming the GvHD set into flowDashboard Objects"
author: "Ted Laderas"
date: "8/4/2017"
output: html_document
---
```{r setup, include=FALSE}
library(knitr)
knitr::opts_chunk$set(echo = TRUE, warning=FALSE, message=FALSE)
knitr::opts_knit$set(root.dir = normalizePath("../"))
```
## flowDashboard Demo
The following document is a guide to how the various objects were generated for the `sampleDashboard` app from a `GatingSet`.
The strength of having different display objects instead of the `GatingSet` are: 1) Each object can be associated with an analysis step, 2) each object handles error handling and display options in a seamless way, populating the modules with very little debugging on the user's part, 3) exploratory data analysis of the flow data can be done in a seamless way, aggregating on notations.
## Creating a GatingSet from GvHD Data
This code was taken from the `flowWorkspace` documentation. Note that we take the incoming `flowSet` and convert it to a `ncdfFlowSet`. In general, we find this file format is more stable, especially when generating plots.
```{r}
## This code was modified from flowWorkspace examples
library(flowStats)
data(GvHD)
#select raw flow data and cast as ncdfFlowSet
fs<-ncdfFlowSet(GvHD)
pData(fs)$Visit <- ordered(pData(fs)$Visit)
pData(fs)$Days <- ordered(pData(fs)$Days)
#transform the raw data
tf <- transformList(colnames(fs[[1]])[3:6], asinh, transformationId="asinh")
fs_trans<-transform(fs,tf)
#add transformed data to a GatingSet
gs <- GatingSet(fs_trans)
gs
getNodes(gs[[1]]) #only contains root node
#add one gate
rg <- rectangleGate("FSC-H"=c(200,400), "SSC-H"=c(250, 400),
filterId="rectangle")
nodeID<-add(gs, rg)#it is added to root node by default if parent is not specified
nodeID
getNodes(gs[[1]]) #the second population is named after filterId of the gate
#add a quadGate
qg <- quadGate("FL1-H"=2, "FL2-H"=4)
nodeIDs<-add(gs,qg,parent="rectangle")
nodeIDs #quadGate produces four population nodes
getNodes(gs[[1]]) #population names are named after dimensions of gate if not specified
#do the actual gating
recompute(gs)
```
## Building Data Objects
Now that the `GvHD` data is gated and in a `GatingSet`, we can build the various objects. First we look at the markers and pick three markers as markers for general QC. Annotation is derived from the `phenoData` slot of `gs@data`. Here, we sample our data using only 1000 points per sample, in order to save memory.
```{r}
#show annotation
pD <- pData(parameters(gs@data[[1]]))
qcMarkers <- pD$desc[-c(6)]
#show markers in data
qcMarkers
library(flowDashboard)
##build QCO object
QCO <- QCOFromGatingSet(gs,samplePop = 1000,qcMarkers = qcMarkers)
##show structure of qcFlowObj
QCO
```
Things to notice: `QCO` has three main slots: `QCO$qcData`, which holds the expression data, `QCO$annotation`, which holds the annotation, and `QCO$mapVar`, which is the key mapping `QCO$annotation` into `QCO$data`.
Additionally, there are multiple methods that alter display options. Once these are set, the UI elements are generated automatically from the object.
+ `QCO$setAnnotationDisplayOptions()` - this controls what annotation columns to display (supplied as a vector of column names) in the hover tooltip when you mouse over the heatmap. This method checks to see that the column names supplied exist within `QCO$annotation`.
+ `QCO$setSubsetAndSortOptions()` - this controls what columns to subset on and sort on (supplied as a vector of column names) in the subset module. This also checks to see that the column names exist in `QCO$annotation`.
Note that `QCO` has a slot called `objId`. This is the identifier used when using `QCO` in one of `flowDashboard`'s shiny modules. Having unique identfiers for each object helps to avoid namespace collisions in the shiny modules. By default, the identifer is randomly generated, though the user can override the default, either by specifying `objId` as an argument in the `QCOfromGatingSet()` function, or when invoking the modules separately. This `objId` lets the `flowDashboard` modules work together, or work separately (more on that later).
```{r}
QCO$objId
```
If we use the `returnMergedData()` method, we can see the underlying merged data/annotation. We keep these two data tables separate in order to save space (avoiding redundant information), and because different display methods require either the annotation or the underlying data.
```{r}
kable(QCO$returnMergedData()[1:15,])
```
Here we build the `gatingObj` from the `GatingSet`. We also create all of the relevant gating plots. Note that if you have a lot of samples and a lot of gates, the plotting can take a while.
```{r eval=FALSE}
#run this code if you want to generate the images as well
GO <- GOFromGatingSet(gs,imageDir = "data/gating/", makeGraphs = TRUE)
```
```{r}
#graphs not generated in this vignette -run the above code if you want to
GO <- GOFromGatingSet(gs,imageDir = "data/gating/", makeGraphs = FALSE, objId="GO-UPCWK13")
##show structure of gatingObj
GO
```
Again, we can see the merged data table from `GO` by using the `returnMergedData()` method built into `GO`:
```{r}
kable(GO$returnMergedData()[1:30,])
```
Finally, we build a `populationExpressionObj` called `PEO` from the `GatingSet`. We limit our samples to
```{r}
PEO <- PEOFromGatingSet(gs, samplePop = 1000)
PEO
```
We want to remove `Time` as a marker from PEO:
```{r}
markers <- as.character(PEO$markers)
markers
PEO$setMarkers(markers[1:7])
```
Viewing the merged data table from `PEO`:
```{r}
kable(PEO$returnMergedData()[1:30,])
```
Save all objects into a new Rda:
```{r}
save(PEO, GO, QCO, file="data/GvHD.rda")
```
## Reference Shiny App
The reference shiny app can be seen at https://tladeras.shinyapps.io/sampleFlowDashboard/
## Subsetting Module
In the app, in our `server.R`, we extract the annotation in order to make it a `reactive` that is subsettable and that has a common interface.
For example, for our `gatingObj` `GO`, we create the following `subsetModule`, which is used as an input for the gatingModuleOutput module created by `gatingModuleOutputGGFromGO()`. Note that we just pass the reactive name `annotationGO` and not the evaluation `annotationGO()`.
```{r eval=FALSE}
#look for this code in server.R
annotationGO <- subsetModuleDCO(input, output, dataObj = GO)
gatingModuleOutputGGFromGO(input, output, session, GO, annotation=annotationGO)
```
In `ui.R`, there is a corresponding entry that generates the subsetting UI, and the UI for the gatingModule itself:
```{r eval=FALSE}
#this is put in a conditional panel to work with shinydashboard
subsetModuleUICDO(GO)
#this is put into a tabPanel
gatingModuleUIFromGO(GO)
```
### Not Using a Subset Module
If you don't want to use the `subsetModule` for a visualization, you can do the following in your `server.R` to generate an annotation `reactive`. Note that `gatingModuleOutputGGFromGO` expects a `reactive` in its `annotation` argument.
```{r eval=FALSE}
annotationGO <- reactive({GO$annotation})
gatingModuleOutputGGFromGO(input, output, session, GO, annotation=annotationGO)
```
And put this in your `ui.R`:
```{r eval=FALSE}
#this is put into a tabPanel
gatingModuleUIFromGO(GO)
```