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

## This code was modified from flowWorkspace examples
library(flowStats)
data(GvHD)
#select raw flow data and cast as ncdfFlowSet
fs<-ncdfFlowSet(GvHD[1:20])

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
## A GatingSet with 20 samples
getNodes(gs[[1]]) #only contains root node
## [1] "root"
#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
## [1] 2
getNodes(gs[[1]]) #the second population is named after filterId of the gate
## [1] "root"       "/rectangle"
#add a quadGate
qg <- quadGate("FL1-H"=2, "FL2-H"=4)
nodeIDs<-add(gs,qg,parent="rectangle")
nodeIDs #quadGate produces four population nodes
## [1] 3 4 5 6
getNodes(gs[[1]]) #population names are named after dimensions of gate if not specified
## [1] "root"                          "/rectangle"                   
## [3] "/rectangle/CD15 FITC-CD45 PE+" "/rectangle/CD15 FITC+CD45 PE+"
## [5] "/rectangle/CD15 FITC+CD45 PE-" "/rectangle/CD15 FITC-CD45 PE-"
#do the actual gating
recompute(gs)



#dir <- paste0(tempdir(),"/gs")
#create.dir(dir)

#save_gs(dir)

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. In this example, annotation is derived from the phenoData slot of gs@data. Here, we sample our data, in order to save memory.

#load_gs(dir)
#show annotation
pD <- pData(gs@data@phenoData)
qcMarkers <- pD$desc[1:3]

#show first three markers
qcMarkers
## NULL
library(flowDashboard)
##build QCO object
QCO <- QCOFromGatingSet(gs,samplePop = 1000, qcMarkers = qcMarkers)
##show structure of qcFlowObj
QCO
## <qcFlowObj>
##   Inherits from: <commonDataObj>
##   Public:
##     annotation: data.table, data.frame
##     annotCols: Patient Visit Days Grade
##     checkIntegrity: function (reconcile = FALSE) 
##     clone: function (deep = FALSE) 
##     contextID: NULL
##     initialize: function (annotation, qcData, mapVar = NULL, checkIntegrity = TRUE, 
##     mapVar: name
##     markers: FSC.Height SSC.Height CD15.FITC CD45.PE CD14.PerCP NA. C ...
##     objId: QCO-XHGMZ85
##     qcData: data.table, data.frame
##     returnMergedData: function () 
##     setAnnotationDisplayOptions: function (annotCols) 
##     setMarkers: function (markers) 
##     setSubsetAndSortOptions: function (subsetOptions, sortOptions, checkIntegrity = TRUE) 
##     sortOptionList: NULL
##     sortOptions: Patient Visit Days Grade
##     subsetAnnotation: function (ids) 
##     subsetOptionList: list
##     subsetOptions: Patient Visit Days Grade

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 option. 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).

QCO$objId
## [1] "QCO-XHGMZ85"

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.

kable(QCO$returnMergedData()[1:15,])
idVar cellNum variable value Patient Visit Days Grade
s5a01 3186 FSC.Height 595 5 1 -6 3
s5a01 411 FSC.Height 96 5 1 -6 3
s5a01 3129 FSC.Height 100 5 1 -6 3
s5a01 569 FSC.Height 453 5 1 -6 3
s5a01 70 FSC.Height 232 5 1 -6 3
s5a01 1402 FSC.Height 90 5 1 -6 3
s5a01 786 FSC.Height 70 5 1 -6 3
s5a01 664 FSC.Height 229 5 1 -6 3
s5a01 3042 FSC.Height 160 5 1 -6 3
s5a01 3007 FSC.Height 91 5 1 -6 3
s5a01 3024 FSC.Height 166 5 1 -6 3
s5a01 2068 FSC.Height 346 5 1 -6 3
s5a01 316 FSC.Height 65 5 1 -6 3
s5a01 1177 FSC.Height 80 5 1 -6 3
s5a01 1557 FSC.Height 183 5 1 -6 3

Here we build the gatingObj from the GatingSet. We can also create all of the relevant gating plots by setting makeGraphs to TRUE. Note that if you have a lot of samples and a lot of gates, the plotting can take a while.

GO <- GOFromGatingSet(gs,imageDir = "../sampleDashboard/data/gating/", makeGraphs = FALSE)
#GO <- GOFromGatingSet(gs,imageDir = "../sampleDashboard/data/gating/", makeGraphs = TRUE)
##show structure of gatingObj
GO
## <gatingObj>
##   Inherits from: <commonDataObj>
##   Public:
##     annotation: data.table, data.frame
##     annotCols: name Patient Visit Days Grade Population Count
##     checkIntegrity: function (reconcile = FALSE) 
##     clone: function (deep = FALSE) 
##     contextID: NULL
##     gates: NULL
##     imageDir: ../sampleDashboard/data/gating/
##     initialize: function (annotation, popTable, mapVar = NULL, gates = NULL, 
##     mapVar: name
##     objId: GO-QCEUS35
##     popSubsets: list
##     popTable: data.table, data.frame
##     populations: rectangle CD15 FITC-CD45 PE+ CD15 FITC+CD45 PE+ CD15 FIT ...
##     returnMergedData: function () 
##     setAnnotationDisplayOptions: function (annotCols) 
##     setPopulations: function (popList) 
##     setPopulationSubset: function (subPopSets = NULL) 
##     setSubsetAndSortOptions: function (subsetOptions, sortOptions, checkIntegrity = TRUE) 
##     sortOptionList: NULL
##     sortOptions: Patient Visit Days Grade
##     subsetAnnotation: function (ids) 
##     subsetOptionList: list
##     subsetOptions: Patient Visit Days Grade

Again, we can see the merged data table from GO by using returnMergedData():

kable(GO$returnMergedData()[1:15,])
name Population Parent Count ParentCount idVar percentPop zscore popKey Patient Visit Days Grade
s5a01 rectangle root 97 3420 s5a01+rectangle+GO-QCEUS35 2.8362573 0.1001221 s5a01+rectangle 5 1 -6 3
s5a01 CD15 FITC-CD45 PE+ rectangle 0 97 s5a01+CD15 FITCnegCD45 PEpos+GO-QCEUS35 0.0000000 -0.4411082 s5a01+CD15 FITC-CD45 PE+ 5 1 -6 3
s5a01 CD15 FITC+CD45 PE+ rectangle 89 97 s5a01+CD15 FITCposCD45 PEpos+GO-QCEUS35 91.7525773 0.0585577 s5a01+CD15 FITC+CD45 PE+ 5 1 -6 3
s5a01 CD15 FITC+CD45 PE- rectangle 6 97 s5a01+CD15 FITCposCD45 PEneg+GO-QCEUS35 6.1855670 1.3761503 s5a01+CD15 FITC+CD45 PE- 5 1 -6 3
s5a01 CD15 FITC-CD45 PE- rectangle 2 97 s5a01+CD15 FITCnegCD45 PEneg+GO-QCEUS35 2.0618557 -0.2443595 s5a01+CD15 FITC-CD45 PE- 5 1 -6 3
s5a02 rectangle root 54 3405 s5a02+rectangle+GO-QCEUS35 1.5859031 -0.2834748 s5a02+rectangle 5 2 0 3
s5a02 CD15 FITC-CD45 PE+ rectangle 0 54 s5a02+CD15 FITCnegCD45 PEpos+GO-QCEUS35 0.0000000 -0.4411082 s5a02+CD15 FITC-CD45 PE+ 5 2 0 3
s5a02 CD15 FITC+CD45 PE+ rectangle 46 54 s5a02+CD15 FITCposCD45 PEpos+GO-QCEUS35 85.1851852 -0.3323285 s5a02+CD15 FITC+CD45 PE+ 5 2 0 3
s5a02 CD15 FITC+CD45 PE- rectangle 1 54 s5a02+CD15 FITCposCD45 PEneg+GO-QCEUS35 1.8518519 -0.1685001 s5a02+CD15 FITC+CD45 PE- 5 2 0 3
s5a02 CD15 FITC-CD45 PE- rectangle 7 54 s5a02+CD15 FITCnegCD45 PEneg+GO-QCEUS35 12.9629630 0.4722496 s5a02+CD15 FITC-CD45 PE- 5 2 0 3
s5a03 rectangle root 11 3435 s5a03+rectangle+GO-QCEUS35 0.3202329 -0.6717704 s5a03+rectangle 5 3 6 3
s5a03 CD15 FITC-CD45 PE+ rectangle 0 11 s5a03+CD15 FITCnegCD45 PEpos+GO-QCEUS35 0.0000000 -0.4411082 s5a03+CD15 FITC-CD45 PE+ 5 3 6 3
s5a03 CD15 FITC+CD45 PE+ rectangle 7 11 s5a03+CD15 FITCposCD45 PEpos+GO-QCEUS35 63.6363636 -1.6148983 s5a03+CD15 FITC+CD45 PE+ 5 3 6 3
s5a03 CD15 FITC+CD45 PE- rectangle 1 11 s5a03+CD15 FITCposCD45 PEneg+GO-QCEUS35 9.0909091 2.4116908 s5a03+CD15 FITC+CD45 PE- 5 3 6 3
s5a03 CD15 FITC-CD45 PE- rectangle 3 11 s5a03+CD15 FITCnegCD45 PEneg+GO-QCEUS35 27.2727273 1.4129345 s5a03+CD15 FITC-CD45 PE- 5 3 6 3

