DillonHammill / CytoExploreR

Interactive Cytometry Data Analysis
62 stars 13 forks source link

Problem with "patchy" colors in cyto_plot 2D plots #215

Open AlexBlais74 opened 1 month ago

AlexBlais74 commented 1 month ago

Hello I am using cyto_plot to examine FSC vs SSC of a FCS file, loaded as a a flowSet object with flowCore::read.flowSet The scatter (2D) plot that I obtain has an appearance that seems correct except for the colors, which seem too patchy: there are well-defined blocks of color that I expect should be more gradual and certainly not rectangular as seen here. I have drawn contour lines to show event density and those have the expected appearance.

The code for the plot:

cyto_plot(  fs.sony_full, 
        parent = "root",
        channels = c("FSC-A", "SSC-A"),
        display = 25000,
        point_size = 2,
        contour_lines = 10,
        xlim = c(0, 1E6), ylim = c(0, 0.3E6))

Here is the distribution of values I am trying to plot:

# number of events in the flowSet
>nrow(exprs(fs.sony_full[[1]]))
[1] 100000

# Distribution of FSC-A values
> summary(exprs(fs.sony_full[[1]])[,"FSC-A"])
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
   47440   108072   204901   276536   300973 25800426 

# Distribution of SSC-A values
> summary(exprs(fs.sony_full[[1]])[,"SSC-A"])
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
    -405    11330    15564    56724    22891 12128400 

# How many events are plotted, with the x- and y-axis limits chosen
> exprs(fs.sony_full[[1]]) %>% as.data.frame() %>% dplyr::filter(`FSC-A` <= 1E6 & `SSC-A` <= 0.3E6) %>% nrow()
[1] 97134

I am getting the same behavior with a gatingSet object creating using cyto_setup. Any help would be greatly appreciated. Thanks Alex

image

> sessionInfo()
R version 4.4.1 (2024-06-14 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 22631)

Matrix products: default

locale:
[1] LC_COLLATE=English_Canada.utf8  LC_CTYPE=English_Canada.utf8    LC_MONETARY=English_Canada.utf8 LC_NUMERIC=C                   
[5] LC_TIME=English_Canada.utf8    

time zone: America/Toronto
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] viridis_0.6.5        viridisLite_0.4.2    ggpubr_0.6.0         gridExtra_2.3        cowplot_1.1.3        ggplotify_0.1.2      ggridges_0.5.6      
 [8] lubridate_1.9.3      forcats_1.0.0        stringr_1.5.1        dplyr_1.1.4          purrr_1.0.2          readr_2.1.5          tidyr_1.3.1         
[15] tibble_3.2.1         tidyverse_2.0.0      CytoExploreR_1.1.0   flowGate_1.4.0       flowCut_1.14.0       flowClean_1.42.0     flowAI_1.34.0       
[22] CytoML_2.16.0        openCyto_2.16.1      ggcyto_1.32.0        flowWorkspace_4.16.0 ncdfFlow_2.50.0      BH_1.84.0-0          ggplot2_3.5.1       
[29] flowViz_1.68.0       lattice_0.22-6       flowCore_2.16.0     

