cytoqc – A QC tool for openCyto

cytoqc performs pre-cleaning, pre-gating and post-gating QC checks.

The basic workflow:

  1. Run cqc_check to see the summary
  2. cqc_set_reference and cqc_find_solution for selected groups
  3. cqc_fix based on the solution or cqc_drop_groups for unsolvable issues
  4. Iterate 1~3 steps until data is cleaned
  5. split the data into multiple sets for multi-panel cases
library(flowCore)
library(flowWorkspace)
# library(cytoqc)
devtools::load_all("../")

Load the FCS

files <- list.files(data_dir, ".fcs", full.names = TRUE)
cqc_data <- cqc_load_fcs(files)
cqc_data
## cytoqc data: 
## 35  samples

QC check for channel

groups <- cqc_check(cqc_data, "channel")
su <- summary(groups)
su

group_id

nFCS

channel

3

32

FL1-H, FL2-A, FL2-H, FL3-H, FL4-H, FSC-H, SSC-H, Time

1

1

channelA, FL1-H, FL2-A, FL2-H, FL3-H, FL4-H, FSC-H, SSC1-H, Time

2

1

FL1-H, FL2-A, FL2-H, FL3-H, FL4-H, fsc-h, SSC-H

4

1

FL1-H, FL2-A, FL2-H, FL3-H, FL4-H, fsc-h, SSC1-H, Time

diff(su)

group_id

nFCS

channel

3

32

FSC-H, SSC-H, Time

1

1

channelA, FSC-H, SSC1-H, Time

2

1

fsc-h, SSC-H

4

1

fsc-h, SSC1-H, Time

Select the reference

groups <- cqc_set_reference(groups, ref = 3)

Recommend the fix for the selected groups

solution <-  cqc_find_solution(groups, select = c(1, 4))
solution

Proposed change

SSC1-H –> SSC-H

channelA

fsc-h –> FSC-H

Show the itemized details

knit_print(solution, itemize = TRUE)

group_id

Proposed change

1

SSC1-H –> SSC-H

channelA

4

fsc-h –> FSC-H

SSC1-H –> SSC-H

Export/import the solution for revision (if needed)

library(readr)
write_csv(solution, csvfile)
#manually edit csvfile and load it back
solution_revised <- read_csv(csvfile)

Apply the fix

cqc_fix(solution)

Refresh QC report

groups <- cqc_check(cqc_data, "channel")
summary(groups)

group_id

nFCS

channel

2

34

FL1-H, FL2-A, FL2-H, FL3-H, FL4-H, FSC-H, SSC-H, Time

1

1

FL1-H, FL2-A, FL2-H, FL3-H, FL4-H, fsc-h, SSC-H

Drop groups that can not be fixed

cqc_data <- cqc_drop_groups(groups, 1)
length(cqc_data)
## [1] 34

QC for marker

#summarise marker groups
groups <- cqc_check(cqc_data, "marker")
su <- summary(groups)
diff(su)

group_id

nFCS

marker

3

21

CD15 FITC, CD33 APC, Time (102.40 sec.)

5

7

CD15 FITC, CD33 APC, Time (51.20 sec.)

4

4

CD15 FITC, CD33 APC, Time (204.80 sec.)

1

1

apc cd33, cd15, Time (102.40 sec.)

2

1

CD15 FITC, CD33 APC, markerA, Time (204.80 sec.)

Pick references and groups to fix

groups <- cqc_set_reference(groups, ref = 3)
solution <- cqc_find_solution(groups, select = 1, max.distance = 0.4) 
solution

Proposed change

cd15 –> CD15 FITC

apc cd33 –> CD33 APC

cqc_fix(solution)

groups <- cqc_set_reference(groups, ref = 4)
solution <- cqc_find_solution(groups, select = 2, max.distance = 0.4) 
solution

Proposed change

markerA

cqc_fix(solution)

update checks

groups <- cqc_check(cqc_data, "marker")
su <- summary(groups)
diff(su)

group_id

nFCS

marker

1

22

Time (102.40 sec.)

3

7

Time (51.20 sec.)

2

5

Time (204.80 sec.)

split by groups

data_list <- split(groups)
data_list
## $`1`
## cytoqc data: 
## 22  samples 
## 
## $`2`
## cytoqc data: 
## 5  samples 
## 
## $`3`
## cytoqc data: 
## 7  samples

QC for panel

# first data set is already clean
summary(cqc_check(data_list[[1]], "panel"))

channel

marker

group_id

nFCS

FL1-H

CD15 FITC

1

22

FL2-H

CD45 PE

FL3-H

CD14 PerCP

FL4-H

CD33 APC

FSC-H

FSC-Height

SSC-H

SSC-Height

Time

Time (102.40 sec.)

Save the cleaned data as FCS

cleaned <- data_list[[1]]
out <- tempfile()
write_fcs(cleaned, out)

Or Coerce it directly into cytoset (zero-copying)

cs <- cytoset(cleaned)
cs
## A cytoset with 22 samples.
## 
##   column names:
##     FSC-H, SSC-H, FL1-H, FL2-H, FL3-H, FL2-A, FL4-H, Time

Further split the data by panel

grps <- cqc_check(data_list[[2]], "panel")
diff(summary(grps))

channel

marker

group_id

nFCS

FL1-H

CD15 FITC

1

4

FL2-H

CD45 PE

FL1-H

CD45 PE

2

1

FL2-H

CD15 FITC

split(grps)
## $`1`
## cytoqc data: 
## 4  samples 
## 
## $`2`
## cytoqc data: 
## 1  samples