Skip to contents

Introduction

This vignette builds on what can be done with the outputs from the Luciernaga_QC() function that was the main focus of vignette 04_FluorescenceSignatures. Please read that vignette for all the details regarding how the function processes the .fcs files into individual signatures.

The following vignette covers the different functions that take these Luciernaga_QC() outputs, either in the “data” or “fcs” format, and process them into useful reports to gain insight into the fluorescence signatures that are present within your unmixing controls (both single-color and unstained). At the end of this vignette, we will discuss how we can extend these reports to visualize changes in signature across time to monitor for changes in antibody-vial quality or instrument health.

Some of these functions we will cover in this vignette will also resurface when we look at the Luciernaga unmixing functions that will be covered in Vignette_06.

Set Up

For this vignette, we will focus on characterizing the cell unmixing controls. The following setup code is a repeat from previous vignettes, and is used to provide the Luciernaga_QC() outputs needed by the functions that we will be covering.

Let’s first load the required packages by calling them with library.

Then we can find the .fcs files stored within the Luciernaga packages extdata folder and sort them by their respective type

File_Location <- system.file("extdata", package = "Luciernaga")
FCS_Pattern <- ".fcs$"
FCS_Files <- list.files(path = File_Location, pattern = FCS_Pattern,
                        full.names = TRUE, recursive = FALSE)
head(FCS_Files[10:30], 20)
#>  [1] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/21_Before.fcs"             
#>  [2] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/22_After.fcs"              
#>  [3] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/22_Before.fcs"             
#>  [4] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/23_After.fcs"              
#>  [5] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/23_Before.fcs"             
#>  [6] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/4BeadsUnstained(Beads).fcs"
#>  [7] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CCR4_BUV615(Beads).fcs"    
#>  [8] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CCR4_BUV615(Cells).fcs"    
#>  [9] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CCR6_BV786(Beads).fcs"     
#> [10] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CCR6_BV786(Cells).fcs"     
#> [11] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CCR7_BV650(Beads).fcs"     
#> [12] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CCR7_BV650(Cells).fcs"     
#> [13] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CD107a_APC-R700(Beads).fcs"
#> [14] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CD107a_APC-R700(Cells).fcs"
#> [15] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CD127_BV421(Beads).fcs"    
#> [16] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CD127_BV421(Cells).fcs"    
#> [17] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CD16_APC(Beads).fcs"       
#> [18] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CD16_APC(Cells).fcs"       
#> [19] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CD161_BV480(Beads).fcs"    
#> [20] "C:/Users/12692/AppData/Local/R/win-library/4.4/Luciernaga/extdata/CD161_BV480(Cells).fcs"
UnstainedFCSFiles <- FCS_Files[grep("Unstained", FCS_Files)]
UnstainedBeads <- UnstainedFCSFiles[grep("Beads", UnstainedFCSFiles)]
UnstainedCells <- UnstainedFCSFiles[-grep("Beads", UnstainedFCSFiles)]

BeadFCSFiles <- FCS_Files[grep("Beads", FCS_Files)]
BeadSingleColors <- BeadFCSFiles[-grep("Unstained", BeadFCSFiles)]

CellSingleColorFiles <- FCS_Files[grep("Cells", FCS_Files)]
CellSingleColors <- CellSingleColorFiles[!str_detect("Unstained", CellSingleColorFiles)]

Now lets create a GatingSet for our single-color cell unmixing controls

MyCytoSet <- load_cytoset_from_fcs(CellSingleColors, 
                                   truncate_max_range = FALSE, 
                                   transform = FALSE)
MyCytoSet
#> A cytoset with 30 samples.
#> 
#>   column names:
#>     Time, UV1-A, UV2-A, UV3-A, UV4-A, UV5-A, UV6-A, UV7-A, UV8-A, UV9-A, UV10-A, UV11-A, UV12-A, UV13-A, UV14-A, UV15-A, UV16-A, SSC-W, SSC-H, SSC-A, V1-A, V2-A, V3-A, V4-A, V5-A, V6-A, V7-A, V8-A, V9-A, V10-A, V11-A, V12-A, V13-A, V14-A, V15-A, V16-A, FSC-W, FSC-H, FSC-A, SSC-B-W, SSC-B-H, SSC-B-A, B1-A, B2-A, B3-A, B4-A, B5-A, B6-A, B7-A, B8-A, B9-A, B10-A, B11-A, B12-A, B13-A, B14-A, YG1-A, YG2-A, YG3-A, YG4-A, YG5-A, YG6-A, YG7-A, YG8-A, YG9-A, YG10-A, R1-A, R2-A, R3-A, R4-A, R5-A, R6-A, R7-A, R8-A
MyGatingSet <- GatingSet(MyCytoSet)
MyGatingSet
#> A GatingSet with 30 samples
FileLocation <- system.file("extdata", package = "Luciernaga")
MyGates <- fread(file.path(path = FileLocation, pattern = 'Gates.csv'))
gt(MyGates)
alias pop parent dims gating_method gating_args collapseDataForGating groupBy preprocessing_method preprocessing_args
singletsFSC + root FSC-A,FSC-H singletGate FALSE NA NA NA
singletsSSC + singletsFSC SSC-A,SSC-H singletGate FALSE NA NA NA
singletsSSCB + singletsSSC SSC-A,SSC-B-A singletGate FALSE NA NA NA
nonDebris + singletsSSCB FSC-A gate_mindensity FALSE NA NA NA
lymphocytes + nonDebris FSC-A, SSC-A flowClust K=2, target=c(1e5, 5e4) FALSE NA NA NA
MyGatingTemplate <- gatingTemplate(MyGates)
gt_gating(MyGatingTemplate, MyGatingSet)
MyGatingSet[[1]]
#> Sample:  CCR4_BUV615(Cells).fcs 
#> GatingHierarchy with  6  gates

Now lets create a GatingSet for our unstained cell unmixing controls

MyUnstainedCytoSet <- load_cytoset_from_fcs(UnstainedCells, 
                                   truncate_max_range = FALSE, 
                                   transform = FALSE)