loaded via a namespace (and not attached):
  [1] RColorBrewer_1.1-3  jsonlite_1.8.8      umap_0.2.10.0       magrittr_2.0.3      farver_2.1.2        rmarkdown_2.28      ragg_1.3.2         
  [8] fs_1.6.4            zlibbioc_1.50.0     vctrs_0.6.5         Cairo_1.6-2         askpass_1.2.0       rstatix_0.7.2       htmltools_0.5.8.1  
 [15] broom_1.0.6         gridGraphics_0.5-1  sass_0.4.9          flowDensity_1.38.0  KernSmooth_2.23-24  bslib_0.8.0         htmlwidgets_1.6.4  
 [22] plyr_1.8.9          zoo_1.8-12          cachem_1.1.0        changepoint_2.2.4   sfsmisc_1.1-19      mime_0.12           lifecycle_1.0.4    
 [29] pkgconfig_2.0.3     rsvd_1.0.5          Matrix_1.7-0        R6_2.5.1            fastmap_1.2.0       shiny_1.9.1         digest_0.6.37      
 [36] colorspace_2.1-1    S4Vectors_0.42.1    RSpectra_0.16-2     textshaping_0.4.0   labeling_0.4.3      cytolib_2.16.0      fansi_1.0.6        
 [43] timechange_0.3.0    polyclip_1.10-7     abind_1.4-5         compiler_4.4.1      proxy_0.4-27        withr_3.0.1         backports_1.5.0    
 [50] EmbedSOM_2.1.2      carData_3.0-5       flowClust_3.42.0    hexbin_1.28.4       gplots_3.1.3.1      ggsignif_0.6.4      MASS_7.3-61        
 [57] openssl_2.2.1       gtools_3.9.5        caTools_1.18.3      tools_4.4.1         httpuv_1.6.15       glue_1.7.0          IDPmisc_1.1.21     
 [64] promises_1.3.0      grid_4.4.1          Rtsne_0.17          reshape2_1.4.4      generics_0.1.3      gtable_0.3.5        tzdb_0.4.0         
 [71] class_7.3-22        data.table_1.16.0   hms_1.1.3           car_3.1-2           utf8_1.2.4          BiocGenerics_0.50.0 pillar_1.9.0       
 [78] yulab.utils_0.1.7   later_1.3.2         robustbase_0.99-4   bit_4.0.5           deldir_2.0-4        RProtoBufLib_2.16.0 tidyselect_1.2.1   
 [85] RBGL_1.80.0         knitr_1.48          rhandsontable_0.3.8 stats4_4.4.1        xfun_0.47           Biobase_2.64.0      matrixStats_1.4.1  
 [92] DEoptimR_1.1-3      visNetwork_2.1.2    stringi_1.8.4       yaml_2.3.10         evaluate_0.24.0     interp_1.1-6        Rgraphviz_2.48.0   
 [99] BiocManager_1.30.25 graph_1.82.0        cli_3.6.3           systemfonts_1.1.0   xtable_1.8-4        reticulate_1.39.0   munsell_0.5.1      
[106] jquerylib_0.1.4     Rcpp_1.0.13         png_0.1-8           XML_3.99-0.17       parallel_4.4.1      latticeExtra_0.6-30 jpeg_0.1-10        
[113] bitops_1.0-8        scales_1.3.0        e1071_1.7-14        rlang_1.1.4        
AlexBlais74 commented 1 month ago

I wanted to add that ggcyto seems to color a similar 2D plot for the same data:

ggcyto(
    fs.sony_full, 
    aes(x = "FSC-A", y = "SSC-A"), 
    subset = "root", 
    max_nrow_to_plot = 25000) +
    geom_hex(bins = 4096) + 
    ggcyto_par_set(limits = list(x = c(0, 1E6), y = c(0, 0.3E6))) +
    theme(  panel.background = element_rect(fill = "white"),
        panel.grid = element_line(color = "gray95"))

image

DillonHammill commented 1 month ago

Do you get the same result when you remove xlim and ylim?

AlexBlais74 commented 1 month ago

Hello, thanks for looking into this. Without the axis limits I get this, with cyto_plot (first plot) and with ggcyto (second plot) There are some events with very high values, hence the need to set some limits.

image image

But I have found a way to generate a plot that has the aspect I would expect: instead of subsetting during plotting by setting xlim and ylim, I subsetted the flowset object itself.

# create FS
fs.sony_full <- flowCore::read.flowSet( files=name.sony, 
path=dir.sony,
truncate_max_range = FALSE)

# For filtering, design a rectangular gate with the limits I want
rectGate <- rectangleGate(  filterId="plot_limits",
"FSC-A"=c(0,1E6),
"SSC-A"=c(0,0.3E6))

# Subset the FS using that gate
fs.sony_full.result <- flowCore::filter(fs.sony_full, rectGate)
fs.sony_full.subset <- Subset(fs.sony_full, fs.sony_full.result)

# Plot
cyto_plot(  fs.sony_full.subset, 
parent = "root",
channels = c("FSC-A", "SSC-A"),
display = 1,
point_size = 2,
contour_lines = 10)

image

So I get the plot I wanted but the workaround is not suitable for me as I would like to retain all events, even the most extremes. I am not an expert, but is it possible that the plot colors are determined on the full dataset, without taking into account the values of xlim and ylim? I can understand why this may be preferred by some users. However, it would also be nice to have the option of setting the colors based on the events that will be retained after the plot limits are set.

I have a feeling that the options "point_col_scale" and "point_cols" might be useful, however I am not sure how to employ them to obtain the result I am after.

Thanks Alex

AlexBlais74 commented 1 month ago

Note that my solution with flowCore::filter and Subset only works with a flowset or flowframe object. It does not work with a GatingSet object. I will have to do more reading to figure out how to implement the same with a GatingSet object.