Question: How to select left hand side of mindensity2 gate
0
10 months ago by
biomiha20
UK/Cambridge
biomiha20 wrote:

Hi,

I'm trying to use the gate_mindensity2 from the openCyto package to gate out debris from my .fcs files. I'm using https://flowrepository.org/id/FR-FCM-ZZ36 as an example. I can gate out the debris at the lower end (i.e. left hand side of the gate) but if I want to apply a gate to remove the events on the right hand side, I am unable to do so, even if I set the positive argument to TRUE. I've probably just missed something, but has the positive=TRUE argument to gate_mindensity2 been removed from the recent version of openCyto.

Reprex and link to reprex output below. The issue I have is from applying FCSgate2fun to the gating set and expecting the filter to take the real line to the left of the cutpoint

Many thanks, Miha

https://github.com/Biomiha/FACS/blob/master/FACS_reprex.html

library(tidyverse)
library(openCyto)
library(ggcyto)

PBMC_luca <- list.files(path = "FR-FCM-ZZ36/", pattern = ".fcs", full.names = TRUE) %>%
grep(pattern = "luca", value = TRUE) %>%

PBMC_luca[[1]] %>%
ggcyto(aes(x = FSC-A)) +
geom_density()

PBMC_luca_gatingSet <- GatingSet(PBMC_luca)
FCS_gate1_fun <- function(fr, channel = "FSC-A"){
peaks_found <- openCyto:::.find_peaks(x = as.numeric(unname(unlist(exprs(fr[, channel])))), num_peaks = 3)
openCyto::gate_mindensity2(fr, channel = channel, gate_range = sort(peaks_found$x)[1:2]) } FCS_gate1_fun(getData(PBMC_luca_gatingSet[[1]])) if(require(openCyto)){ thisData <- getData(PBMC_luca_gatingSet) nonDebris_gate <- fsApply(thisData, FCS_gate1_fun) add(PBMC_luca_gatingSet, nonDebris_gate, parent = "root", name = "nonDebris") recompute(PBMC_luca_gatingSet) } getData(PBMC_luca_gatingSet[[1]]) %>% ggcyto(aes(x = FSC-A)) + geom_density() + geom_gate(FCS_gate1_fun(getData(PBMC_luca_gatingSet[[1]]))) getData(PBMC_luca_gatingSet[[1]], y = "nonDebris") %>% ggcyto(aes(x = FSC-A)) + geom_density() FCS_gate2_fun <- function(fr, channel = "FSC-A"){ openCyto::gate_mindensity2(fr, channel = channel, positive = TRUE) #not sure if this argument exists anymore } getData(PBMC_luca_gatingSet[[1]], y = "nonDebris") %>% ggcyto(aes(x = FSC-A)) + geom_density() + geom_gate(FCS_gate2_fun(getData(PBMC_luca_gatingSet[[1]], y = "nonDebris"))) if(require(openCyto)){ thisData <- getData(PBMC_luca_gatingSet, y = "nonDebris") nonDebris_gate2 <- fsApply(thisData, FCS_gate2_fun) add(PBMC_luca_gatingSet, nonDebris_gate2, parent = "nonDebris", name = "nonDebris2") recompute(PBMC_luca_gatingSet) } getData(PBMC_luca_gatingSet[[1]], y = "nonDebris") %>% ggcyto(aes(x = FSC-A)) + geom_density() getData(PBMC_luca_gatingSet[[1]], y = "nonDebris2") %>% ggcyto(aes(x = FSC-A)) + geom_density() sessionInfo()  opencyto mindensity • 286 views ADD COMMENTlink modified 10 months ago by Jiang, Mike1.2k • written 10 months ago by biomiha20 I've figured out the reason. At least in my version of openCyto::gate_mindensity2 the last 3 lines of code are: coords <- list(c(g$final_cut, Inf))
names(coords) <- channel
return(rectangleGate(coords, filterId = filterId))


Meaning that any positive argument passed to gate_mindensity2 is irrelevant as the coords are hardwired to be c(g$final_cut, Inf). I'm not sure if this was done deliberately, but I've noticed the same for the other gates, e.g. openCyto::gate_tail. I've generated my own version of the gating function. Attached below. my_mindensity <- function(fr, channel, filterId = "", pivot = FALSE, gate_range = NULL, min = NULL, max = NULL, peaks = NULL, positive = TRUE, ...) { stopifnot(require(openCyto)) if (missing(channel) || length(channel) != 1) { stop("A single channel must be specified.") } if (!(is.null(min) && is.null(max))) { fr <- .truncate_flowframe(fr, channels = channel, min = min, max = max ) } x <- exprs(fr[, channel]) g <- openCyto:::.improvedMindensity( D = x, gate_range = gate_range, ... ) if (positive == TRUE) { coords <- list(c(g$final_cut, Inf))
} else {
coords <- list(c(-Inf, g\$final_cut))
}
names(coords) <- channel
return(rectangleGate(coords, filterId = filterId))
}

Answer: How to select left hand side of mindensity2 gate
0
10 months ago by
Jiang, Mike1.2k
Jiang, Mike1.2k wrote:

I'd recommend openCyto gating functions to be used with its template-based gating framework. Instead of iterating through each sample (i.e. fsApply) of each gated population (i.e. getData) and invoking mindensity and adding gates manually, you can simply submit the gating strategy to the framework and let openCyto do these boilerplate jobs for you. It can be done either through a csv template or incrementally by add_pop API. To select lower(left) end of 1d gate, simply set pop column(or argument) to "-" in csv (or add_pop() call)

Here is the example http://rpubs.com/wjiang2/464414, which is more succinct and easy to read/understand.

P.S. With more recent development version of openCyto (trunk branch of github repo), you will able to quickly undo add_pop through newly added 'remove_pop' API.(instead of manually remove gates through 'Rm' function)

Thanks Mike. With regards to the fsApply iteration I followed this vignette, which seems to be quite recent https://www.bioconductor.org/packages/devel/bioc/vignettes/flowCore/inst/doc/HowTo-flowCore.pdf. The add_pop API looks like a very good alternative though.

flowCore&flowWorkspace provide the relative low-level of APIs to interact with the basic data structures (e.g. flowSet, Gatingset). For the auto gating, openCyto package provides more high-level interlaces and convenient wrappers (which are built upon those two packages). They operate at the different layers and thus serve different purposes. From my understanding based on your use cases, template/gating strategy-based openCyto will meet your needs better. That said, flowCore&flowWorkspace are the building blocks of openCyto, feel free to use them if you need more complex and customized gating and you didn't find the existing tools available in openCyto.

Hi Mike,

One thing I've noticed is that even with the pop argument set to "-" in the add_pop API, the gate dimensions themselves are actually set to:

Rectangular gate 'nonDebris2' with dimensions:
FSC-A: (244703.838155759,Inf)


i.e. right hand side. I'm not sure what goes on behind the scenes because the population stats look ok and the ggcyto labels are fine as well but if I use a different plotting function it (correctly) sets the gate on the right. I've summarised it all here: http://rpubs.com/biomiha/470168. Presumably the desired behaviour would be to get the gate dims as:

Rectangular gate 'nonDebris2' with dimensions:
FSC-A: (-Inf, 244703.838155759)


?