## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.height = 6, fig.width = 8, fig.align = "center" ) ## ----setup-------------------------------------------------------------------- # Load libraries library(staRgate) library(openCyto) library(flowWorkspace) library(flowCore) # Just for plotting in the vignette library(ggplot2) library(ggcyto) # Set up dynamic variables pt_samp_nm <- "flow_sample_1" ## File path to the FCS file path_fcs <- system.file("extdata", "example_fcs.fcs", package = "staRgate", mustWork = TRUE) ## File path to the compensation matrix csv file ## Expect format to match flowJo exported version path_comp_mat <- system.file("extdata", "comp_mat_example_fcs.csv", package = "staRgate", mustWork = TRUE) ## File path for outputs/saving # Maybe not the best sol, but create a temp dir? path_out <- tempdir() # Print the path_out for user to see path_out ## File path Gating template gtFile <- system.file("extdata", "gating_template_x50_tcell.csv", package = "staRgate", mustWork = TRUE) ## File path to biexp parameters ## Expects 4 columns: full_name, ext_neg_dec, width_basis, positive_dec ## full name should contain the channel/dye name # 3 remaining cols fill in with desired parameter values path_biexp_params <- system.file("extdata", "biexp_transf_parameters_x50.csv", package = "staRgate", mustWork = TRUE) ## File path to positive peak thresholds path_pos_peak_thresholds <- system.file("extdata", "pos_peak_thresholds.csv", package = "staRgate", mustWork = TRUE) ## ----echo = FALSE------------------------------------------------------------- # Some preferred ggplot settings. # Not required/relevant for gating plot_font_size <- 11 ggplot2::theme_set(ggplot2::theme_bw() + ggplot2::theme( text = ggplot2::element_text(size = plot_font_size), axis.text = ggplot2::element_text(color = "black"), legend.position = "bottom" )) ## ----------------------------------------------------------------------------- # Read in gating template dtTemplate <- data.table::fread(gtFile) # Load the FCS gt_tcell <- openCyto::gatingTemplate(gtFile) cs <- flowWorkspace::load_cytoset_from_fcs(path_fcs) # Create a GatingSet of 1 sample gs <- flowWorkspace::GatingSet(cs) # Check- how many cells is in the FCS file? n_root <- flowWorkspace::gh_pop_get_count(gs, "root") # The example FCS has 30000 cells n_root ## ----------------------------------------------------------------------------- # Apply comp gs <- getCompGS(gs, path_comp_mat = path_comp_mat) # Can check that the comp was applied chk_cm <- flowWorkspace::gh_get_compensations(gs) # Not aware of an accessor that we can use for this head(methods::slot(chk_cm, "spillover"), 2) ## ----------------------------------------------------------------------------- tbl_biexp_params <- utils::read.csv(path_biexp_params) |> janitor::clean_names(case="all_caps") head(tbl_biexp_params, 2) ## ----------------------------------------------------------------------------- # Save the pre-transformed data to compare ranges # And check that transformation was applied dat_pre_transform <- flowWorkspace::gh_pop_get_data(gs) |> flowCore::exprs() # Apply biexp trans gs <- getBiexpTransformGS(gs, path_biexp_params = path_biexp_params) ## **Optional**-- to check what pre-transformed data against post # save the post-transformed data dat_post_transform <- flowWorkspace::gh_pop_get_data(gs) |> flowCore::exprs() ## **Optional**-- to check that the transformation worked on all provided channels! ## Commented out for ease of length # summary(dat_pre_transform) # summary(dat_post_transform) ## ----------------------------------------------------------------------------- # Pre-gating up to CD4/8+ with `r BiocStyle::Biocpkg("openCyto")` ## Set seed using today's date set.seed(glue::glue({ format(Sys.Date(), format = "%Y%m%d") })) openCyto::gt_gating(gt_tcell, gs) ## ----fig.height = 10, fig.width = 8, warning = FALSE, message = FALSE--------- ## Check autoplot ggcyto::autoplot(gs[[1]]) ## ----------------------------------------------------------------------------- ## Grab marker names from GatingSet for labeling col names in intensity matrix ## Can skip this step if you know the names of the channels that correspond to your marker names in your FCS files # In that case, supply strings for `chnl` and `marker_full` is fine. Such as: # chnl = c("BV750-A", "BUV496-A") # marker_full = c("CD3", "CD4) # This returns a named character vector # With the channel names as names and marker names as the values marker_chnl_names <- flowWorkspace::markernames(flowWorkspace::gh_pop_get_data(gs)) ## Specify which markers to gate based on individual density distributions # For our Tcell panel, we only want to apply the density gating on # these 23 markers markers_to_gate = c("CD45RA", "ICOS", "CD25", "TIM3", "CD27", "CD57", "CXCR5", "CCR4", "CCR7", "HLADR", "CD28", "PD1", "LAG3", "CD127", "CD38", "TIGIT", "EOMES", "CTLA4", "FOX_P3", "GITR", "TBET", "KI67", "GZM_B") ## ----------------------------------------------------------------------------- # Extract intensity matrix from GatingSet object ## Grab the intensity matrix from GatingSet intensity_dat <- cbind( # This grabs the intensity matrix with intensity values flowWorkspace::gh_pop_get_data(gs) |> flowCore::exprs(), # the gh_pop_get_indices grabs the 0/1 for whether gated as pos/neg # for each step specified "fsc_ssc_qc" = flowWorkspace::gh_pop_get_indices(gs, y = "fsc_ssc_qc"), "nonDebris" = flowWorkspace::gh_pop_get_indices(gs, y = "nonDebris"), "singlets" = flowWorkspace::gh_pop_get_indices(gs, y = "singlets"), "cd14_neg_19_neg" = flowWorkspace::gh_pop_get_indices(gs, y = "cd14-cd19-"), "live" = flowWorkspace::gh_pop_get_indices(gs, y = "live"), "cd3_pos" = flowWorkspace::gh_pop_get_indices(gs, y = "cd3"), "cd4_pos" = flowWorkspace::gh_pop_get_indices(gs, y = "cd4+"), "cd8_pos" = flowWorkspace::gh_pop_get_indices(gs, y = "cd8+") ) |> # The intensity matrix is a matrix object. Convert to tibble. tibble::as_tibble() |> # Rename with colnames which are the channel names # to marker names because it's easier to call columns by markers # Rename using the marker_chnl_names we created above # But we need it flipped when supplying to dplyr::rename() # Where the names = value to rename to (marker names) # The values of the vector = current names (Channel names) dplyr::rename( stats::setNames(names(marker_chnl_names), # Clean up the marker names, make them all caps janitor::make_clean_names(marker_chnl_names, case = "all_caps", replace = c("-" = "", "_" = "", " " = ""))) ) |> dplyr::mutate( # Create a 4-level category for cd4, cd8 neg/pos # in order to calculate the percentages individually within these parent populations cd4_pos_cd8_pos = dplyr::case_when( cd3_pos == 1 & cd4_pos == 1 & cd8_pos == 1 ~ "cd4_pos_cd8_pos", cd3_pos == 1 & cd4_pos == 1 & cd8_pos == 0 ~ "cd4_pos_cd8_neg", cd3_pos == 1 & cd4_pos == 0 & cd8_pos == 1 ~ "cd4_neg_cd8_pos", cd3_pos == 1 & cd4_pos == 0 & cd8_pos == 0 ~ "cd4_neg_cd8_neg" ) ) ## Preview of intensity matrix head(intensity_dat, 2) ## ----------------------------------------------------------------------------- gates_pseudo_neg = dplyr::filter(intensity_dat, live == 1, cd3_pos == 0) |> dplyr::select(CD127, CD28) |> dplyr::summarise( dplyr::across(c(CD127, CD28), ~ quantile(.x, 0.95)) ) ## ----------------------------------------------------------------------------- # Density gating parameters # peak detection ratio where any peak < 1/10 of the tallest peak will be # considered as noise peak_r <- 10 # smoothing to apply to the density estimation # Using the default of 512 creates many little bumps/noise that are artifacts # From a systematic grid search, we found the bin sizes of ~40-50 works best bin_i <- 40 # Remove any very negative values that are artifacts from autogating # -1000 on the biexp transformed scale corresponds to roughly -3300 on the original # intensity scale so this is quite conservative. neg_intensity_thres <- -1000 # select a few markers to gate example_markers <- c("LAG3", "CCR7", "CD45RA") # Read in positive peak thresholds pos_thres <- utils::read.csv(path_pos_peak_thresholds) |> janitor::clean_names(case = "all_caps") ## ----------------------------------------------------------------------------- # calculate the gates dens_gates_pre <- dplyr::filter(intensity_dat, cd3_pos == 1) |> getDensityGates( intens_dat = _, marker = example_markers, subset_col = "cd3_pos", bin_n = bin_i, peak_detect_ratio = peak_r, pos_peak_threshold = pos_thres, neg_intensity_threshold = neg_intensity_thres ) # Since we apply density gating on CD3+ cells but # Would like to calculate subpopulations with CD4+ and CD8+ as # the starting parent population, we need to add corresponding rows # to pass into getGatedDat() dens_gates <- # Stack the pseudo-neg gated markers and empirically gated markers dplyr::bind_cols(dens_gates_pre, gates_pseudo_neg) |> tibble::add_row() |> tibble::add_row() |> tibble::add_row() |> dplyr::mutate(cd4_pos_cd8_pos = c("cd4_neg_cd8_neg", "cd4_pos_cd8_neg", "cd4_neg_cd8_pos", "cd4_pos_cd8_pos")) |> tidyr::fill(-cd4_pos_cd8_pos, .direction = "down") # View updated gates with the col for CD4/CD8 dens_gates # get indicator col example_intensity_gated <- getGatedDat( # Only gate T-cells, which are CD3+ dplyr::filter(intensity_dat, cd3_pos == 1), subset_col = "cd4_pos_cd8_pos", cutoffs = dens_gates ) ## ----fig.width=8, fig.height=6------------------------------------------------ # Plot the gate for visual intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(LAG3)) + geom_vline( data = dens_gates, aes(xintercept = LAG3), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of LAG3 intensity on all CD3+. Gate identifed by {staRgate} in blue.") ## ----fig.width=8, fig.height=6------------------------------------------------ # If by CD4/CD8, intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(LAG3)) + geom_vline( data = dens_gates, aes(xintercept = LAG3), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of LAG3 intensity by CD4/CD8 subsets. Gate identifed by {staRgate} in blue.") + facet_wrap(~cd4_pos_cd8_pos) ## ----fig.width=8, fig.height=6------------------------------------------------ # For CCR7 intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(CCR7)) + geom_vline( data = dens_gates, aes(xintercept = CCR7), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of CCR7 intensity on all CD3+. Gate identifed by {staRgate} in blue.") ## ----fig.width=8, fig.height=6------------------------------------------------ # If by CD4/CD8, intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(CCR7)) + geom_vline( data = dens_gates, aes(xintercept = CCR7), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of CCR7 intensity for CD4/CD8 subsets. Gate identifed by {staRgate} in blue.") + facet_wrap(~cd4_pos_cd8_pos) ## ----fig.width=8, fig.height=6------------------------------------------------ # For CD45RA intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(CD45RA)) + geom_vline( data = dens_gates, aes(xintercept = CD45RA), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of CD45RA intensity on all CD3+. Gate identifed by {staRgate} in blue.") ## ----fig.width=8, fig.height=6------------------------------------------------ # If by CD4/CD8, intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(CD45RA)) + geom_vline( data = dens_gates, aes(xintercept = CD45RA), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of CD45RA intensity for CD4/CD8 subsets. Gate identifed by {staRgate} in blue.") + facet_wrap(~cd4_pos_cd8_pos) ## ----fig.width=8, fig.height=6------------------------------------------------ # For CD127 intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(CD127)) + geom_vline( data = dens_gates, aes(xintercept = CD127), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of CD127 intensity on all CD3+. Gate identifed by {staRgate} in blue.") ## ----fig.width=8, fig.height=6------------------------------------------------ # If by CD4/CD8, intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(CD127)) + geom_vline( data = dens_gates, aes(xintercept = CD127), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of CD127 intensity for CD4/CD8 subsets. Gate identifed by {staRgate} in blue.") + facet_wrap(~cd4_pos_cd8_pos) ## ----fig.width=8, fig.height=6------------------------------------------------ # For CD28 intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(CD28)) + geom_vline( data = dens_gates, aes(xintercept = CD28), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of CD28 intensity on all CD3+. Gate identifed by {staRgate} in blue.") ## ----fig.width=8, fig.height=6------------------------------------------------ # If by CD4/CD8, intensity_dat |> dplyr::filter(cd3_pos == 1) |> # additional step to remove large intensity values only when density gating. # Still kept in the data dplyr::filter(!(dplyr::if_any(dplyr::all_of(markers_to_gate), ~ .x < neg_intensity_thres))) |> ggplot() + geom_density(aes(CD28)) + geom_vline( data = dens_gates, aes(xintercept = CD28), color = "blue", linetype = "dashed" ) + labs(subtitle = "Distribution of CD28 intensity for CD4/CD8 subsets. Gate identifed by {staRgate} in blue.") + facet_wrap(~cd4_pos_cd8_pos) ## ----echo = FALSE------------------------------------------------------------- panel_n <- 23 panel_n_d <- 2 ## ----echo = FALSE, warning = FALSE-------------------------------------------- # Follows supp table 1 in the paper tibble::tibble( expand_num = c("FALSE", "TRUE", "FALSE", "TRUE"), expand_denom = c("FALSE", "FALSE", "TRUE", "TRUE"), gen = c( # For expand_num, expand_denom combos # FALSE, FALSE "- Numerator: Positive and negative for each marker specified - Denominator: Combinations of positive and negative for markers specified", # TRUE, FALSE "- Numerator: Positive and negative for each marker specified, and combinations of positive/negative for pairs of markers - At least 2 markers must be included in the numerator - Denominator: Combinations of positive and negative for marker(s)", # FALSE, TRUE "- Numerator: Positive and negative for each marker specified - At least 2 markers must be included in the numerator - Denominator: Combinations of positive and negative for marker(s), and combinations of positive and negative for marker(s) in denominator with one marker from the numerator", # TRUE, TRUE "- Numerator: Positive and negative for each marker specified, and combinations of positive/negative for pairs of markers - At least 3 markers must be included in the numerator - Denominator: Combinations of positive and negative for marker(s), and combinations of positive and negative for marker(s) in denominator with one marker from the numerator" ), examples = c( "Numerator specified to (“LAG3”) and denominator specified as (“CD4”, “CD8”): - LAG3+/- of CD4- & CD8- - LAG3+/- of CD4+ & CD8- - LAG3+/- of CD4+ & CD8+ - LAG3+/- of CD4- & CD8+ ", "Numerator specified as (“LAG3”, “KI67”) and denominator as (“CD4”): - LAG3+/- of CD4+/- - KI67+/- of CD4+/- - LAG3- KI67- of CD4+/- - LAG3+ KI67- of CD4+/- - LAG3- KI67+ of CD4+/- - LAG3+ KI67+ of CD4+/- ", "Numerator specified as (“LAG3”, “KI67”) and denominator as (“CD4”) - LAG3+/- of CD4+/- - KI67+/- of CD4+/- - LAG3+/- of CD4-KI67- - LAG3+/- of CD4-KI67+ - LAG3+/- of CD4+KI67- - LAG3+/- of CD4+KI67+ - KI67+/- of CD4-LAG3- - KI67+/- of CD4-LAG3+ - KI67+/- of CD4+LAG3- - KI67+/- of CD4+LAG3+", "Numerator specified as (“LAG3”, “KI67”, “CTLA4”) and denominator as (“CD4”) - LAG3+/- of CD4+/- - KI67+/- of CD4+/- - CTLA4+/- of CD4+/- - LAG3+/- of CD4-KI67- - LAG3+/- of CD4-KI67+ - LAG3+/- of CD4+KI67- - LAG3+/- of CD4+KI67+ - KI67+/- of CD4-LAG3- - KI67+/- of CD4-LAG3+ - KI67+/- of CD4+LAG3- - KI67+/- of CD4+LAG3+ - …. - LAG3- KI67- of CD4+/- - LAG3+ KI67- of CD4+/- - LAG3- KI67+ of CD4+/- - LAG3+ KI67+ of CD4+/- - … - LAG3+ KI67+ of CD4+/- & CTLA4+/- - …" ), n_subpops = c( "2n\\*(2nd)", "2n\\*(2nd) +
2nd\\*(n choose 2)\\*(22)", "2n\\*(2nd) +
4\\*2nd\\*n\\*(n-1)", "2n\\*(2nd) +
2nd\\*(n choose 2)\\*(22) +
4\\*2nd\\*n\\*(n-1) +
22\\*n\\*((n-1) choose 2)\\*(2nd+1)" ), combos = c( 2 * panel_n * 2^(panel_n_d), # 184, 2 * panel_n * 2^(panel_n_d) + 2^(panel_n_d) * (choose(panel_n, 2)) * 2^2, # 4232, 2 * panel_n * 2^(panel_n_d) + 4 * 2^(panel_n_d) * panel_n * (panel_n - 1), # 8280, 2 * panel_n * 2^(panel_n_d) + 2^(panel_n_d) * (choose(panel_n, 2)) * 2^2 + 4 * 2^(panel_n_d) * panel_n * (panel_n - 1) + 2^2 * (panel_n) * (choose(panel_n - 1, 2)) * (2^(panel_n_d + 1)) # 182344) ) ) |> gt::gt() |> gt::fmt_markdown( columns = dplyr::everything() ) |> gt::cols_label( expand_num = "expand_num", expand_denom = "expand_denom", gen = "The subpopulations to generate", examples = "Examples", n_subpops = "Expected number of subpopulations", combos = "Expected number of subpopulations
for the 29-marker T-cell panel", .fn = gt::md ) |> gt::cols_align( align = "center", columns = c("n_subpops", "combos") ) |> gt::tab_footnote( footnote = gt::md("n, number of markers specified in the numerator; nd, number of markers specified in the denominator"), locations = gt::cells_column_labels(columns = "n_subpops") ) ## ----------------------------------------------------------------------------- example_perc1 <- # Should only count the CD3+ cells dplyr::filter(example_intensity_gated, cd3_pos == 1) |> getPerc( intens_dat = _, num_marker = example_markers, denom_marker = c("CD4", "CD8"), expand_num = FALSE, expand_denom = FALSE, keep_indicators = TRUE ) # For display only, group based on the denominators and # simplify the names to be numerators example_perc1 |> tidyr::separate_wider_delim(subpopulation, delim = "_OF_", names = c("num", "denom"), cols_remove = FALSE ) |> dplyr::mutate(denom = paste("Denom = ", denom)) |> dplyr::group_by(denom) |> dplyr::select(-subpopulation) |> gt::gt() |> gt::fmt_number( columns = "perc", decimals = 1 ) ## ----------------------------------------------------------------------------- example_perc2 <- # Should only count the CD3+ cells dplyr::filter(example_intensity_gated, cd3_pos == 1) |> getPerc( intens_dat = _, num_marker = example_markers, denom_marker = c("CD4", "CD8"), expand_num = TRUE, expand_denom = FALSE, keep_indicators = FALSE ) # For display only, group based on the denominators and # simplify the names to be numerators example_perc2 |> tidyr::separate_wider_delim(subpopulation, delim = "_OF_", names = c("num", "denom"), cols_remove = FALSE ) |> dplyr::mutate(denom = paste("Denom = ", denom)) |> dplyr::group_by(denom) |> dplyr::select(-subpopulation) |> gt::gt() |> gt::fmt_number( columns = "perc", decimals = 1 ) ## ----------------------------------------------------------------------------- example_perc3 <- # Should only count the CD3+ cells dplyr::filter(example_intensity_gated, cd3_pos == 1) |> getPerc( intens_dat = _, num_marker = example_markers, denom_marker = c("CD4", "CD8"), expand_num = FALSE, expand_denom = TRUE, keep_indicators = FALSE ) # For display only, group based on the denominators and # simplify the names to be numerators example_perc3 |> tidyr::separate_wider_delim(subpopulation, delim = "_OF_", names = c("num", "denom"), cols_remove = FALSE ) |> dplyr::mutate(denom = paste("Denom = ", denom)) |> dplyr::group_by(denom) |> dplyr::select(-subpopulation) |> gt::gt() |> gt::fmt_number( columns = "perc", decimals = 1 ) ## ----------------------------------------------------------------------------- example_perc4 <- # Should only count the CD3+ cells dplyr::filter(example_intensity_gated, cd3_pos == 1) |> getPerc( intens_dat = _, num_marker = example_markers, denom_marker = c("CD4", "CD8"), expand_num = TRUE, expand_denom = TRUE, keep_indicators = FALSE ) # For display only, group based on the denominators and # simplify the names to be numerators example_perc4 |> tidyr::separate_wider_delim(subpopulation, delim = "_OF_", names = c("num", "denom"), cols_remove = FALSE ) |> dplyr::mutate(denom = paste("Denom = ", denom)) |> dplyr::group_by(denom) |> dplyr::select(-subpopulation) |> gt::gt() |> gt::fmt_number( columns = "perc", decimals = 1 ) ## ----warning = FALSE, message = FALSE, fig.height = 10, fig.width = 8--------- # Grab gate as a numeric current_gate <- dens_gates |> dplyr::filter(cd4_pos_cd8_pos == "cd4_neg_cd8_pos") |> dplyr::pull(LAG3) # Apply using gs_add_gating-method and # We want a boundary gate openCyto::gs_add_gating_method( gs, alias = "lag3_cd8", pop = "+", parent = "cd4-cd8+", dims = "LAG3", gating_method = "boundary", gating_args = list(min = current_gate, max = Inf) ) current_gate <- dens_gates |> dplyr::filter(cd4_pos_cd8_pos == "cd4_pos_cd8_neg") |> dplyr::pull(LAG3) openCyto::gs_add_gating_method( gs, alias = "lag3_cd4", pop = "+", parent = "cd4+cd8-", dims = "LAG3", gating_method = "boundary", gating_args = list(min = current_gate, max = Inf) ) ggcyto::autoplot(gs[[1]]) ## ----------------------------------------------------------------------------- sessionInfo()