DillonHammill / CytoExploreR

Interactive Cytometry Data Analysis
60 stars 13 forks source link

Extracting spillover matrices for cyto_compensate() #138

Closed rwbaer closed 2 years ago

rwbaer commented 2 years ago

Briefly describe what you hope to achieve: Typically, I have generated spillover matrices with code, but I thought I'd try using the ones that I generated while collecting the data on the cell sorter since comparisons on previous runs show them to be quite similar.

This seems straight forward according to the Issue 56 answer, but it has not been working with my data. It did work (apparently) fine with the Activation data.

I can verify that the spill matrices are present using flowcore. Do I somehow need to be more specific about the spillover parameter name? My matrix is in the parameter $$SPILLOVER of each .fcs file.

Error: > gsSamp <- cyto_compensate(gsSamp, spillover = NULL) Error in FUN(X[[i]], ...) : 'compensation' should be a compensation object, matrix or data.frame!

Outline the steps taken to attempt to reach this goal (paste code below): See console output below

...
# activation data set works
$Activation_33.fcs
                  Alexa Fluor 488-A     PE-A PE-Texas Red-A  7-AAD-A PE-Cy7-A
Alexa Fluor 488-A             1.000 0.188001       0.084001 0.018000 0.000000
PE-A                          0.006 1.000000       0.523009 0.168001 0.028000
PE-Texas Red-A                0.000 0.000000       1.000000 0.000000 0.000000
7-AAD-A                       0.000 0.000000       0.000056 1.000000 0.310001
PE-Cy7-A                      0.000 0.000000       0.000000 0.000000 1.000000
Alexa Fluor 405-A             0.000 0.000000       0.000000 0.000000 0.000000
Alexa Fluor 430-A             0.000 0.000000       0.000000 0.000000 0.000000
Qdot 605-A                    0.000 0.000000       0.000000 0.000000 0.000000
Alexa Fluor 647-A             0.000 0.000000       0.000000 0.026000 0.008000
Alexa Fluor 700-A             0.000 0.000000       0.000000 0.041000 0.049000
APC-Cy7-A                     0.016 0.010001       0.012001 0.016000 0.088000
                  Alexa Fluor 405-A Alexa Fluor 430-A Qdot 605-A Alexa Fluor 647-A
Alexa Fluor 488-A             0.000          0.014001   0.000000             0.000
PE-A                          0.000          0.000000   0.132001             0.000
PE-Texas Red-A                0.000          0.000000   0.000000             0.000
7-AAD-A                       0.000          0.000000   0.000000             0.006
PE-Cy7-A                      0.000          0.000000   0.000000             0.000
Alexa Fluor 405-A             1.000          0.000000   0.000000             0.000
Alexa Fluor 430-A             0.000          1.000000   0.000000             0.000
Qdot 605-A                    0.000          0.000000   1.000000             0.000
Alexa Fluor 647-A             0.000          0.000000   0.003000             1.000
Alexa Fluor 700-A             0.000          0.000000   0.000000             0.004
APC-Cy7-A                     0.012          0.008001   0.019000             0.032
                  Alexa Fluor 700-A APC-Cy7-A
Alexa Fluor 488-A             0.000     0.000
PE-A                          0.000     0.000
PE-Texas Red-A                0.000     0.000
7-AAD-A                       0.037     0.015
PE-Cy7-A                      0.000     0.000
Alexa Fluor 405-A             0.000     0.000
Alexa Fluor 430-A             0.000     0.000
Qdot 605-A                    0.000     0.000
Alexa Fluor 647-A             0.359     0.090
Alexa Fluor 700-A             1.000     0.270
APC-Cy7-A                     0.114     1.000

> 
> # My dataset
> gsSamp <- cyto_setup(path = "Samples",
+                      gatingTemplate = "Samples-Template.csv",
+                      details = "Samples-Details.csv",
+                      restrict = TRUE)
Loading FCS files into a GatingSet...
Assigning markers to channels...
Experiment-Markers.csv found in working directory.
Updating experiment details...
Samples-Details.csv found in working directory.
Removing unassigned channels...
Setting Samples-Template.csv as the active gatingTemplate...
Done!
> 
> # According to issue 56, I thought this would work
> # Apply compensation to samples, based on the spill matrix stored 
> #    in .fcs files.
**> gsSamp <- cyto_compensate(gsSamp, spillover = NULL)
Error in FUN(X[[i]], ...) : 
  'compensation' should be a compensation object, matrix or data.frame!**