MyUnstainedCytoSet
#> A cytoset with 18 samples.
#> 
#>   column names:
#>     Time, UV1-A, UV2-A, UV3-A, UV4-A, UV5-A, UV6-A, UV7-A, UV8-A, UV9-A, UV10-A, UV11-A, UV12-A, UV13-A, UV14-A, UV15-A, UV16-A, SSC-W, SSC-H, SSC-A, V1-A, V2-A, V3-A, V4-A, V5-A, V6-A, V7-A, V8-A, V9-A, V10-A, V11-A, V12-A, V13-A, V14-A, V15-A, V16-A, FSC-W, FSC-H, FSC-A, SSC-B-W, SSC-B-H, SSC-B-A, B1-A, B2-A, B3-A, B4-A, B5-A, B6-A, B7-A, B8-A, B9-A, B10-A, B11-A, B12-A, B13-A, B14-A, YG1-A, YG2-A, YG3-A, YG4-A, YG5-A, YG6-A, YG7-A, YG8-A, YG9-A, YG10-A, R1-A, R2-A, R3-A, R4-A, R5-A, R6-A, R7-A, R8-A
MyUnstainedGatingSet <- GatingSet(MyUnstainedCytoSet)
MyUnstainedGatingSet
#> A GatingSet with 18 samples
FileLocation <- system.file("extdata", package = "Luciernaga")
MyGates <- fread(file.path(path = FileLocation, pattern = 'Gates.csv'))
gt(MyGates)
alias pop parent dims gating_method gating_args collapseDataForGating groupBy preprocessing_method preprocessing_args
singletsFSC + root FSC-A,FSC-H singletGate FALSE NA NA NA
singletsSSC + singletsFSC SSC-A,SSC-H singletGate FALSE NA NA NA
singletsSSCB + singletsSSC SSC-A,SSC-B-A singletGate FALSE NA NA NA
nonDebris + singletsSSCB FSC-A gate_mindensity FALSE NA NA NA
lymphocytes + nonDebris FSC-A, SSC-A flowClust K=2, target=c(1e5, 5e4) FALSE NA NA NA
MyGatingTemplate <- gatingTemplate(MyGates)
gt_gating(MyGatingTemplate, MyUnstainedGatingSet)
MyUnstainedGatingSet[[1]]
#> Sample:  INF071_Ctrl_Unstained.fcs 
#> GatingHierarchy with  6  gates

Generate Luciernaga_QC Outputs

Now that the GatingSets are re-established, let’s continue where the last vignette left off by processing all the fcs files with Luciernaga_QC to characterize the fluorescent signatures within.

Let’s first provision the AFOverlap csv to handle conflicts.

FileLocation <- system.file("extdata", package = "Luciernaga")
pattern = "AutofluorescentOverlaps.csv"
AFOverlap <- list.files(path=FileLocation, pattern=pattern,
                        full.names = TRUE)
AFOverlap_CSV <- read.csv(AFOverlap, check.names = FALSE)
AFOverlap_CSV
#>   Fluorophore         MainDetector
#> 1   Unstained UV7-A,V7-A,V3-A,V5-A
#> 2      BUV496                UV7-A
#> 3       BV480                 V5-A
#> 4       BV510                 V7-A
#> 5       BV570                 V8-A

And next generate a CellAF unstained signature that can be used when these fluorophore-autofluorescence overlap files are encountered:

# pData(MyUnstainedGatingSet[1])
removestrings <- c(".fcs")

TheCellAF <- map(.x=MyUnstainedGatingSet[1], .f=Luciernaga_QC, subsets="lymphocytes",
                              removestrings=removestrings, sample.name="GUID",
                              unmixingcontroltype = "cells", Unstained = TRUE,
                              ratiopopcutoff = 0.001, Verbose = FALSE,
                              AFOverlap = AFOverlap, stats = "median",
                              ExportType = "data", SignatureReturnNow = TRUE,
                              outpath = TemporaryFolder, Increments=0.1,
                              SecondaryPeaks=2, experiment = "FirstExperiment",
                              condition = "ILTPanel", SCData="subtracted",
                              NegativeType="default")
#> Normalizing Data for Signature Comparison

TheCellAF <- TheCellAF[[1]] #Removes list caused by map

gt(TheCellAF)
UV1-A UV2-A UV3-A UV4-A UV5-A UV6-A UV7-A UV8-A UV9-A UV10-A UV11-A UV12-A UV13-A UV14-A UV15-A UV16-A V1-A V2-A V3-A V4-A V5-A V6-A V7-A V8-A V9-A V10-A V11-A V12-A V13-A V14-A V15-A V16-A B1-A B2-A B3-A B4-A B5-A B6-A B7-A B8-A B9-A B10-A B11-A B12-A B13-A B14-A YG1-A YG2-A YG3-A YG4-A YG5-A YG6-A YG7-A YG8-A YG9-A YG10-A R1-A R2-A R3-A R4-A R5-A R6-A R7-A R8-A
359.38 612.9988 437.0275 559.4488 779.7476 1246.153 2423.138 1793.776 1682.139 625.345 402.5919 251.5363 198.8788 255.1806 175.5994 168.3106 379.9125 1167.719 1815.069 2080.031 3214.613 3112.45 4226.681 3096.637 2104.025 2316.6 1251.25 704.825 632.8438 574.3375 518.1688 295.5562 1192.289 1367.454 1904.727 1289.431 1090.77 870.5431 619.2231 459.5087 477.0831 316.0812 239.0244 221.5788 163.0619 210.1844 516.2194 394.8131 402.2363 388.5 308.8575 310.3838 380.73 196.4006 195.2213 131.2575 189.9812 239.6306 253.4731 285.1131 152.1969 142.1681 129.8794 89.97625

We will start with the ExportType = “data” return for now for both the cell Single-Color and Unstained Unmixing controls.

SingleColor_Data <- map(.x=MyGatingSet, .f=Luciernaga_QC, subsets="lymphocytes",
                              removestrings=removestrings, sample.name="GUID",
                              unmixingcontroltype = "cells", Unstained = FALSE,
                              ratiopopcutoff = 0.001, Verbose = FALSE,
                              AFOverlap = AFOverlap, stats = "median",
                              ExportType = "data", SignatureReturnNow = FALSE,
                              outpath = TemporaryFolder, Increments=0.1,
                              SecondaryPeaks=2, experiment = "FirstExperiment",
                              condition = "ILTPanel", Subtraction = "Internal", 
                              CellAF=TheCellAF, SCData="subtracted",
                              NegativeType="default") %>% bind_rows()
