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)
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.table
s 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")