> cyto_spillover_extract(gsSamp)
NULL
> 
> # the basic way using flowcore
> fil = list.files("./Samples", pattern = ".fcs")
> fsSamp = read.flowSet(fil, path = "./Samples")
> spillover(fsSamp[[3]])
$SPILL
NULL

$spillover
NULL

$`$SPILLOVER`
     FL1-AREA    FL2-AREA FL3-AREA   FL4-AREA
[1,]        1 0.000000000        0 0.00000000
[2,]        0 1.000000000        0 0.07894737
[3,]        0 0.000000000        1 0.00000000
[4,]        0 0.007643312        0 1.00000000

Include any associated screenshots or images here:

DillonHammill commented 2 years ago

Thanks for reporting this @rwbaer, I will need to make the keyword search a bit more flexible to better handle data from other instruments.

DillonHammill commented 2 years ago

I just pushed a fixed to the master branch - please pull it down and try again.

devtools::install_github("DillonHammill/CytoExploreR")
rwbaer commented 2 years ago

We don't quite seem to be there yet.

> # According to issue 56, I thought this would work
> # Apply compensation to samples, based on the spill matrix stored 
> #    in .fcs files.
> # https://github.com/DillonHammill/CytoExploreR/issues/56
> 
> # CytoExploreR 
> devtools::install_github("DillonHammill/CytoExploreR")
Skipping install of 'CytoExploreR' from a github remote, the SHA1 (b8e9e458) has not changed since last install.
  Use `force = TRUE` to force installation
> 
> library(CytoExploreRData)
> fs <- Activation
> gs <- GatingSet(fs)
> 
> cyto_spillover_extract(fs)[1]
$Activation_1.fcs
      Alexa Fluor 488-A       PE-A PE-Texas Red-A    7-AAD-A    PE-Cy7-A Alexa Fluor 405-A Alexa Fluor 430-A
 [1,]       1.000000000 0.18800066   0.0840010055 0.01800011 0.000000000        0.00000000        0.01400073
 [2,]       0.006000035 1.00000000   0.5230093475 0.16800103 0.028000168        0.00000000        0.00000000
 [3,]       0.000000000 0.00000000   1.0000000000 0.00000000 0.000000000        0.00000000        0.00000000
 [4,]       0.000000000 0.00000000   0.0000556259 1.00000000 0.310001025        0.00000000        0.00000000
 [5,]       0.000000000 0.00000000   0.0000000000 0.00000000 1.000000000        0.00000000        0.00000000
 [6,]       0.000000000 0.00000000   0.0000000000 0.00000000 0.000000000        1.00000000        0.00000000
 [7,]       0.000000000 0.00000000   0.0000000000 0.00000000 0.000000000        0.00000000        1.00000000
 [8,]       0.000000000 0.00000000   0.0000000000 0.00000000 0.000000000        0.00000000        0.00000000
 [9,]       0.000000000 0.00000000   0.0000000000 0.02600016 0.008000026        0.00000000        0.00000000
[10,]       0.000000000 0.00000000   0.0000000000 0.04100026 0.049000041        0.00000000        0.00000000
[11,]       0.016000008 0.01000058   0.0120008920 0.01600009 0.088000019        0.01199991        0.00800065
       Qdot 605-A Alexa Fluor 647-A Alexa Fluor 700-A APC-Cy7-A
 [1,] 0.000000000       0.000000000        0.00000000     0.000
 [2,] 0.132000815       0.000000000        0.00000000     0.000
 [3,] 0.000000000       0.000000000        0.00000000     0.000
 [4,] 0.000000000       0.005999995        0.03699999     0.015
 [5,] 0.000000000       0.000000000        0.00000000     0.000
 [6,] 0.000000000       0.000000000        0.00000000     0.000
 [7,] 0.000000000       0.000000000        0.00000000     0.000
 [8,] 1.000000000       0.000000000        0.00000000     0.000
 [9,] 0.003000122       1.000000000        0.35900000     0.090
[10,] 0.000000000       0.004000004        1.00000000     0.270
[11,] 0.019000078       0.032000004        0.11400001     1.000

> cyto_spillover_extract(gs)
NULL
> gs <- cyto_compensate(gs) # use first sample spill, I think
> cyto_spillover_extract(gs)[1]
$Activation_1.fcs
                  Alexa Fluor 488-A     PE-A PE-Texas Red-A  7-AAD-A PE-Cy7-A Alexa Fluor 405-A Alexa Fluor 430-A