#> No second peak
#> No second peak
#> No second peak
#> Only a single detector present. If this was not an autofluorescence overlap
#>               fluourophore, it would suggest there was no antibody staining, or everything
#>               was overstained. Please investigate further.
#> No second peak
#> No second peak
#> No second peak
nrow(SingleColor_Data)
#> [1] 2598
gt(head(SingleColor_Data, 5))
Sample Experiment Condition Cluster Count UV1 UV2 UV3 UV4 UV5 UV6 UV7 UV8 UV9 UV10 UV11 UV12 UV13 UV14 UV15 UV16 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 YG1 YG2 YG3 YG4 YG5 YG6 YG7 YG8 YG9 YG10 R1 R2 R3 R4 R5 R6 R7 R8
CCR4_BUV615(Cells) FirstExperiment ILTPanel UV10_10-YG3_09-V10_03 95 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.30 1 0.5 0.3 0.2 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.10 0.1 0.1 0.1 0.1 0.0 0.00 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.10 0.1 0.10 0.1 0.1 0.4 0.9 0.4 0.3 0.3 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
CCR4_BUV615(Cells) FirstExperiment ILTPanel UV10_10-YG3_09-V10_04 35 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.30 1 0.5 0.3 0.2 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.4 0.20 0.1 0.1 0.1 0.1 0.1 0.10 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.10 0.1 0.10 0.1 0.1 0.4 0.9 0.4 0.3 0.3 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.0 0.1 0.0
CCR4_BUV615(Cells) FirstExperiment ILTPanel UV10_10-YG3_08-V10_03 32 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.35 1 0.4 0.3 0.2 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.3 0.15 0.1 0.1 0.1 0.1 0.1 0.05 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.05 0.0 0.05 0.0 0.1 0.4 0.8 0.4 0.3 0.3 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.0 0.1 0.1 0.1 0.0
CCR4_BUV615(Cells) FirstExperiment ILTPanel UV10_10-YG3_08-V10_04 25 0.1 0.1 0.1 0.1 0.2 0.2 0.5 0.4 0.60 1 0.5 0.3 0.2 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.4 0.20 0.1 0.1 0.1 0.1 0.1 0.10 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.00 0.1 0.10 0.0 0.1 0.4 0.8 0.4 0.3 0.3 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.0 0.0 0.1 0.1
CCR4_BUV615(Cells) FirstExperiment ILTPanel UV10_10-YG3_10-V10_03 19 0.0 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.30 1 0.5 0.3 0.2 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.3 0.10 0.1 0.1 0.1 0.0 0.0 0.10 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.0 0.10 0.0 0.10 0.0 0.1 0.5 1.0 0.5 0.4 0.3 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.0 0.0 0.0 0.1 0.0

Let’s now repeat this process for the Unstained GatingSet.

# pData(MyUnstainedGatingSet)

Unstained_Data <- map(.x=MyUnstainedGatingSet, .f=Luciernaga_QC, subsets="lymphocytes",
                              removestrings=removestrings, sample.name="GUID",
                              unmixingcontroltype = "cells", Unstained = TRUE,
                              ratiopopcutoff = 0.001, Verbose = FALSE,
                              AFOverlap = AFOverlap, stats = "median",
                              ExportType = "data", SignatureReturnNow = FALSE,
                              outpath = TemporaryFolder, Increments=0.1,
                              SecondaryPeaks=2, experiment = "FirstExperiment",
                              condition = "ILTPanel", Subtraction = "Internal", 
                              CellAF=TheCellAF, SCData="subtracted",
                              NegativeType="default") %>% bind_rows()
nrow(Unstained_Data)
#> [1] 1752
gt(head(Unstained_Data, 5))
Sample Experiment Condition Cluster Count UV1 UV2 UV3 UV4 UV5 UV6 UV7 UV8 UV9 UV10 UV11 UV12 UV13 UV14 UV15 UV16 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 YG1 YG2 YG3 YG4 YG5 YG6 YG7 YG8 YG9 YG10 R1 R2 R3 R4 R5 R6 R7 R8
INF071_Ctrl_Unstained FirstExperiment ILTPanel V7_10-UV8_05-B3_05 641 0.1 0.2 0.1 0.2 0.2 0.3 0.6 0.5 0.4 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.5 0.5 0.8 0.8 1 0.8 0.5 0.6 0.3 0.2 0.2 0.2 0.2 0.1 0.3 0.4 0.5 0.4 0.3 0.3 0.2 0.2 0.20 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
INF071_Ctrl_Unstained FirstExperiment ILTPanel V7_10-UV8_04-B3_05 536 0.1 0.2 0.1 0.2 0.2 0.3 0.6 0.4 0.4 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.5 0.5 0.8 0.8 1 0.8 0.5 0.6 0.3 0.2 0.2 0.2 0.2 0.1 0.3 0.4 0.5 0.3 0.3 0.3 0.2 0.2 0.20 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
INF071_Ctrl_Unstained FirstExperiment ILTPanel V7_10-UV8_05-B3_06 362 0.1 0.2 0.1 0.2 0.2 0.3 0.6 0.5 0.5 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.5 0.5 0.8 0.8 1 0.8 0.6 0.6 0.4 0.2 0.2 0.2 0.2 0.1 0.4 0.4 0.6 0.4 0.3 0.3 0.2 0.2 0.20 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
INF071_Ctrl_Unstained FirstExperiment ILTPanel V7_10-UV8_05-B3_04 330 0.1 0.2 0.2 0.2 0.2 0.4 0.6 0.5 0.4 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.5 0.5 0.8 0.8 1 0.8 0.5 0.6 0.3 0.2 0.2 0.2 0.2 0.1 0.3 0.3 0.4 0.3 0.3 0.2 0.2 0.2 0.15 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
INF071_Ctrl_Unstained FirstExperiment ILTPanel V7_10-UV8_04-B3_04 329 0.1 0.2 0.2 0.2 0.2 0.3 0.6 0.4 0.4 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.5 0.5 0.8 0.8 1 0.7 0.5 0.6 0.3 0.2 0.2 0.2 0.2 0.1 0.3 0.3 0.4 0.3 0.3 0.2 0.2 0.1 0.10 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1

Luciernaga_Plots

The Luciernaga_Plots() function works directly from the Luciernaga_QC() output when the ExportType = “data”. Let’s start exploring what it can do.

We will first provide a file.path to the panel information, which will be used by Luciernaga_Plots() to arrange the plots/report by the order of the fluorophores listed in the panel. If there is a mismatch between the fluorophore data and the panel, it will not rearrange but proceed to the output.

FileLocation <- system.file("extdata", package = "Luciernaga")
pattern = "^Panel.csv"
CSV <- list.files(path=FileLocation, pattern=pattern, full.names=TRUE)
TheFluorophoreOrder <- read.csv(CSV, check.names = FALSE)

The SingleColor_Data output from above currently contains the information for every single fluorophore .fcs file that was processed. While we can pass the entire object to Luciernaga_Plots() and it will process a report for each, we can also tailor our output by using dplyr to target particular fluorophores of interest if we want to find information for a specific fluorophore.

BUV615 <- SingleColor_Data %>% filter(str_detect(Sample, "BUV615"))
nrow(BUV615)
#> [1] 100
head(BUV615)
#>               Sample      Experiment Condition               Cluster Count UV1
#> 1 CCR4_BUV615(Cells) FirstExperiment  ILTPanel UV10_10-YG3_09-V10_03    95 0.1
#> 2 CCR4_BUV615(Cells) FirstExperiment  ILTPanel UV10_10-YG3_09-V10_04    35 0.1
#> 3 CCR4_BUV615(Cells) FirstExperiment  ILTPanel UV10_10-YG3_08-V10_03    32 0.1
#> 4 CCR4_BUV615(Cells) FirstExperiment  ILTPanel UV10_10-YG3_08-V10_04    25 0.1
#> 5 CCR4_BUV615(Cells) FirstExperiment  ILTPanel UV10_10-YG3_10-V10_03    19 0.0
#> 6 CCR4_BUV615(Cells) FirstExperiment  ILTPanel UV10_10-YG3_09-V10_02    12 0.1
#>   UV2 UV3 UV4 UV5 UV6  UV7 UV8  UV9 UV10 UV11 UV12 UV13 UV14 UV15 UV16  V1  V2
#> 1 0.1 0.1 0.1 0.1 0.1 0.10 0.1 0.30    1  0.5  0.3 0.20  0.2  0.1  0.1 0.1 0.1
#> 2 0.1 0.1 0.1 0.1 0.1 0.20 0.1 0.30    1  0.5  0.3 0.20  0.2  0.1  0.1 0.1 0.1
#> 3 0.1 0.1 0.1 0.1 0.1 0.20 0.1 0.35    1  0.4  0.3 0.20  0.2  0.1  0.1 0.1 0.1
#> 4 0.1 0.1 0.1 0.2 0.2 0.50 0.4 0.60    1  0.5  0.3 0.20  0.2  0.1  0.1 0.1 0.1
#> 5 0.1 0.1 0.1 0.1 0.1 0.10 0.1 0.30    1  0.5  0.3 0.20  0.2  0.1  0.1 0.1 0.1
#> 6 0.1 0.1 0.1 0.1 0.1 0.05 0.0 0.30    1  0.5  0.3 0.15  0.1  0.1  0.1 0.0 0.1
#>     V3  V4  V5  V6  V7  V8  V9 V10  V11 V12  V13  V14  V15 V16   B1  B2  B3  B4
#> 1 0.10 0.1 0.1 0.1 0.1 0.1 0.1 0.3 0.10 0.1 0.10 0.10 0.10 0.0 0.00 0.1 0.1 0.1
#> 2 0.10 0.1 0.1 0.1 0.1 0.1 0.2 0.4 0.20 0.1 0.10 0.10 0.10 0.1 0.10 0.1 0.1 0.1
#> 3 0.10 0.1 0.1 0.1 0.1 0.1 0.2 0.3 0.15 0.1 0.10 0.10 0.10 0.1 0.05 0.1 0.1 0.1
#> 4 0.10 0.1 0.1 0.1 0.1 0.2 0.2 0.4 0.20 0.1 0.10 0.10 0.10 0.1 0.10 0.1 0.1 0.1
#> 5 0.10 0.1 0.1 0.1 0.1 0.1 0.2 0.3 0.10 0.1 0.10 0.10 0.00 0.0 0.10 0.1 0.1 0.1
#> 6 0.05 0.1 0.0 0.0 0.0 0.0 0.1 0.2 0.10 0.1 0.05 0.05 0.05 0.0 0.00 0.0 0.0 0.1
#>    B5  B6  B7  B8   B9 B10  B11  B12  B13  B14 YG1 YG2 YG3 YG4 YG5 YG6  YG7 YG8
#> 1 0.1 0.1 0.1 0.1 0.10 0.1 0.10 0.10 0.10 0.10 0.1 0.4 0.9 0.4 0.3 0.3 0.20 0.1
#> 2 0.1 0.1 0.1 0.1 0.10 0.1 0.10 0.10 0.10 0.10 0.1 0.4 0.9 0.4 0.3 0.3 0.20 0.1
#> 3 0.1 0.1 0.1 0.1 0.10 0.1 0.05 0.00 0.05 0.00 0.1 0.4 0.8 0.4 0.3 0.3 0.20 0.1
#> 4 0.1 0.1 0.1 0.1 0.10 0.1 0.00 0.10 0.10 0.00 0.1 0.4 0.8 0.4 0.3 0.3 0.20 0.1
#> 5 0.1 0.1 0.1 0.1 0.10 0.0 0.10 0.00 0.10 0.00 0.1 0.5 1.0 0.5 0.4 0.3 0.20 0.1
#> 6 0.1 0.1 0.1 0.1 0.05 0.0 0.00 0.05 0.10 0.05 0.1 0.4 0.9 0.4 0.4 0.3 0.25 0.1
#>   YG9 YG10  R1  R2  R3  R4  R5  R6  R7   R8
#> 1 0.1  0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.10
#> 2 0.1  0.1 0.1 0.1 0.1 0.1 0.1 0.0 0.1 0.00
#> 3 0.1  0.1 0.1 0.1 0.1 0.0 0.1 0.1 0.1 0.00
#> 4 0.1  0.1 0.1 0.1 0.1 0.1 0.0 0.0 0.1 0.10
#> 5 0.1  0.1 0.1 0.1 0.1 0.0 0.0 0.0 0.1 0.00
#> 6 0.1  0.1 0.1 0.1 0.1 0.1 0.0 0.0 0.0 0.05

As you can tell, we processed Luciernaga_QC() with increments set at 0.1 so there was a lot of splitting into specific Clusters for this fluorophore. This can be overwhelming for Luciernaga_Plots() default arguments in some individual circumstances, such as the example below:

TheFluorophoreOrder <- read.csv(CSV, check.names = FALSE)
TheFluorophore <- TheFluorophoreOrder %>% filter(Fluorophore %in% "BUV615")

ThePlotReport <- Luciernaga_Plots(data=BUV615, RetainedType="normalized", CellPopRatio=0.001,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="patchwork",
                                  LinePlots=TRUE, CosinePlots=TRUE, StackedBarPlots = TRUE,
                                  HeatmapPlots = TRUE, reference = TheFluorophore)
#> names not matching, no reorderring according to panel order
ThePlotReport[[1]]

To work around this, when the data.frame is handed to Luciernaga_Plot(), we can filter by CellPopRatio to dictate what percentage of the total outputed cells a Cluster needs to be to be visualized. For the clusters that are excluded, these are gathered by the function and classified as Cluster “Other”. Let’s see this in action by setting CellPopRatio to 0.05 (so a cluster is retained if it makes up 5% stained cells):

TheFluorophoreOrder <- read.csv(CSV, check.names = FALSE)
TheFluorophore <- TheFluorophoreOrder %>% filter(Fluorophore %in% "BUV615")

ThePlotReport <- Luciernaga_Plots(data=BUV615, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="patchwork",
                                  LinePlots=TRUE, CosinePlots=TRUE, StackedBarPlots = TRUE,
                                  HeatmapPlots = TRUE, reference = TheFluorophore)
#> names not matching, no reorderring according to panel order
ThePlotReport[[1]]

From the above we can see the basic available formats of the Luciernaga_Plots() outputs. Namely, from the Luciernaga_QC() output we can visualize LinePlots (showing visualized signatures), CosinePlots (showing the cosine similarity matrix values of individual signatures relative to each other), StackedBarPlots and HeatmapPlots (which in different ways show relative abundance of the cluster signatures).

For the above example, we are using the returntype=“patchwork” argument. As with other Luciernaga packages, it takes the same arguments that are passed to the Utility_Patchwork() function to dictate layout. Similarly, we can set returntype = “pdf” to generate a .pdf file with the report contents sent to the location specified by the outfolder and filename.


ThePlotReport <- Luciernaga_Plots(data=BUV615, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="patchwork",
                                  LinePlots=TRUE, CosinePlots=TRUE, StackedBarPlots = TRUE,
                                  HeatmapPlots = TRUE, reference = TheFluorophore, thecolumns=2,
                                  therows=2, width=7, height=9)
#> names not matching, no reorderring according to panel order
ThePlotReport[[1]]

In the cases above, the report returned all four plots. These can be turned on or off as desired. For example, if we want to only retrieve only individual plot elements, we would leave our desired plot value as TRUE, set the other plot arguments to FALSE.


ThePlotReport <- Luciernaga_Plots(data=BUV615, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="patchwork",
                                  LinePlots=TRUE, CosinePlots=FALSE, StackedBarPlots = FALSE,
                                  HeatmapPlots = TRUE, reference = TheFluorophore, thecolumns=2,
                                  therows=2, width=7, height=9)
#> names not matching, no reorderring according to panel order
ThePlotReport[[1]]

Additionally, we would switch from returntype = “patchwork” to “plots” to retrieve the actual ggplot2 object of interest. The returned objects are still in a list format, so we use rCRANpkg("purrr") flatten function to get rid of the list, allowing the ggplot2 object to be handed to rCRANpkg("plotly") ggplotly function to allow for interactive elements.

ThePlotReport <- Luciernaga_Plots(data=BUV615, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="plots",
                                  LinePlots=TRUE, CosinePlots=FALSE, StackedBarPlots = FALSE,
                                  HeatmapPlots = FALSE, reference = TheFluorophore)
#> names not matching, no reorderring according to panel order

ThePlotReport <- purrr::flatten(ThePlotReport)
plotly::ggplotly(ThePlotReport[[1]])
ThePlotReport <- Luciernaga_Plots(data=BUV615, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="plots",
                                  LinePlots=FALSE, CosinePlots=TRUE, StackedBarPlots = FALSE,
                                  HeatmapPlots = FALSE, reference = TheFluorophore)
#> names not matching, no reorderring according to panel order

ThePlotReport <- purrr::flatten(ThePlotReport)
plotly::ggplotly(ThePlotReport[[1]])
ThePlotReport <- Luciernaga_Plots(data=BUV615, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="plots",
                                  LinePlots=FALSE, CosinePlots=FALSE, StackedBarPlots = TRUE,
                                  HeatmapPlots = FALSE, reference = TheFluorophore)
#> names not matching, no reorderring according to panel order

ThePlotReport <- purrr::flatten(ThePlotReport)
plotly::ggplotly(ThePlotReport[[1]])
ThePlotReport <- Luciernaga_Plots(data=BUV615, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="plots",
                                  LinePlots=FALSE, CosinePlots=FALSE, StackedBarPlots = FALSE,
                                  HeatmapPlots = TRUE, reference = TheFluorophore)
#> names not matching, no reorderring according to panel order

ThePlotReport <- purrr::flatten(ThePlotReport)
plotly::ggplotly(ThePlotReport[[1]])

Since the returned plots are ggplot2 objects, you can additionally modify them further using ggplot2 arguments to change respective elements appearance and aesthetics however you see fit. Please refer to rCRANpkg("ggplot2") vignettes and tutorials on how to do this, as it’s outside of our scope for this vignette.

Having characterized the pieces of Luciernaga_Plots() for a single fluorophore, let’s quickly see how it behaves without the initial filtering for the entire SC_Data

TheFluorophoreOrder <- read.csv(CSV, check.names = FALSE)

ThePlotReport <- Luciernaga_Plots(data=SingleColor_Data, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="patchwork",
                                  LinePlots=TRUE, CosinePlots=TRUE, StackedBarPlots = TRUE,
                                  HeatmapPlots = TRUE, reference = TheFluorophore)
#> names not matching, no reorderring according to panel order
ThePlotReport[1:4]
#> [[1]]

#> 
#> [[2]]

#> 
#> [[3]]

#> 
#> [[4]]

As can be seen, it automatically processed the data for each individual fluorophore. As with the above, the arguments can be altered to turn on/off individual plot elements, change the orientation, and alter the return type as with the examples above.

TheFluorophoreOrder <- read.csv(CSV, check.names = FALSE)

ThePlotReport <- Luciernaga_Plots(data=SingleColor_Data, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="plots",
                                  LinePlots=FALSE, CosinePlots=FALSE, StackedBarPlots = FALSE,
                                  HeatmapPlots = TRUE, reference = TheFluorophore)
#> names not matching, no reorderring according to panel order
ThePlotReport[1:4]
#> [[1]]
#> [[1]][[1]]

#> 
#> 
#> [[2]]
#> [[2]][[1]]

#> 
#> 
#> [[3]]
#> [[3]][[1]]

#> 
#> 
#> [[4]]
#> [[4]][[1]]

The examples above relied on LuciernagaQC() ExportType = “data” output to generate the desired reports and plots. This can be saved by individual users as a .csv that can be retrieved for later use.

# Saving Elsewhere
StorageLocation <- file.path("C:", "Users", "JohnDoe", "Desktop")
TheName <- "SingleColorData.csv"
TheFinalLocation <- file.path(StorageLocation, TheName)
write.csv(SingleColor_Data, TheFinalLocation, row.names=FALSE)

# Reading in Later
TheRetrievedData <- read.csv(TheFinalLocation, check.names=FALSE)

Luciernaga_FCSToReport

Luciernaga_FCSToReport() is a function that handles cases when there is no LuciernagaQC() ExportType = “data” to allow for the generation of plots and reports, and instead, we need to take the LuciernagaQC() ExportType = “fcs” outputs from their storage folder and re-derrive the equivalent data to be used with Luciernaga_Plots().

To demonstrate this, let’s first switch the Luciernaga_QC() ExportType argument to “fcs” and store the same single-color output .fcs files within the temporary folder in a specific folder where we can retrieve them again when needed:

StorageLocation <- file.path(tempdir(), "LuciernagaTemporaryExamples")

if (!dir.exists(StorageLocation)) {
  dir.create(StorageLocation)
}

SingleColor_Data <- map(.x=MyGatingSet[c(1:22, 25:30)], .f=Luciernaga_QC, subsets="lymphocytes",
                              removestrings=removestrings, sample.name="GUID",
                              unmixingcontroltype = "cells", Unstained = FALSE,
                              ratiopopcutoff = 0.001, Verbose = FALSE,
                              AFOverlap = AFOverlap, stats = "median",
                              ExportType = "fcs", Brightness=TRUE, SignatureReturnNow = FALSE,
                              outpath = StorageLocation, Increments=0.1,
                              SecondaryPeaks=2, experiment = "FirstExperiment",
                              condition = "ILTPanel", Subtraction = "Internal", 
                              CellAF=TheCellAF, SCData="subtracted",
                              NegativeType="default")
#> No second peak
#> No second peak
#> No second peak
#> Only a single detector present. If this was not an autofluorescence overlap
#>               fluourophore, it would suggest there was no antibody staining, or everything
#>               was overstained. Please investigate further.
#> No second peak
#> No second peak
#> No second peak

TheLuciernagaOutputs_FCS <- list.files(StorageLocation, pattern="fcs", full.names = TRUE)
head(TheLuciernagaOutputs_FCS, 4)
#> [1] "C:\\Users\\12692\\AppData\\Local\\Temp\\RtmpyeBMqE/LuciernagaTemporaryExamples/CCR4_BUV615(Cells)_UV1010YG308V1003.fcs"
#> [2] "C:\\Users\\12692\\AppData\\Local\\Temp\\RtmpyeBMqE/LuciernagaTemporaryExamples/CCR4_BUV615(Cells)_UV1010YG308V1004.fcs"
#> [3] "C:\\Users\\12692\\AppData\\Local\\Temp\\RtmpyeBMqE/LuciernagaTemporaryExamples/CCR4_BUV615(Cells)_UV1010YG309V1003.fcs"
#> [4] "C:\\Users\\12692\\AppData\\Local\\Temp\\RtmpyeBMqE/LuciernagaTemporaryExamples/CCR4_BUV615(Cells)_UV1010YG309V1004.fcs"
TheLuciernagaOutputs_CSV <- list.files(StorageLocation, pattern="csv", full.names = TRUE)
head(TheLuciernagaOutputs_CSV, 4)
#> [1] "C:\\Users\\12692\\AppData\\Local\\Temp\\RtmpyeBMqE/LuciernagaTemporaryExamples/RelativeBrightnessCCR4_BUV615(Cells).csv"    
#> [2] "C:\\Users\\12692\\AppData\\Local\\Temp\\RtmpyeBMqE/LuciernagaTemporaryExamples/RelativeBrightnessCCR6_BV786(Cells).csv"     
#> [3] "C:\\Users\\12692\\AppData\\Local\\Temp\\RtmpyeBMqE/LuciernagaTemporaryExamples/RelativeBrightnessCCR7_BV650(Cells).csv"     
#> [4] "C:\\Users\\12692\\AppData\\Local\\Temp\\RtmpyeBMqE/LuciernagaTemporaryExamples/RelativeBrightnessCD107a_APC-R700(Cells).csv"

We can now proceed to evaluate Luciernaga_FCSToReport():

ReferencePath <- system.file("extdata", package = "Luciernaga")
PanelPath <- file.path(ReferencePath, "Panel.csv")
#PanelNames <- read.csv(PanelPath, check.names = FALSE)
#PanelNames <- PanelNames %>% pull(Fluorophore) %>% gsub("-A", "", .)

ReportOutput <- Luciernaga_FCSToReport(path=StorageLocation, reference=PanelPath, stats="median",
                      RetainedType = "normalized", experiment="FirstExperiment",
                      condition="ILTExperiment", TheSummary = TRUE)
gt(head(ReportOutput, 10))
Sample Experiment Condition Cluster Count UV1 UV2 UV3 UV4 UV5 UV6 UV7 UV8 UV9 UV10 UV11 UV12 UV13 UV14 UV15 UV16 V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 YG1 YG2 YG3 YG4 YG5 YG6 YG7 YG8 YG9 YG10 R1 R2 R3 R4 R5 R6 R7 R8
BUV395(Cells) FirstExperiment ILTExperiment UV210 3177 0.253 1.000 0.475 0.347 0.305 0.281 0.138 0.030 0.001 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.0000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.001
BUV395(Cells) FirstExperiment ILTExperiment UV210V702 199 0.251 1.000 0.472 0.362 0.322 0.330 0.218 0.101 0.080 0.024 0.019 0.010 0.007 0.012 0.004 0.013 0.006 0.045 0.042 0.049 0.091 0.081 0.141 0.077 0.068 0.077 0.056 0.035 0.028 0.035 0.036 0.025 0.035 0.056 0.048 0.033 0.035 0.022 0.022 0.009 0.014 0.006 0.010 0.013 0.014 0.014 0.010 0.012 0.007 0.011 0.013 0.005 0.0280 0.004 0.008 0.000 0.003 0.007 0.011 0.008 0.007 0.002 0.004 0.009
BUV496(Cells) FirstExperiment ILTExperiment UV710V602 543 0.009 0.033 0.025 0.023 0.032 0.184 1.000 0.533 0.249 0.061 0.016 0.006 0.005 0.004 0.002 0.001 0.000 0.003 0.014 0.069 0.218 0.163 0.170 0.071 0.035 0.029 0.009 0.003 0.002 0.002 0.001 0.001 0.066 0.042 0.033 0.010 0.005 0.004 0.002 0.001 0.001 0.001 0.000 0.000 0.000 0.000 0.000 0.001 0.000 0.001 0.000 0.000 0.0010 0.000 0.000 0.000 0.000 0.000 0.000 0.001 0.000 0.000 0.000 0.001
BUV496(Cells) FirstExperiment ILTExperiment UV710 283 0.004 0.001 0.000 0.000 0.000 0.071 1.000 0.494 0.138 0.043 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.034 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.001 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.0000 0.007 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.005 0.000 0.017
BUV496(Cells) FirstExperiment ILTExperiment UV710V603 157 0.010 0.047 0.026 0.027 0.034 0.196 1.000 0.562 0.264 0.067 0.022 0.007 0.006 0.008 0.008 0.000 0.001 0.022 0.036 0.100 0.268 0.232 0.217 0.108 0.058 0.055 0.015 0.009 0.016 0.009 0.006 0.001 0.080 0.052 0.051 0.024 0.009 0.019 0.008 0.009 0.009 0.007 0.001 0.002 0.000 0.004 0.005 0.005 0.004 0.009 0.002 0.003 0.0110 0.000 0.000 0.000 0.004 0.004 0.000 0.004 0.006 0.000 0.003 0.001
BUV496(Cells) FirstExperiment ILTExperiment UV710V502 71 0.005 0.027 0.017 0.023 0.010 0.156 1.000 0.537 0.216 0.057 0.010 0.005 0.000 0.000 0.000 0.000 0.004 0.000 0.000 0.031 0.154 0.093 0.069 0.024 0.003 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.036 0.015 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.006 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.0020 0.000 0.000 0.000 0.005 0.005 0.000 0.002 0.000 0.000 0.003 0.003
BUV563(Cells) FirstExperiment ILTExperiment UV910YG105B402 2384 0.007 0.031 0.024 0.020 0.021 0.021 0.016 0.339 1.000 0.253 0.057 0.024 0.013 0.009 0.005 0.002 0.000 0.000 0.000 0.000 0.000 0.000 0.010 0.051 0.019 0.013 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.089 0.186 0.093 0.057 0.016 0.009 0.007 0.002 0.001 0.000 0.000 0.000 0.412 0.194 0.115 0.031 0.017 0.012 0.0080 0.002 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
BUV563(Cells) FirstExperiment ILTExperiment UV910YG104B402 1639 0.009 0.033 0.026 0.023 0.025 0.028 0.029 0.345 1.000 0.252 0.057 0.024 0.013 0.009 0.005 0.002 0.000 0.000 0.000 0.000 0.000 0.000 0.011 0.051 0.019 0.013 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.084 0.177 0.088 0.053 0.013 0.008 0.005 0.001 0.000 0.000 0.000 0.000 0.388 0.185 0.109 0.029 0.015 0.010 0.0060 0.001 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
BUV563(Cells) FirstExperiment ILTExperiment UV910YG105B403 496 0.007 0.030 0.023 0.020 0.021 0.020 0.015 0.340 1.000 0.253 0.056 0.023 0.012 0.009 0.004 0.002 0.000 0.000 0.000 0.000 0.000 0.000 0.012 0.054 0.020 0.014 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.001 0.097 0.206 0.100 0.061 0.017 0.010 0.007 0.002 0.001 0.001 0.000 0.000 0.419 0.197 0.117 0.032 0.017 0.012 0.0085 0.002 0.001 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
BUV615(Cells) FirstExperiment ILTExperiment UV1010YG309V1003 95 0.014 0.039 0.027 0.031 0.031 0.051 0.058 0.040 0.242 1.000 0.408 0.220 0.120 0.112 0.064 0.031 0.008 0.016 0.013 0.011 0.019 0.016 0.022 0.032 0.097 0.260 0.088 0.044 0.025 0.013 0.010 0.000 0.000 0.004 0.007 0.002 0.036 0.066 0.032 0.019 0.021 0.008 0.002 0.000 0.001 0.001 0.079 0.383 0.843 0.385 0.288 0.221 0.1990 0.069 0.048 0.021 0.007 0.006 0.009 0.004 0.004 0.001 0.001 0.001

As you can see, we have returned a Luciernaga_QC() style output that we can now evaluate using Luciernaga_Plots() as described above:

ThePlotReport <- Luciernaga_Plots(data=ReportOutput, RetainedType="normalized", CellPopRatio=0.05,
                                  outfolder=NULL, filename="LuciernagaReport", returntype="plots",
                                  LinePlots=FALSE, CosinePlots=FALSE, StackedBarPlots = FALSE,
                                  HeatmapPlots = TRUE, reference = PanelPath)
#> names not matching, no reorderring according to panel order
ThePlotReport[1]
#> [[1]]
#> [[1]][[1]]

Luciernaga_Brightness

One advantage of retrieving the data from LuciernagaQC() ExportType = “fcs” outputs is that we can generate an additional type of plot to look at the individual brightness for the cells that clustered within the isolated signatures. This is accomplished by switching up a couple arguments in Luciernaga_FCSToReport() and passing the intermediate to the Luciernaga_Brightness() function

ReferencePath <- system.file("extdata", package = "Luciernaga")
PanelPath <- file.path(ReferencePath, "Panel.csv")
PanelNames <- read.csv(PanelPath, check.names = FALSE)

PanelNames <- PanelNames %>% filter(!str_detect(Fluorophore, "Pacific"))
PanelNames <- PanelNames %>% mutate(Fluorophore = case_when(
    Fluorophore == "FITC" ~ "AlexaFluor488",
    TRUE ~ Fluorophore  # Keep all other values unchanged
  ))

PanelItems <- PanelNames %>% pull(Fluorophore) %>% gsub("-A", "", .)


BrightnessOutput <- Luciernaga_FCSToReport(path=StorageLocation, reference=PanelNames, stats="median",
                      RetainedType = "raw", experiment="FirstExperiment", condition="ILTExperiement", 
                      TheSummary = FALSE)

PanelItems <- gsub(".", "", fixed=TRUE, PanelItems)
PanelItems <- gsub(" ", "", fixed=TRUE, PanelItems)
#PanelItems <- gsub("-", "", fixed=TRUE, PanelItems)

BrightnessOutput$Sample <- gsub(".", "", fixed=TRUE, BrightnessOutput$Sample)
BrightnessOutput$Sample <- gsub(" ", "", fixed=TRUE, BrightnessOutput$Sample)
#BrightnessOutput$Sample <- gsub("-", "", fixed=TRUE, BrightnessOutput$Sample)

BrightnessPlots <- map(.x=PanelItems[c(28:29)], .f=Luciernaga_Brightness, data=BrightnessOutput,                       reference=PanelNames, Scaled=TRUE)
ThePlot <- BrightnessPlots[[8]]
ThePlot
plotly::ggplotly(ThePlot)

In the above example, we needed to modify the list to exclude PacificBlue Fluorophore that failed to generate in Luciernaga_QC(). The Panel.CSV also had a mismatch (FITC instead AlexaFluor488) that we had to rename. And in my version the APC-Fire810 bugged. So resolve these to fix this vignette :( and make it easier to work with.

The resulting brightness plot is a geom_density plot showing the MFI for the respective clustered signatures. As you can tell from the ggplot2 object, a bunch of the signatures are relatively dim, which reflects the case seen in signatures.

Luciernaga_Lists

Luciernaga_Lists() is a wrapper function that allows us to merge in the Luciernaga_Brightness() plots with Luciernaga_Plots() plots to generate a more complete view of the fluorescent signatures for given samples. In addition to being able to return a “pdf” plot, it can also be used to generate a “html” output that is interactive (at the cost of being more storage space used on your computer)

FinalPlots <- Luciernaga_Lists(ListOfList = TheMainPlots, SecondaryList = BrightnessPlots, thecolumns = 2, 
                               therows = 3, width=9, height=7, ReturnFolder = ReferencePath,
                               CurrentExperiment = "Test", PlotType = "html")

Visualizing Longitudinally

All of the above functions focused their work primarily in the context of visualizing the variation in Luciernaga_QC() isolated fluorescent signatures within the context of a single experiment. But what happens when we want to look longitudinally across a series of experiments to monitor for tandem degradation in an antibody vial, or pinpoint if the instrumental issue impacted fluorophore signatures on a particular day?

The following functions are still in active development, and require a little more upfront coding on the part of the user to ensure that the data.frame object is tidy compatible, but we attach the workflow below.

Conclusion

And this concludes the vignette covering how to visualize the Luciernaga_QC() outputs to leverage insight into what is occuring within individual fluorophores for a given experiment and across time. Thanks for your patience and happy visualizing.

#> 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_United States.utf8 
#> [2] LC_CTYPE=English_United States.utf8   
#> [3] LC_MONETARY=English_United States.utf8
#> [4] LC_NUMERIC=C                          
#> [5] LC_TIME=English_United States.utf8    
#> 
#> time zone: America/New_York
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#>  [1] htmltools_0.5.8.1    plotly_4.10.4        gt_0.11.1           
#>  [4] stringr_1.5.1        purrr_1.0.2          dplyr_1.1.4         
#>  [7] data.table_1.16.2    ggcyto_1.32.0        ncdfFlow_2.50.0     
#> [10] BH_1.84.0-0          ggplot2_3.5.1        openCyto_2.16.1     
#> [13] flowWorkspace_4.16.0 flowCore_2.16.0      Luciernaga_0.99.1   
#> [16] BiocStyle_2.32.1    
#> 
#> loaded via a namespace (and not attached):
#>  [1] RBGL_1.80.0           gridExtra_2.3         rlang_1.1.4          
#>  [4] magrittr_2.0.3        matrixStats_1.4.1     ggridges_0.5.6       
#>  [7] compiler_4.4.1        dir.expiry_1.12.0     png_0.1-8            
#> [10] systemfonts_1.1.0     vctrs_0.6.5           reshape2_1.4.4       
#> [13] pkgconfig_2.0.3       fastmap_1.2.0         magick_2.8.5         
#> [16] labeling_0.4.3        utf8_1.2.4            rmarkdown_2.28       
#> [19] graph_1.82.0          ragg_1.3.3            xfun_0.48            
#> [22] zlibbioc_1.50.0       cachem_1.1.0          jsonlite_1.8.9       
#> [25] highr_0.11            SnowballC_0.7.1       parallel_4.4.1       
#> [28] R6_2.5.1              bslib_0.8.0           stringi_1.8.4        
#> [31] RColorBrewer_1.1-3    reticulate_1.39.0     lubridate_1.9.3      
#> [34] jquerylib_0.1.4       figpatch_0.2          Rcpp_1.0.13          
#> [37] bookdown_0.41         knitr_1.48            zoo_1.8-12           
#> [40] Matrix_1.7-0          timechange_0.3.0      tidyselect_1.2.1     
#> [43] rstudioapi_0.17.0     yaml_2.3.10           viridis_0.6.5        
#> [46] lattice_0.22-6        tibble_3.2.1          plyr_1.8.9           
#> [49] Biobase_2.64.0        basilisk.utils_1.16.0 withr_3.0.1          
#> [52] evaluate_1.0.1        Rtsne_0.17            desc_1.4.3           
#> [55] xml2_1.3.6            pillar_1.9.0          lsa_0.73.3           
#> [58] BiocManager_1.30.25   filelock_1.0.3        stats4_4.4.1         
#> [61] generics_0.1.3        S4Vectors_0.42.1      munsell_0.5.1        
#> [64] scales_1.3.0          glue_1.8.0            lazyeval_0.2.2       
#> [67] tools_4.4.1           hexbin_1.28.4         fs_1.6.4             
#> [70] XML_3.99-0.17         grid_4.4.1            flowClust_3.42.0     
#> [73] tidyr_1.3.1           RProtoBufLib_2.16.0   crosstalk_1.2.1      
#> [76] colorspace_2.1-1      patchwork_1.3.0       basilisk_1.16.0      
#> [79] cli_3.6.3             textshaping_0.4.0     fansi_1.0.6          
#> [82] cytolib_2.16.0        viridisLite_0.4.2     uwot_0.2.2           
#> [85] Rgraphviz_2.48.0      gtable_0.3.5          sass_0.4.9           
#> [88] digest_0.6.37         BiocGenerics_0.50.0   htmlwidgets_1.6.4    
#> [91] farver_2.1.2          pkgdown_2.1.1         lifecycle_1.0.4      
#> [94] httr_1.4.7