Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

geom_stats static location #73

Open
alexheubeck opened this issue Oct 28, 2020 · 16 comments
Open

geom_stats static location #73

alexheubeck opened this issue Oct 28, 2020 · 16 comments

Comments

@alexheubeck
Copy link

alexheubeck commented Oct 28, 2020

Hi @jacobpwagner,

I had a quick question about using geom_stats. I am trying to plot a boolean NOT gate with ggcyto, and display the stats for that population. I'm using the adjust parameter to change the location of the gate info. However, since it is relative to centroid of the population, the stats box is moving around a lot more than I'd like when the population shifts more than usual. Is there a way to have a static position for the geom_stats info on a plot? I saw that you could add arguments from geom_label, but I couldn't get anything to work.

Here's an example where the 'Non-Treg' population is a boolean NOT gate of the 'Treg' gate:

Screen Shot 2020-10-28 at 12 28 37 PM
Screen Shot 2020-10-28 at 12 28 50 PM

Thanks,

Alex

@jacobpwagner
Copy link
Member

Interesting, I believe this should be what the abs parameter is for at the level of stat_position. However, that is currently not recongized by geom_stats and thus not passed down to stat_position. Let me see if I can fix this quickly.

@jacobpwagner
Copy link
Member

After 0cdb186, adding abs=TRUE to geom_stats should set the starting point for adjust to the center of the whole ("absolute") data range as opposed to the subset in the gate. Note that this still doesn't mean the center of the window, as that would probably require adding an extra static arg that triggers a bypass of the centroid logic entirely. That's certainly doable as well so I'll probably leave the issue open to track that. However, exposing abs was an easy addition so I thought it was worth adding it first.

Additionally, @mikejiang , it looks like there was already logic to automatically set abs=TRUE for booleanFilters . For now I just made sure that automatic logic doesn't override explicit abs=TRUE from the user. I'm not sure why it wasn't getting triggered here but it could be a class inheritance issue or something. I'll look into it as time allows.

Examples below:

Setup:

library(flowCore)
library(flowWorkspace)
library(ggcyto)
gs <- load_gs(system.file("extdata", "gs_manual", package = "flowWorkspaceData"))

Position: default -- center of gate

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats()

image

Position: lower left with respect to center of gate range

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(adjust = c(0.1, 0.1))

image

Position: center of full data range

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(abs = TRUE)

image

Position: lower left with respect to center of full data range

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(adjust = c(0.1, 0.1), abs = TRUE)

image

Note this is still not with respect to the range of the window (just the data):

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(adjust = c(0.1, 0.1), abs = TRUE) +
  ggcyto_par_set(limits = list(x = c(-10000, 4000), y = c(-1000, 4500)))

image

@alexheubeck
Copy link
Author

Hi @jacobpwagner,

Thanks for that fix. It's working better, as the label moves less, but it still gets moved off of the plot sometimes when the populations shown are atypical. Adding the static argument would be great, but as time allows.

@jacobpwagner
Copy link
Member

Hi @alexheubeck. I'll get to work on the static option. Just out of curiosity, could you show a case where the label is getting moved off the plot? I just want to also make sure that that last fix is behaving as expected.

@alexheubeck
Copy link
Author

I want the label to sit in the top right, opposite the other label.
These two plots have the correct placement:

Screen Shot 2020-10-29 at 9 28 13 AM
Screen Shot 2020-10-29 at 9 28 48 AM

These two are cases where it gets moved off:
Screen Shot 2020-10-29 at 9 30 09 AM
Screen Shot 2020-10-29 at 9 30 24 AM

@jacobpwagner
Copy link
Member

jacobpwagner commented Oct 29, 2020

Gotcha. And are you using ggcyto_par_set to manually change the limits of the window? I just want to make sure I understand how it's getting pushed off. Also, it looks like the static option will be a simple addition as well.

I'm adding an argument that determines what range to use to determine the starting point for the label. It will allow the 3 options:

  • gate range -- abs = FALSE in the old argument -- "gate" (and default) for the new arg
  • data range -- abs = TRUE in the old argument -- "data" for the new arg
  • whole plot range -- not possible with the old args -- maybe "plot" or "window" for the new arg

As a user, if there's a name for this argument (and the whole plot range option) that makes the most sense, I'd be happy to get your input. Currently, I'm using location, so it would be location="gate", location="data", or location="plot". I thought about window instead of location as well, but thought that might confuse the purpose of the argument which is just to determine the starting location for the label that can then be moved around with adjust.

@alexheubeck
Copy link
Author

alexheubeck commented Oct 29, 2020

I am using ggcyto_par_set. This is the line I'm using for that plot:

Treg <- ggcyto(gs[[idx]], aes(x = CD127, y = CD25), subset = "CD4 T Cells",) + geom_hex(binwidth = c(0.015,0.015)) + ggcyto_par_set(limits = list(x = c(1,3.5), y = c(1,4))) + geom_gate('Treg' ,col='black') + geom_stats("Treg", type = c("gate_name", "percent"), adjust=c(0.1,0.95), size=1.5, fill="transparent") + geom_stats('Non-Treg',type = c("gate_name", "percent"), adjust=c(0.95, 1), abs=TRUE, size=1.5, fill="transparent") + axis_x_inverse_trans() + axis_y_inverse_trans() + theme_bw() + mytheme + facet_null() + scale_fill_gradientn(colours = matlab.like2(300), trans = "sqrt")