Alexa Fluor 488-A             1.000 0.188001       0.084001 0.018000 0.000000             0.000          0.014001
PE-A                          0.006 1.000000       0.523009 0.168001 0.028000             0.000          0.000000
PE-Texas Red-A                0.000 0.000000       1.000000 0.000000 0.000000             0.000          0.000000
7-AAD-A                       0.000 0.000000       0.000056 1.000000 0.310001             0.000          0.000000
PE-Cy7-A                      0.000 0.000000       0.000000 0.000000 1.000000             0.000          0.000000
Alexa Fluor 405-A             0.000 0.000000       0.000000 0.000000 0.000000             1.000          0.000000
Alexa Fluor 430-A             0.000 0.000000       0.000000 0.000000 0.000000             0.000          1.000000
Qdot 605-A                    0.000 0.000000       0.000000 0.000000 0.000000             0.000          0.000000
Alexa Fluor 647-A             0.000 0.000000       0.000000 0.026000 0.008000             0.000          0.000000
Alexa Fluor 700-A             0.000 0.000000       0.000000 0.041000 0.049000             0.000          0.000000
APC-Cy7-A                     0.016 0.010001       0.012001 0.016000 0.088000             0.012          0.008001
                  Qdot 605-A Alexa Fluor 647-A Alexa Fluor 700-A APC-Cy7-A
Alexa Fluor 488-A   0.000000             0.000             0.000     0.000
PE-A                0.132001             0.000             0.000     0.000
PE-Texas Red-A      0.000000             0.000             0.000     0.000
7-AAD-A             0.000000             0.006             0.037     0.015
PE-Cy7-A            0.000000             0.000             0.000     0.000
Alexa Fluor 405-A   0.000000             0.000             0.000     0.000
Alexa Fluor 430-A   0.000000             0.000             0.000     0.000
Qdot 605-A          1.000000             0.000             0.000     0.000
Alexa Fluor 647-A   0.003000             1.000             0.359     0.090
Alexa Fluor 700-A   0.000000             0.004             1.000     0.270
APC-Cy7-A           0.019000             0.032             0.114     1.000

> 
> # My dataset
> gsSamp <- cyto_setup(path = "Samples",
+   gatingTemplate = "Samples-Template.csv",
+   details = "Samples-Details.csv",
+   restrict = TRUE)
Loading FCS files into a GatingSet...
Assigning markers to channels...
Experiment-Markers.csv found in working directory.
Updating experiment details...
Samples-Details.csv found in working directory.
Removing unassigned channels...
Setting Samples-Template.csv as the active gatingTemplate...
Done!
> 
> cyto_spillover_extract(gsSamp)
NULL
> gsSamp <- cyto_compensate(gsSamp) # use first sample spill for all samples, I think
Error in cyto_compensate.GatingSet(gsSamp) : 
  Unable to extract spillover matrix from selected sample.
> cyto_spillover_extract(gsSamp)
NULL
> 
> # Issue 56 - use each data set's own spill matrix for compensation
> #  " ... and you can set select = NULL to apply the spillover matrix attached to each fcs file"
> #  Not documented in ?cyto_compensate
> gsSamp <- cyto_compensate(gsSamp, select = NULL)
Error in FUN(X[[i]], ...) : 
  Unable to extract spillover matrix from M0_CCR7-CD36-CD80-SytoxAAD_S1.fcs.
> cyto_spillover_extract(gsSamp)  # doesn't work either
NULL
> 
> # Prove a spillmatrix is present and it's keyword
> fil = list.files("./Samples", pattern = ".fcs")
> fsSamp = read.flowSet(fil, path = "./Samples")
> spillover(fsSamp[[1]])
$SPILL
NULL

$spillover
NULL

$`$SPILLOVER`
        FL1-AREA  FL2-AREA     FL3-AREA    FL4-AREA
[1,]  1.00000000 0.2952381 -0.038095238 -0.03809524
[2,] -0.01367781 1.0000000 -0.006079027 -0.01519757
[3,] -0.14516129 0.1451613  1.000000000  0.37096774
[4,]  0.11016949 0.7203390 -0.008474576  1.00000000

> 
> spillmat = spillover(fsSamp[[1]])
> spillmat = spillover(fsSamp[[1]])$`$SPILLOVER`
> spillmat
        FL1-AREA  FL2-AREA     FL3-AREA    FL4-AREA
[1,]  1.00000000 0.2952381 -0.038095238 -0.03809524
[2,] -0.01367781 1.0000000 -0.006079027 -0.01519757
[3,] -0.14516129 0.1451613  1.000000000  0.37096774
[4,]  0.11016949 0.7203390 -0.008474576  1.00000000
DillonHammill commented 2 years ago