Finally, we build a populationExpressionObj from the GatingSet.

PEO <- PEOFromGatingSet(gs, samplePop = 1000)
PEO
## <populationExpressionObj>
##   Inherits from: <commonDataObj>
##   Public:
##     annotation: data.table, data.frame
##     annotCols: Patient Visit Days Grade
##     checkIntegrity: function (reconcile = FALSE) 
##     clone: function (deep = FALSE) 
##     contextID: NULL
##     countPopulations: function () 
##     expressionData: data.table, data.frame
##     initialize: function (annotation, expressionData, mapVar = NULL, checkIntegrity = TRUE, 
##     mapVar: name
##     markers: FSC-Height SSC-Height CD15 FITC CD45 PE CD14 PerCP FL2-A ...
##     objId: PEO-PLVHZ87
##     populations: rectangle CD15 FITC-CD45 PE+ CD15 FITC+CD45 PE+ CD15 FIT ...
##     returnMergedData: function () 
##     setAnnotationDisplayOptions: function (annotCols) 
##     setMarkers: function (markers) 
##     setSubsetAndSortOptions: function (subsetOptions, sortOptions, checkIntegrity = TRUE) 
##     sortOptionList: NULL
##     sortOptions: Patient Visit Days Grade
##     subsetAnnotation: function (ids) 
##     subsetOptionList: list
##     subsetOptions: Patient Visit Days Grade

We want to remove Time as a marker from PEO

markers <- as.character(PEO$markers)
markers
## [1] "FSC-Height"        "SSC-Height"        "CD15 FITC"        
## [4] "CD45 PE"           "CD14 PerCP"        "FL2-A"            
## [7] "CD33 APC"          "Time (51.20 sec.)"
PEO$setMarkers(markers[1:7])

Viewing the merged data table from PEO:

kable(PEO$returnMergedData()[1:20,])
cell idVar variable value Population Patient Visit Days Grade
1 s5a01 FSC-Height 371 rectangle 5 1 -6 3
2 s5a01 FSC-Height 236 rectangle 5 1 -6 3
3 s5a01 FSC-Height 269 rectangle 5 1 -6 3
4 s5a01 FSC-Height 259 rectangle 5 1 -6 3
5 s5a01 FSC-Height 232 rectangle 5 1 -6 3
6 s5a01 FSC-Height 201 rectangle 5 1 -6 3
7 s5a01 FSC-Height 240 rectangle 5 1 -6 3
8 s5a01 FSC-Height 380 rectangle 5 1 -6 3
9 s5a01 FSC-Height 206 rectangle 5 1 -6 3
10 s5a01 FSC-Height 213 rectangle 5 1 -6 3
11 s5a01 FSC-Height 276 rectangle 5 1 -6 3
12 s5a01 FSC-Height 217 rectangle 5 1 -6 3
13 s5a01 FSC-Height 239 rectangle 5 1 -6 3
14 s5a01 FSC-Height 232 rectangle 5 1 -6 3
15 s5a01 FSC-Height 211 rectangle 5 1 -6 3
16 s5a01 FSC-Height 226 rectangle 5 1 -6 3
17 s5a01 FSC-Height 247 rectangle 5 1 -6 3
18 s5a01 FSC-Height 229 rectangle 5 1 -6 3
19 s5a01 FSC-Height 264 rectangle 5 1 -6 3
20 s5a01 FSC-Height 205 rectangle 5 1 -6 3

Save all objects into a new Rda:

save(PEO, GO, QCO, file="../sampleDashboard/data/GvHD.rda")