RGLab / openCyto

A package that provides data analysis pipeline for flow cytometry.
GNU Affero General Public License v3.0
75 stars 29 forks source link

new gate_tail and 'side==left' behavior #221

Closed alexheubeck closed 3 years ago

alexheubeck commented 3 years ago

Hi all,

This is related to the recent change noted in Issue https://github.com/RGLab/openCyto/issues/216

I have gating templates that use gate_tail and side==left frequently. I recently updated openCyto, and I'd like to figure out how to make the templates behave as they did before.

For example, I use this line to generate a positive and negative population from a single histogram gate:

alias pop parent dims gating_method gating_args
* +/- T Cells abTCR tailgate min=1, side='left', tol=0.05

With the new changes, that line creates two negative populations:

Screen Shot 2020-10-23 at 3 20 32 PM

What's the best way to correct this line so that it creates the appropriate positive and negative population?

Thanks, Alex

jacobpwagner commented 3 years ago

Hey Alex,

Yeah, I think the "+/-" expansion was one complication that still had to be worked out in this case. The crux of the problem is that the relevant logic in openCyto:::.gating_refGate expects positively defined gates to be defined [a, Inf) (with a finite): https://github.com/RGLab/openCyto/blob/aa2cf70b86997642e110928a23caaf36967d0a9b/R/gating-methods.R#L603-L606 So it assumes that the negation should then be (-Inf, a]. However, in this case the positively-defined gate is already (-Inf, a] so negation amounts to a no-op. In theory extending the logic to perform a 1-D inversion regardless of the prior bounds should be simple. I just have to make sure it doesn't break prior assumptions or test cases. I'll get to work on it, but in the meantime it should also work to just add two lines (one "+" and one "-"). That prevents you from converging on that refGate logic. I believe gate_tail should be deterministic, so while you pay a small penalty in execution time to re-perform the same cutpoint-discovery, it should land at the same point in both the "+" and "-" case. Example script:

library(flowCore)
library(flowWorkspace)
library(ggcyto)
library(openCyto)

gs1 <- load_gs(system.file("extdata", "gs_manual", package = "flowWorkspaceData"))
gs2 <- gs_clone(gs1)

openCyto::gs_add_gating_method(gs1, alias = "CCR7_left_tail_pos", pop = "+", parent = "CD4",
                               dims = "<G560-A>", gating_method = "gate_tail", 
                               gating_args = "min=1,side='left',tol=0.05")
openCyto::gs_add_gating_method(gs1, alias = "CCR7_left_tail_neg", pop = "-", parent = "CD4",
                               dims = "<G560-A>", gating_method = "gate_tail", 
                               gating_args = "min=1,side='left',tol=0.05")

autoplot(gs1[[1]], "CCR7_left_tail_pos")
autoplot(gs1[[1]], "CCR7_left_tail_neg")
ggcyto(gh_pop_get_data(gs1[[1]], "CD4"), aes("CCR7")) +
  geom_density() +
  geom_gate(gh_pop_get_gate(gs1[[1]], "CCR7_left_tail_pos"))
ggcyto(gh_pop_get_data(gs1[[1]], "CD4"), aes("CCR7")) +
  geom_density() +
  geom_gate(gh_pop_get_gate(gs1[[1]], "CCR7_left_tail_neg"))

gh_pop_get_stats(gs1[[1]], "CCR7_left_tail_pos")
gh_pop_get_stats(gs1[[1]], "CCR7_left_tail_neg")
jacobpwagner commented 3 years ago

Some more quick notes on the 1-D inversion. If the rectangleGate only has one finite bound, this is simple:

[a, Inf]) negates to (-Inf, a] and vice versa. One rectangleGate is replaced with another.

However, for two finite bounds it's a little more complicated. The negation (complement) would be:

[a, b] negates to (-Inf, a] union [b, Inf). One rectangleGate is replaced with a union of two others.

That's a problem because that would require more substantial changes. However, there aren't any automatic methods that generate rectangleGates with two finite bounds included in openCyto yet, so for now we could just error out on that case in the refGate logic. That's no real change from the current behavior which assumes an infinite bound anyway.

jacobpwagner commented 3 years ago

Fixed/clarified by https://github.com/RGLab/openCyto/commit/47687e6d42900bc0af1b964cb7e5b63d7e25ba81. See discussion on https://github.com/RGLab/openCyto/issues/216.