You are trying to do two different things. Spillover matrices are only extracted from GatingSets if they have been applied using cyto_compensate(). If you want the matrices from the machine, you must first extract the data into a cytoset and then pull out the matrices using cyto_spillover_extract().

Please try extracting the matrices from your cytoset. The behaviour for GatingSets is correct.

rwbaer commented 2 years ago

I think I am struggling with the concept of "applied"

When I ran the line:

 gsSamp <- cyto_compensate(gsSamp)      #  I "thought" I was applying with this line.  
#  (and this seemed to work for Activation set)

I expected cyto_spillover_extract() to fail before running that line, but succeed after running that line. I thought that was "applying". Could you enlighten me on what "applying" means"?

I guess I still need to educate myself on the fundamentals of GatingSet objects. Unfortunately, I'm not (yet??) well versed in inspecting S4 objects.

DillonHammill commented 2 years ago

I updated my previous comment. Can you confirm whether cyto_compensate() works for your GatingSet when no spillover is supplied? If that works this issue is resolved.

rwbaer commented 2 years ago

Not sure the update to your previous comment came through, but I attempted to do nothing but try cyto_compensate() with no spillover specified. Hope I am following instructions properly.

Here is the result:

> # CytoExploreR 
> devtools::install_github("DillonHammill/CytoExploreR")
Skipping install of 'CytoExploreR' from a github remote, the SHA1 (b8e9e458) has not changed since last install.
  Use `force = TRUE` to force installation
> library(CytoExploreR)
Loading required package: flowCore
Loading required package: flowWorkspace
As part of improvements to flowWorkspace, some behavior of
GatingSet objects has changed. For details, please read the section
titled "The cytoframe and cytoset classes" in the package vignette:

  vignette("flowWorkspace-Introduction", "flowWorkspace")
Loading required package: openCyto
> # My dataset
> gsSamp <- cyto_setup(path = "Samples",
+                      gatingTemplate = "Samples-Template.csv",
+                      details = "Samples-Details.csv",
+                      restrict = TRUE)
Loading FCS files into a GatingSet...
Assigning markers to channels...
Experiment-Markers.csv found in working directory.
Loading required package: shiny
Updating experiment details...
Samples-Details.csv found in working directory.
Removing unassigned channels...
Setting Samples-Template.csv as the active gatingTemplate...
Done!
> gsSamp <- cyto_compensate(gsSamp) # use first sample spill for all samples
Error in cyto_compensate.GatingSet(gsSamp) : 
  Unable to extract spillover matrix from selected sample.
DillonHammill commented 2 years ago

OK and the output of calling cyto_spillover_extract() on your cytoset?

DillonHammill commented 2 years ago

Are you able to share a file with me? It may be easier for me to debug things that way.

rwbaer commented 2 years ago

Again, I'm not clear if I'm doing what you want, but here is what I tried (a different gs from the same cell sorter that I happen to have open)

> cs = gs_pop_get_data(gsNecrosis, "root")
> cyto_spillover_extract(cs)
NULL
rwbaer commented 2 years ago

Sure. I can share a file. (sorry - forgot I had to zip and got hung up) M0_CCR7_CD172_CD209_SytoxAAD_S1.zip

DillonHammill commented 2 years ago

I just pushed the fix to master. Please pull it down and try again:

devtools::install_github("DillonHammill/CytoExploreR")
rwbaer commented 2 years ago

@DillonHammill Thank you. The patch seems to be working now.

Before closing this issue, I'd like to suggest a 'documentation enhancement' related to the undocumented behavior shared in your response to issue #56.

In issue #56 response, you refer to code of the form

gsSamp <- cyto_compensate(gsSamp, select = NULL)

as being a mechanism to apply each .fcs file's spill matrix to itself as opposed to the default format

gsSamp <- cyto_compensate(gsSamp)

applying the spill matrix from the first sample to all samples.

I do not think this is currently documented in help. If this behavior is really available, I would encourage you to document it in the cyto_compensate() help file. There certainly are circumstances where it might be beneficial.

(PS - I dont know how to change the tag from 'help wanted' to 'request enhancement' so I'm leaving it) Thanks, again for your incredible responsiveness!!

DillonHammill commented 2 years ago

Thanks for reporting this issue. All the details are already in the docs: https://dillonhammill.github.io/CytoExploreR/reference/cyto_compensate.html