(Sorry it's a mess)

I think location makes sense. Since I'm using a static range for the plot, my ideal way of doing this would be to provide coordinates on the plot for the center of the label. For example, if the range of both axis is (0,4), I could set the center of the label to (3.5,3.5) so it always stays in that static location. I'm assuming that's what you're doing with the "whole plot range" argument.

@jacobpwagner
Copy link
Member

jacobpwagner commented Oct 29, 2020

Cool, I'll go with location then. Regarding the specification of the location for adjust, I could also add a "fixed" option to handle your use case. That is, instead of:

ggcyto(...) +
... +
ggcyto_par_set(limits = list(x = c(0,4), y = c(0,4)) +
geom_stats(location = "plot", adjust=c(0.875, 0.875))

you could instead do this:

ggcyto(...) +
... +
ggcyto_par_set(limits = list(x = c(0,4), y = c(0,4)) +
geom_stats(location = "fixed", adjust=c(3.5, 3.5))

Does that sound about right? That seems like a pretty reasonable request and addition.

@alexheubeck
Copy link
Author

Yeah that's perfect, thanks!

@jacobpwagner
Copy link
Member

Alright, after f0a4d42, this is now possible. Here are some examples using the same setup as before. I include the ggcyto_par_set adjustment of axis limits to demonstrate how they are ignored or used in each case:

Default positioning

 ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats() +
  ggcyto_par_set(limits = list(x = c(-10000, 4000), y = c(-1000, 4500)))

image

Lower left within gate (location="gate" is default and could be left out here)

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(adjust = c(0.1, 0.1), location = "gate") +
  ggcyto_par_set(limits = list(x = c(-10000, 4000), y = c(-1000, 4500)))

image

Lower left within data range

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(adjust = c(0.1, 0.1), location = "data") +
  ggcyto_par_set(limits = list(x = c(-10000, 4000), y = c(-1000, 4500)))

image

Lower left within range of plot axis limits

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(adjust = c(0.1, 0.1), location = "plot") +
  ggcyto_par_set(limits = list(x = c(-10000, 4000), y = c(-1000, 4500)))

image

Fixed location

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(adjust = c(-2500, 2000), location = "fixed") +
  ggcyto_par_set(limits = list(x = c(-10000, 4000), y = c(-1000, 4500)))

image

Of course, there's also nothing really stopping you from pushing the annotation outside of whatever window by going beyond 1.0 or below 0.0. For example:

ggcyto(gs[[1]], aes("CD4", "CD8"), subset = "CD3+") +
  geom_hex(bins = 0) +
  geom_gate("CD4") +
  geom_stats(adjust = c(-0.5, 1.2), location = "gate") +
  ggcyto_par_set(limits = list(x = c(-10000, 4000), y = c(-1000, 4500)))

image

@alexheubeck
Copy link
Author

Thanks @jacobpwagner, this is perfect. To that last point, I set the adjust annotation higher than 1 if I want the label outside of the gate pretty frequently. It would be good to mention that in the documentation.

@jacobpwagner
Copy link
Member

Agreed. I actually meant to do that and then forgot. Now it's included.

@alexheubeck
Copy link
Author

Looks like the location annotation works for regular gates, but it's not working for the boolean NOT gate that I'd like to use it for.

Using this line:

NKCells <- ggcyto(gs[[idx]], aes(x = CD14, y = CD56), subset = "CD3-CD19- Cells") + geom_hex(binwidth = c(0.015,0.015)) + ggcyto_par_set(limits = list(x = c(0.25,4.7), y = c(0.3,4.5))) + geom_gate(c('NK Cells'),col='black') + geom_stats('NK Cells',type = c("gate_name", "percent"), location = 'fixed', adjust=c(0.5,3), size=1.4, fill="transparent") ..

The label is placed properly:

image

Using this line, where the "CD3-CD19-CD56- Cells" gate is a boolean NOT gate of the "NK Cells" gate:

NKCells <- ggcyto(gs[[idx]], aes(x = CD14, y = CD56), subset = "CD3-CD19- Cells") + geom_hex(binwidth = c(0.015,0.015)) + ggcyto_par_set(limits = list(x = c(0.25,4.7), y = c(0.3,4.5))) + geom_gate(c('CD3-CD19-CD56- Cells'),col='black') + geom_stats('CD3-CD19-CD56- Cells',type = c("gate_name", "percent"), location = 'fixed', adjust=c(0.5,3), size=1.4, fill="transparent") ...

I get this error:

Error in FUN(X[[i]], ...) : object 'BUV661-A' not found

Where BUV661-A is the channel for x axis in this plot

@jacobpwagner
Copy link
Member

Sorry about that. I think I know the issue. I'll try to get it fixed quickly.

@jacobpwagner
Copy link
Member

jacobpwagner commented Oct 29, 2020

@alexheubeck , will you try again after 333c61f? I think that should solve the issue. Note that for booleanFilter, the location="gate" option still gets automatically flipped to location="data". That is just a continuation of the prior behavior until more sophisticated logic is added there.

@alexheubeck
Copy link
Author

@jacobpwagner, It's working now. Thank you once again for your help with this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants