Skip to content

Commit 171acab

Browse files
Merge pull request #29 from lorenzobonaguro/dev
Version 0.3.0
2 parents d7ef100 + a5076f6 commit 171acab

225 files changed

Lines changed: 19189 additions & 7938 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.Rhistory

Lines changed: 0 additions & 512 deletions
This file was deleted.

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
condor.Rproj
1+
cyCONDOR.Rproj
22
.Rproj.user/
3-
inst/doc
43
.test_files
54
.Rhistory

DESCRIPTION

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
Package: cyCONDOR
22
Type: Package
33
Title: Flow Cytometry data analysis toolbox
4-
Version: 0.2.1
4+
Version: 0.3.0
55
Authors@R: c(
66
person(given = "Lorenzo", family = "Bonaguro", email = "lorenzo.bonaguro@dzne.de", role = c("aut", "cre")),
77
person(given = "Charlotte", family = "Kroeger", email = "charlotte.kroeger@dzne.de", role = "aut"),
88
person(given = "Sophie", family = "Mueller", email = "sophie.mueller@dzne.de", role = "aut"),
9-
person(given = "Jacqueline", family = "Leidner", email = "jacqueline.leidner@dzne.de", role = "aut")
9+
person(given = "Jacqueline", family = "Leidner", email = "jacqueline.leidner@dzne.de", role = "aut"),
10+
person(given = "Aleksej", family = "Frolov", email = "aleksej.frolov@dzne.de", role = "aut"),
11+
person(given = "Francesco", family = "Elli", email = "francesco.elli@dzne.de", role = "aut"),
12+
person(given = "Nico", family = "Henschel", email = "nico.henschel@dzne.de", role = "aut")
1013
)
11-
Description: Flow cytometry analysis workflow. The aim of this project if to
14+
Description: Flow cytometry analysis workflow. The aim of this project is to
1215
provide an intuitive workflow for the analysis of high-dimensionality cytometry data in R.
13-
URL: https://github.com/lorenzobonaguro/condor
16+
URL: https://lorenzobonaguro.github.io/cyCONDOR
1417
License: GPL-3 + file LICENSE
1518
Encoding: UTF-8
16-
LazyData: FALSE
1719
biocViews:
1820
Imports:
1921
ggplot2,
@@ -58,9 +60,17 @@ Imports:
5860
ggridges,
5961
rstatix,
6062
tidyr,
61-
CytoNorm
62-
RoxygenNote: 7.2.3
63+
CytoNorm,
64+
corrplot
65+
Remotes:
66+
JinmiaoChenLab/Rphenograph,
67+
stuchly/Rphenoannoy,
68+
saeyslab/CytoNorm@362ac08
69+
RoxygenNote: 7.3.2
6370
VignetteBuilder: knitr
6471
Suggests:
6572
rmarkdown,
66-
knitr
73+
knitr,
74+
testthat (>= 3.0.0),
75+
here
76+
Config/testthat/edition: 3

NAMESPACE

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
# Generated by roxygen2: do not edit by hand
22

33
export(PC_loadings)
4+
export(add_diffcyt_statistics)
45
export(change_param_name)
56
export(checkInput)
67
export(check_IDs)
78
export(clr)
9+
export(condor_session_info)
810
export(confusionMatrix)
11+
export(corr_plot_comparison)
912
export(create_metaclustering_script)
1013
export(df_frequency)
1114
export(filter_fcd)
@@ -53,13 +56,15 @@ export(runUMAP)
5356
export(run_cytonorm)
5457
export(runtSNE)
5558
export(scaleColors)
59+
export(subsample_geosketch)
5660
export(subset_fcd)
5761
export(subset_fcd_byparam)
5862
export(train_classifier_model)
5963
export(train_cytonorm)
6064
export(train_transfer_model)
6165
export(transform_data)
6266
export(used_markers)
67+
export(write_fcs)
6368
import(Biobase)
6469
import(CytoDx)
6570
import(CytoML)
@@ -74,6 +79,7 @@ import(Rtsne)
7479
import(SingleCellExperiment)
7580
import(SummarizedExperiment)
7681
import(caret)
82+
import(corrplot)
7783
import(cowplot)
7884
import(destiny)
7985
import(devtools)
@@ -101,7 +107,10 @@ import(stringr)
101107
import(tidyr)
102108
import(umap)
103109
import(uwot)
110+
importFrom(Biobase,AnnotatedDataFrame)
104111
importFrom(Matrix,sparseMatrix)
112+
importFrom(grDevices,recordPlot)
105113
importFrom(igraph,membership)
106114
importFrom(utils,packageDescription)
115+
importFrom(utils,sessionInfo)
107116
importFrom(utils,write.csv)

NEWS.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# cyCONDOR 0.3.0
2+
* Bug fix with data projection where specific parameters were removed in UMAP calculation
3+
* Updated official Docker image to the latest Bioconductor version (Bioconductor 3.20, R 4.4.2)
4+
* Completed documentation of the `Astir` workflow.
5+
* Added parameter to select number of PCs and markers for UMAP projection in `learnUMAP` function.
6+
* Added documentation and guide to install cyCONDOR in Silicon Mac. We now how a compiled version of the Rphenoannoy package.
7+
* Simplified installation process, now automatically installing also the GitHub dependencies.
8+
* Enable Geometric Sketching to subset a `condor` object with the function `geometric_sketching`
9+
* Developed a function (`condor_session_info`) to include the `SessionInfo` to the `condor` object to increase tackability of the analysis.
10+
* Included storage of the statistical test results in the `condor` object
11+
* Added the option to display statistics to the `plot_frequency_boxplot` function - so far for `wilcox`, `t_test` and `diffcyt`
12+
* Added function to correlate the cyCONDOR results and the manual gating with FlowJo or similar software (`corr_plot_comparison`)
13+
* **Experimental**: Added a function to write FCS files from a `condor` object (`write_fcs`). Currently the function if writing in the .fcs file the cyCONDOR transformed values, we will change to the original values in the next iteration after more extensive testing.
14+
115
# cyCONDOR 0.2.1
216
* Included help function to assign metaclusters (Thanks to Lucas Secchim Ribeiro)
317
* Removal of redundant `color_palette` parameter and other redundant lines in the source code

R/corr_plot_comparison.R

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# This function is designed to calculate a sample-wise correlation of cell population percentages that are found in CyCondor and FlowJo.
2+
3+
4+
#' corr_plot_comparison
5+
#' @title Sample-wise correlation of cell type proportions to compare manual gating and cyCONDOR.
6+
#' @description 'corr_plot_comparison' performs a sample-wise correlation of cell type proportions obtained via manual gating and via clustering on cyCONDOR. The result is shown in a correlogram.
7+
#' @param condor_df data frame containing the cell type frequencies obtained via clustering and annotation in cyCONDOR.
8+
#' @param flowjo_df data frame containing the cell type frequencies obtained via manual gating and annotation (e.g. FlowJo).
9+
#' @param sample_col name of the column containing sample names. This column name needs to be matching between the two data frames.
10+
#' @param method_corr correlation method used in the correlogram (default = "pearson").
11+
#' @param tl.cex Numeric, for the size of text label (variable names).
12+
#' @param cl.cex Numeric, text size of number-label in color-legend
13+
#' @import corrplot
14+
#' @importFrom grDevices recordPlot
15+
#'
16+
#' @export
17+
18+
19+
20+
corr_plot_comparison <- function(condor_df,
21+
flowjo_df,
22+
sample_col,
23+
method_corr = "pearson",
24+
tl.cex = 1,
25+
cl.cex = 1){
26+
27+
28+
# Merge the two dataframes by Sample/DONOR ID
29+
merged_data <- merge(condor_df, flowjo_df, by = sample_col)
30+
31+
flowjo_cols <- colnames(merged_data)[grepl("FlowJo",colnames(merged_data))]
32+
condor_cols <- colnames(merged_data)[grepl("Condor",colnames(merged_data))]
33+
34+
35+
condor_clean <- setNames(condor_cols, sub("^[^_]+_", "", condor_cols))
36+
flowjo_clean <- setNames(flowjo_cols, sub("^[^_]+_", "", flowjo_cols))
37+
38+
39+
matching_cell_types <- intersect(names(condor_clean), names(flowjo_clean))
40+
41+
total_cell_types_count <- length(condor_clean)
42+
matching_cell_types_count <- length(matching_cell_types)
43+
44+
45+
46+
# Check if there are cell types not matching
47+
diff_count <- total_cell_types_count - matching_cell_types_count
48+
49+
if (diff_count != 0) {
50+
51+
missing_cell_types <- setdiff(names(condor_clean), matching_cell_types)
52+
53+
warning(paste("There are ", diff_count, " cell types that are not matching between Condor and FlowJo.\n",
54+
"Missing cell types: ", paste(missing_cell_types,collapse = ", ")))
55+
56+
if(diff_count == total_cell_types_count){
57+
58+
stop("No matching cell types found. Ensure column names are formatted correctly and match between Condor and FlowJo.")
59+
}
60+
}
61+
62+
63+
# Subset the two data frames only for the matching cell types
64+
selected_condor <- condor_clean[matching_cell_types]
65+
selected_flowjo <- flowjo_clean[matching_cell_types]
66+
67+
# Create a dataframe with only the selected columns
68+
cor_data <- merged_data[, c(selected_condor, selected_flowjo)]
69+
70+
71+
M <- cor(cor_data,use = "pairwise.complete.obs",method = method_corr)
72+
73+
corr_M <- M[selected_condor,selected_flowjo]
74+
75+
plot <- corrplot::corrplot(corr_M,method = "circle",type = "lower", tl.cex = 1, cl.cex = 1)
76+
77+
return(plot)
78+
}

R/data_load_and_transform.R

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,3 +522,125 @@ prep_fjw <- function(data_gs,
522522

523523
}
524524

525+
526+
#' Save the results from cyCONDOR as FCS file(s)
527+
#'
528+
#' @title Save the results from cyCONDOR as FCS file(s)
529+
#' @description Saves the expression data, annotation data and (optionally) results from the cyCONDOR analysis (dimensionality reduction, clustering) as one or more FCS file(s).
530+
#' @param fcd flow cytometry data set
531+
#' @param expr_slot expr_slot from which to take marker expression values, default is "orig".
532+
#' @param reduction_method string specifying which dimensionality reduction method to use.
533+
#' @param reduction_slot string specifying reduction name in reduction_method to use for visualization, e.g. "pca_orig".
534+
#' @param cluster_slot string specifying which clustering slot to use to find variable specified in cluster_var.
535+
#' @param cluster_var string specifying variable name in cluster_slot that identifies cell population labels to be used (e.g. clusters, metaclusters or predicted labels). Must be numeric in this function - factors are converted automatically.
536+
#' @param split_by NULL or character string specifying a metadata variable (e.g. sample_ID) to split the data. If NULL, only one FCS file with all data is generated.
537+
#' @param dir string specifying the directory where the FCS file(s) is/are saved. Current working directory by default.
538+
#' @param filename string specifying the filename for the FCS file. If split_by is defined, an automatic suffix according to the defined variable is assigned to the FCS files.
539+
#' @importFrom Biobase AnnotatedDataFrame
540+
#' @import flowCore
541+
#' @return Message that FCS file(s) are saved in the defined directory.
542+
#'
543+
#' @export
544+
write_fcs <- function(fcd = condor,
545+
expr_slot = "orig",
546+
reduction_method = NULL,
547+
reduction_slot = NULL,
548+
cluster_slot = NULL,
549+
cluster_var = NULL,
550+
split_by = NULL,
551+
dir = paste0(getwd(), "/"),
552+
filename){
553+
554+
# Print a working to let people know this is an experimental functio
555+
warning("This function is still experimental. Feel free to test if and report your experience, this function
556+
is currently writing cyCONDOR transformed value, future revision will export original values.")
557+
558+
# Get the expression data
559+
xdata <- fcd[["expr"]][[expr_slot]]
560+
exp <- xdata
561+
562+
# Add dimensionl reduction information
563+
if(!is.null(reduction_method)){
564+
rdata <- fcd[[reduction_method]][[reduction_slot]]
565+
exp <- cbind(exp, rdata)
566+
}
567+
568+
# Add cluster labels (must be numeric!)
569+
if(!is.null(cluster_slot)){
570+
cluster <- fcd[["clustering"]][[cluster_slot]][[cluster_var]]
571+
exp <- cbind(exp, cluster)
572+
}
573+
574+
# Ensure all columns in exp are numeric
575+
exp[] <- lapply(exp, function(x){
576+
if (is.numeric(x)) return(x)
577+
xnum <- as.numeric(as.character(x))
578+
if (any(is.na(xnum) & !is.na(x)))
579+
warning("Some values in column could not be converted to numeric.")
580+
return(xnum)
581+
})
582+
583+
# Hanlde splitting
584+
if(!is.null(split_by)){
585+
anno <- fcd[["anno"]][["cell_anno"]]
586+
587+
if(!split_by %in% colnames(anno)){
588+
stop("Column '", split_by, "' not found in the annotation data.")
589+
}
590+
591+
split_vec <- anno[[split_by]]
592+
exp_mat <- as.matrix(exp)
593+
split_list <- split(seq_len(nrow(exp)), split_vec)
594+
595+
# create a flowSet with flowFrames for each subset
596+
ffs <- lapply(names(split_list), function(group){
597+
idx <- split_list[[group]]
598+
exp_sub <- exp_mat[idx, , drop = FALSE]
599+
600+
# Create AnnotatedDataFrame for parameters of each subset
601+
param_sub <- Biobase::AnnotatedDataFrame(data.frame(
602+
name = colnames(exp_sub),
603+
desc = paste("Channel", colnames(exp_sub), sep = "_"),
604+
range = apply(exp_sub, 2, function(x) ceiling(max(x))),
605+
minRange = apply(exp_sub, 2, min),
606+
maxRange = apply(exp_sub, 2, max)
607+
))
608+
609+
# flowFrames
610+
flowCore::flowFrame(exprs = exp_sub, parameters = param_sub)
611+
})
612+
613+
names(ffs) <- names(split_list)
614+
615+
# flowSet
616+
fs <- flowCore::flowSet(ffs)
617+
618+
# Write each frame into its own fcs file
619+
for(sample_name in flowCore::sampleNames(fs)){
620+
out_file <- paste0(dir, filename, "_", make.names(sample_name), ".fcs")
621+
flowCore::write.FCS(fs[[sample_name]], file = out_file)
622+
message("File was saved to ", out_file)
623+
}
624+
}
625+
626+
# No splitting, yields a single fcs file
627+
else{
628+
629+
# Create AnnotatedDataFrame for parameters
630+
param <- Biobase::AnnotatedDataFrame(data.frame(
631+
name = colnames(exp),
632+
desc = paste("Channel", colnames(exp), sep = "_"),
633+
range = apply(exp, 2, function(x) ceiling(max(x))),
634+
minRange = apply(exp, 2, min),
635+
maxRange = apply(exp, 2, max)
636+
))
637+
638+
# Create flowFrame file
639+
ffs <- flowCore::flowFrame(exprs = as.matrix(exp),
640+
parameters = param)
641+
642+
# Write the fcs
643+
flowCore::write.FCS(ffs, file = paste0(dir, filename, ".fcs"))
644+
message("File was saved to ", dir, filename, ".fcs")
645+
}
646+
}

0 commit comments

Comments
 (0)