diff --git a/.Rbuildignore b/.Rbuildignore index 2b42f0ac..e20d4904 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -28,3 +28,5 @@ ^vignettes/articles$ ^vignettes/.quarto$ ^CRAN-SUBMISSION$ +^immdata-.*$ +^immdata*$ diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index bfc9f4db..9e66e42f 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -37,7 +37,7 @@ jobs: needs: website - name: Build site - run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) + run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE, run_dont_run = FALSE) shell: Rscript {0} - name: Deploy to GitHub pages 🚀 diff --git a/DESCRIPTION b/DESCRIPTION index 0123266b..85d4c443 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: immunarch Type: Package Title: Multi-Modal Immune Repertoire Analytics for Immunotherapy and Vaccine Design in R -Version: 0.10.0 +Version: 0.10.2 Authors@R: c( person("Vadim I.", "Nazarov", , "support@immunomind.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0003-3659-2709")), @@ -19,10 +19,10 @@ Description: A comprehensive analytics framework for building reproducible pipel Think Scanpy or Seurat, but for AIRR data, a.k.a. Adaptive Immune Receptor Repertoire, VDJ-seq, RepSeq, or VDJ sequencing data. A successor to our previously published "tcR" R package (Nazarov 2015). License: Apache License (>= 2.0) -URL: https://immunomind.github.io/docs/, https://github.com/immunomind/immunarch +URL: https://immunomind.github.io/docs/, https://github.com/immunomind/immunarch/, https://immunarch.com/ BugReports: https://github.com/immunomind/immunarch/issues Depends: - R (>= 4.1.0), + R (>= 4.2.0), ggplot2 (>= 3.1.0), immundata (>= 0.0.5), patchwork @@ -53,16 +53,19 @@ Imports: utils, glue, checkmate, - duckplyr (>= 1.1.0), + duckplyr (>= 1.1.2), dbplyr, lifecycle, purrr, - stats + stats, + vctrs, + ggthemes, + ggsci LinkingTo: Rcpp Suggests: knitr (>= 1.8), roxygen2 (>= 3.0.0), - testthat (>= 2.1.0), + testthat (>= 3.0.0), pkgdown (>= 0.1.0), assertthat, rmarkdown, @@ -90,3 +93,4 @@ LazyData: true LazyDataCompression: xz Roxygen: list(markdown = TRUE) Config/Needs/website: rmarkdown +Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index e9f001af..faa2be93 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -145,8 +145,11 @@ importFrom(checkmate,assert_character) importFrom(checkmate,assert_choice) importFrom(checkmate,assert_data_frame) importFrom(checkmate,assert_logical) +importFrom(checkmate,assert_matrix) importFrom(checkmate,assert_numeric) importFrom(checkmate,assert_r6) +importFrom(checkmate,assert_string) +importFrom(checkmate,assert_subset) importFrom(circlize,chordDiagram) importFrom(cli,cli_alert_info) importFrom(cli,cli_alert_success) @@ -189,6 +192,7 @@ importFrom(dplyr,group_by) importFrom(dplyr,group_by_at) importFrom(dplyr,group_keys) importFrom(dplyr,group_map) +importFrom(dplyr,inner_join) importFrom(dplyr,intersect) importFrom(dplyr,left_join) importFrom(dplyr,mutate) @@ -213,6 +217,8 @@ importFrom(dplyr,union_all) importFrom(dtplyr,lazy_dt) importFrom(duckplyr,as_duckdb_tibble) importFrom(duckplyr,as_tbl) +importFrom(ggsci,scale_fill_locuszoom) +importFrom(ggthemes,theme_few) importFrom(glue,glue) importFrom(grDevices,colorRampPalette) importFrom(graphics,plot) @@ -310,4 +316,5 @@ importFrom(utils,read.table) importFrom(utils,setTxtProgressBar) importFrom(utils,tail) importFrom(utils,txtProgressBar) +importFrom(vctrs,s3_register) useDynLib(immunarch, .registration = TRUE) diff --git a/R/aaa-registry.R b/R/aaa-registry.R index 10c6f1bf..260ce22a 100644 --- a/R/aaa-registry.R +++ b/R/aaa-registry.R @@ -1,7 +1,16 @@ IMMUNARCH_METHOD_REGISTRY <- new.env(parent = emptyenv()) +IMMUNARCH_VIS_REGISTRY <- new.env(parent = emptyenv()) -#' Common arguments for immundata helpers +IMMUNARCH_CLASS_PREFIX <- "immunarch_res" + + +# ---------------------------------------------------------------------------- # +# --- Common arguments +# ---------------------------------------------------------------------------- # + + +#' Common arguments for immunarch helpers #' @keywords internal #' @param autojoin Logical. If TRUE, join repertoire metadata by the schema repertoire id. #' Change the default behaviour by calling `options(immunarch.autojoin = FALSE)`. @@ -13,6 +22,42 @@ im_common_args <- function( format = c("long", "wide")) {} # nocov +# ---------------------------------------------------------------------------- # +# --- Immunarch results attributes +# ---------------------------------------------------------------------------- # + + +im_norm <- function(x) { + x <- tolower(x) + gsub("[^a-z0-9]+", "_", x) +} + + +im_result_class <- function(family, name = NULL) { + fam <- im_norm(family) + if (is.null(name)) { + paste0(IMMUNARCH_CLASS_PREFIX, "_", fam) + } else { + nm <- im_norm(name) + paste0(IMMUNARCH_CLASS_PREFIX, "_", fam, "_", nm) + } +} + + +im_as_result <- function(x, family, name) { + # Wrap any object as an Immunarch result, preserving original classes + cls_full <- im_result_class(family, name) + cls_fam <- im_result_class(family, NULL) + # TODO: maybe I need the "airr" or "receptor" instead of IMMUNARCH_CLASS_PREFIX? + structure(x, class = c(cls_full, cls_fam, IMMUNARCH_CLASS_PREFIX, class(x))) +} + + +# ---------------------------------------------------------------------------- # +# --- Immunarch methods +# ---------------------------------------------------------------------------- # + + im_method <- function(core, family, name, required_cols = NULL, need_repertoires = TRUE) { checkmate::assert_function(core, args = c("idata")) checkmate::assert_string(family) @@ -96,6 +141,9 @@ im_method <- function(core, family, name, required_cols = NULL, need_repertoires } } + # Wrap the output to assign correct classes + out <- im_as_result(out, family, name) + out }, list(core = core, core_fmls = core_fmls, required_cols = required_cols) @@ -180,5 +228,58 @@ register_immunarch_method <- function(core, family, name, register_family = TRUE ), silent = TRUE) } + # Link visualisation to a method if visualisation was already created + im_ensure_vis_s3_for(family, name) + fn } + + +# ---------------------------------------------------------------------------- # +# --- Immunarch visualisations +# ---------------------------------------------------------------------------- # + + +IMMUNARCH_VIS_REGISTRY <- new.env(parent = emptyenv()) + +.im_ns <- function() asNamespace("immunarch") + +im_vis_s3_exists <- function(class) { + !is.null(utils::getS3method("vis", class, optional = TRUE)) +} + +im_ensure_vis_s3_for <- function(family, name) { + cls <- im_result_class(family, name) + fn <- IMMUNARCH_VIS_REGISTRY[[cls]] + if (!is.function(fn)) { + return(invisible(FALSE)) + } + if (im_vis_s3_exists(cls)) { + return(invisible(FALSE)) + } + + method <- function(.data, ...) { + f <- IMMUNARCH_VIS_REGISTRY[[cls]] + if (!is.function(f)) cli::cli_abort("Visualization for {.code {cls}} not found.") + f(.data, ...) + } + + base::registerS3method("vis", cls, method, envir = .im_ns()) + invisible(TRUE) +} + +register_immunarch_visualisation <- function(fn, family, name) { + checkmate::assert_function(fn, args = c(".data")) + checkmate::assert_string(family) + checkmate::assert_string(name) + + cls <- im_result_class(family, name) + assign(cls, fn, envir = IMMUNARCH_VIS_REGISTRY) + + # immediate S3 registration (errors if vis generic not yet defined) + if (!exists("vis", envir = .im_ns(), inherits = FALSE)) { + stop("vis() generic must be defined before registering visualisations.") + } + im_ensure_vis_s3_for(family, name) + invisible(cls) +} diff --git a/R/globals.R b/R/globals.R index 468d578a..ac335dd1 100644 --- a/R/globals.R +++ b/R/globals.R @@ -8,7 +8,9 @@ utils::globalVariables(c( "ch", "clonal_prop_bin", "clonal_rank_bin", - "prop" + "prop", + ".val", + "size" )) #' @keywords internal diff --git a/R/immunarch-package.R b/R/immunarch-package.R index 0d1915b5..5ff84883 100644 --- a/R/immunarch-package.R +++ b/R/immunarch-package.R @@ -3,8 +3,11 @@ #' @importFrom checkmate assert_choice #' @importFrom checkmate assert_data_frame #' @importFrom checkmate assert_logical +#' @importFrom checkmate assert_matrix #' @importFrom checkmate assert_numeric #' @importFrom checkmate assert_r6 +#' @importFrom checkmate assert_string +#' @importFrom checkmate assert_subset #' @importFrom cli cli_alert_info #' @importFrom cli cli_alert_success #' @importFrom cli cli_alert_warning @@ -23,6 +26,7 @@ #' @importFrom dplyr count #' @importFrom dplyr distinct #' @importFrom dplyr filter +#' @importFrom dplyr inner_join #' @importFrom dplyr intersect #' @importFrom dplyr left_join #' @importFrom dplyr mutate @@ -37,6 +41,8 @@ #' @importFrom dplyr union_all #' @importFrom duckplyr as_duckdb_tibble #' @importFrom duckplyr as_tbl +#' @importFrom ggsci scale_fill_locuszoom +#' @importFrom ggthemes theme_few #' @importFrom immundata imd_schema #' @importFrom immundata ImmunData #' @importFrom lifecycle deprecated @@ -57,6 +63,7 @@ #' @importFrom tidyr as_tibble #' @importFrom utils adist #' @importFrom utils globalVariables +#' @importFrom vctrs s3_register #' @useDynLib immunarch, .registration = TRUE ## usethis namespace: end NULL diff --git a/R/v0_data_docs.R b/R/v0_data_docs.R index e36805d4..a53f6715 100644 --- a/R/v0_data_docs.R +++ b/R/v0_data_docs.R @@ -93,22 +93,3 @@ AA_TABLE_REVERSED <- AA_TABLE_REVERSED[order(names(AA_TABLE_REVERSED))] #' ... #' } "bcrdata" - - -#' Paired chain immune repertoire dataset -#' -#' @concept data -#' -#' @description A dataset with paired chain IG data for testing and examplatory purposes. -#' -#' @format A list of four elements: -#' "data" is a list with data frames with clonotype tables. -#' "meta" is a metadata table. -#' "bc_patients" is a list of barcodes corresponding to specific patients. -#' "bc_clusters" is a list of barcodes corresponding to specific cell clusters. -#' \describe{ -#' \item{data}{List of immune repertoire data frames.} -#' \item{meta}{Metadata} -#' ... -#' } -"scdata" diff --git a/R/v0_filters.R b/R/v0_filters.R index 9cae0759..10541e21 100644 --- a/R/v0_filters.R +++ b/R/v0_filters.R @@ -45,29 +45,6 @@ #' - substring: matches all strings containing the specified substring. #' Default value: 'exact'. #' -#' @examples -#' data(immdata) -#' -#' # Select samples with status "MS" -#' repFilter(immdata, "by.meta", list(Status = include("MS"))) -#' -#' # Select samples without status "MS" -#' repFilter(immdata, "by.meta", list(Status = exclude("MS"))) -#' -#' # Select samples from lanes "A" and "B" with age > 15 -#' repFilter(immdata, "by.meta", list(Lane = include("A", "B"), Age = morethan(15))) -#' -#' # Select samples that are not from lanes "A" and "B" -#' repFilter(immdata, "by.meta", list(Lane = exclude("A", "B"))) -#' -#' # Select samples with a number of clonotypes from 1000 to 5000 -#' repFilter(immdata, "by.repertoire", list(n_clonotypes = interval(1000, 5000))) -#' -#' # Select clonotypes in all samples with alpha chains -#' repFilter(immdata, "by.clonotype", -#' list(V.name = include("AV"), J.name = include("AJ")), -#' .match = "substring" -#' ) #' @export repFilter include exclude lessthan morethan interval repFilter <- function(.data, .method = "by.clonotype", .query = list(CDR3.aa = exclude("partial", "out_of_frame")), diff --git a/R/v0_overlap.R b/R/v0_overlap.R index 4c33389c..9f19a3ec 100644 --- a/R/v0_overlap.R +++ b/R/v0_overlap.R @@ -378,9 +378,11 @@ horn_index <- function(.x, .y) { #' List with overlap matrices. #' #' @examples +#' \dontrun{ #' data(immdata) #' ov <- repOverlap(immdata$data, "inc+overlap", .step = 100, .verbose.inc = FALSE, .verbose = FALSE) #' vis(ov) +#' } #' @export inc_overlap inc_overlap <- function(.data, .fun, .step = 1000, .n.steps = 10, .downsample = FALSE, .bootstrap = NA, .verbose.inc = TRUE, ...) { .n.steps <- as.integer(.n.steps) diff --git a/R/v0_vis.R b/R/v0_vis.R index bf52c686..7b4d50e6 100644 --- a/R/v0_vis.R +++ b/R/v0_vis.R @@ -163,10 +163,6 @@ theme_cleveland2 <- function(rotate = TRUE) { #' One function to visualise them all #' -#' @concept vis -#' -#' @name vis -#' #' @import ggplot2 #' @importFrom grDevices colorRampPalette #' @importFrom tidyr drop_na @@ -244,6 +240,7 @@ theme_cleveland2 <- function(rotate = TRUE) { #' @seealso [fixVis] for precise manipulation of plots. #' #' @examples +#' \dontrun{ #' # Load the test data #' data(immdata) #' @@ -256,7 +253,8 @@ theme_cleveland2 <- function(rotate = TRUE) { #' #' dv <- repDiversity(immdata$data) #' vis(dv) -#' @export vis +#' } +#' @export vis <- function(.data, ...) { UseMethod("vis") } @@ -302,12 +300,14 @@ vis <- function(.data, ...) { #' A ggplot2, pheatmap or circlize object. #' #' @examples +#' \dontrun{ #' data(immdata) #' ov <- repOverlap(immdata$data) #' vis(ov) #' vis(ov, "heatmap") #' vis(ov, "heatmap2") #' vis(ov, "circos") +#' } #' @export vis.immunr_ov_matrix <- function(.data, .plot = c("heatmap", "heatmap2", "circos"), ...) { args <- list(...) @@ -396,11 +396,13 @@ vis.immunr_gu_matrix <- function(.data, .plot = c("heatmap", "heatmap2", "circos #' @seealso [vis], [repOverlap]. #' #' @examples +#' \dontrun{ #' data(immdata) #' ov <- repOverlap(immdata$data) #' vis_heatmap(ov) #' gu <- geneUsage(immdata$data, "hs.trbj") #' vis_heatmap(gu) +#' } #' @export vis_heatmap <- function(.data, .text = TRUE, .scientific = FALSE, .signif.digits = 2, .text.size = 4, .axis.text.size = NULL, @@ -510,9 +512,11 @@ vis_heatmap <- function(.data, .text = TRUE, .scientific = FALSE, .signif.digits #' @seealso [vis], [repOverlap] #' #' @examples +#' \dontrun{ #' data(immdata) #' ov <- repOverlap(immdata$data) #' vis_heatmap2(ov) +#' } #' @export vis_heatmap2 <- function(.data, .meta = NA, .by = NA, .title = NA, .color = colorRampPalette(c("#67001f", "#d6604d", "#f7f7f7", "#4393c3", "#053061"))(1024), ...) { args <- list(...) @@ -560,9 +564,11 @@ vis_heatmap2 <- function(.data, .meta = NA, .by = NA, .title = NA, .color = colo #' @seealso [vis], [repOverlap]. #' #' @examples +#' \dontrun{ #' data(immdata) #' ov <- repOverlap(immdata$data) #' vis(ov, .plot = "circos") +#' } #' @export vis_circos <- function(.data, .title = NULL, ...) { if (has_class(.data, "tibble")) { @@ -686,10 +692,12 @@ vis_circos <- function(.data, .title = NULL, ...) { #' @seealso [repOverlap] #' #' @examples +#' \dontrun{ #' data(immdata) #' tmp <- repOverlap(immdata$data[1:4], "inc+overlap", .verbose.inc = FALSE, .verbose = FALSE) #' vis(tmp, .target = 1) #' vis(tmp, .grid = TRUE) +#' } #' @export vis.immunr_inc_overlap <- function(.data, .target = 1, .grid = FALSE, .ncol = 2, ...) { data_is_bootstrapped <- !is.null(attr(.data, "bootstrap")) @@ -786,6 +794,7 @@ vis.immunr_inc_overlap <- function(.data, .target = 1, .grid = FALSE, .ncol = 2, #' A ggplot2 object. #' #' @examples +#' \dontrun{ #' data(immdata) #' immdata$data <- lapply(immdata$data, head, 300) #' pr <- pubRep(immdata$data, .verbose = FALSE) @@ -793,6 +802,7 @@ vis.immunr_inc_overlap <- function(.data, .target = 1, .grid = FALSE, .ncol = 2, #' vis(pr, "freq", .type = "none") #' #' vis(pr, "clonotypes", 1, 2) +#' } #' @export vis.immunr_public_repertoire <- function(.data, .plot = c("freq", "clonotypes"), ...) { .plot <- .plot[1] @@ -826,10 +836,12 @@ vis.immunr_public_repertoire <- function(.data, .plot = c("freq", "clonotypes"), #' A ggplot2 object. #' #' @examples +#' \dontrun{ #' data(immdata) #' immdata$data <- lapply(immdata$data, head, 2000) #' pr <- pubRep(immdata$data, .verbose = FALSE) #' pubRepStatistics(pr) %>% vis() +#' } #' @export vis.immunr_public_statistics <- function(.data, ...) { if (!requireNamespace("UpSetR", quietly = TRUE)) { @@ -874,6 +886,7 @@ vis.immunr_public_statistics <- function(.data, ...) { #' A ggplot2 object. #' #' @examples +#' \dontrun{ #' data(immdata) #' immdata$data <- lapply(immdata$data, head, 500) #' pr <- pubRep(immdata$data, .verbose = FALSE) @@ -881,6 +894,7 @@ vis.immunr_public_statistics <- function(.data, ...) { #' vis(pr, "freq", .type = "none") #' vis(pr, "freq", .type = "mean") #' vis(pr, "freq", .by = "Status", .meta = immdata$meta) +#' } vis_public_frequencies <- function(.data, .by = NA, .meta = NA, .type = c("boxplot", "none", "mean")) { .type <- .type[1] @@ -986,9 +1000,11 @@ vis_public_frequencies <- function(.data, .by = NA, .meta = NA, #' @seealso [pubRep], [vis.immunr_public_repertoire] #' #' @examples +#' \dontrun{ #' data(immdata) #' pr <- pubRep(immdata$data, .verbose = FALSE) #' vis(pr, "clonotypes", 1, 2) +#' } vis_public_clonotypes <- function(.data, .x.rep = NA, .y.rep = NA, .title = NA, .ncol = 3, .point.size.modif = 1, .cut.axes = TRUE, @@ -1189,6 +1205,7 @@ vis_public_clonotypes <- function(.data, .x.rep = NA, .y.rep = NA, #' A ggplot2 object, pheatmap or circlize object. #' #' @examples +#' \dontrun{ #' data(immdata) #' #' gu <- geneUsage(immdata$data[[1]]) @@ -1197,6 +1214,7 @@ vis_public_clonotypes <- function(.data, .x.rep = NA, .y.rep = NA, #' gu <- geneUsage(immdata$data) #' vis(gu, .by = "Status", .meta = immdata$meta) #' vis(gu, "box", .by = "Status", .meta = immdata$meta) +#' } #' @seealso [geneUsage] #' #' @export @@ -1298,6 +1316,7 @@ vis.immunr_gene_usage <- function(.data, .plot = c("hist", "box", "heatmap", "he #' @seealso [vis.immunr_gene_usage], [geneUsage] #' #' @examples +#' \dontrun{ #' data(immdata) #' imm_gu <- geneUsage(immdata$data[[1]]) #' vis(imm_gu, @@ -1309,6 +1328,7 @@ vis.immunr_gene_usage <- function(.data, .plot = c("hist", "box", "heatmap", "he #' .plot = "hist", .grid = TRUE, .add.layer = #' theme(axis.text.x = element_text(angle = 75, vjust = 1)) #' ) +#' } #' @export vis_hist <- function(.data, .by = NA, .meta = NA, .title = "Gene usage", .ncol = NA, .points = TRUE, .test = TRUE, .coord.flip = FALSE, @@ -1475,7 +1495,9 @@ vis_hist <- function(.data, .by = NA, .meta = NA, .title = "Gene usage", .ncol = #' @seealso [vis.immunr_gene_usage], [geneUsage] #' #' @examples +#' \dontrun{ #' vis_box(data.frame(Sample = sample(c("A", "B", "C"), 100, TRUE), Value = rnorm(100)), .melt = FALSE) +#' } #' @export vis_box <- function(.data, .by = NA, .meta = NA, .melt = TRUE, .points = TRUE, .test = TRUE, .signif.label.size = 3.5, .defgroupby = "Sample", .grouping.var = "Group", @@ -1636,9 +1658,11 @@ vis_box <- function(.data, .by = NA, .meta = NA, .melt = TRUE, #' @seealso [vis], [repOverlapAnalysis], [geneUsageAnalysis] #' #' @examples +#' \dontrun{ #' data(immdata) #' ov <- repOverlap(immdata$data) #' repOverlapAnalysis(ov, "mds+hclust") %>% vis() +#' } #' @export vis.immunr_hclust <- function(.data, .rect = FALSE, .plot = c("clust", "best"), ...) { if (!requireNamespace("factoextra", quietly = TRUE)) { @@ -1698,9 +1722,11 @@ vis.immunr_hclust <- function(.data, .rect = FALSE, .plot = c("clust", "best"), #' @seealso [vis], [repOverlapAnalysis], [geneUsageAnalysis] #' #' @examples +#' \dontrun{ #' data(immdata) #' ov <- repOverlap(immdata$data) #' repOverlapAnalysis(ov, "mds+kmeans") %>% vis() +#' } #' @export vis.immunr_kmeans <- function(.data, .point = TRUE, .text = TRUE, .ellipse = TRUE, .point.size = 2, .text.size = 10, .plot = c("clust", "best"), @@ -1802,9 +1828,11 @@ vis.immunr_dbscan <- function(.data, .point = TRUE, .text = TRUE, .ellipse = TRU #' - tSNE - [vis.immunr_tsne] #' #' @examples +#' \dontrun{ #' data(immdata) #' ov <- repOverlap(immdata$data) #' repOverlapAnalysis(ov, "mds") %>% vis() +#' } #' @export vis.immunr_mds <- function(.data, .by = NA, .meta = NA, .point = TRUE, .text = TRUE, .ellipse = TRUE, @@ -2030,6 +2058,7 @@ vis_bar_stacked <- function(.data, .by = NA, .meta = NA, #' @seealso [repClonality] [vis] #' #' @examples +#' \dontrun{ #' data(immdata) #' clp <- repClonality(immdata$data, "clonal.prop") #' vis(clp) @@ -2037,6 +2066,7 @@ vis_bar_stacked <- function(.data, .by = NA, .meta = NA, #' hom <- repClonality(immdata$data, "homeo") #' # Remove p values and points from the plot #' vis(hom, .by = "Status", .meta = immdata$meta, .test = FALSE, .points = FALSE) +#' } #' @export vis.immunr_clonal_prop <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), .errorbars.off = FALSE, .points = TRUE, .test = TRUE, .signif.label.size = 3.5, ...) { # ToDo: this and other repClonality and repDiversity functions doesn't work on a single repertoire. Fix it @@ -2214,7 +2244,9 @@ vis.immunr_rare_prop <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.0 #' A ggplot2 object. #' #' @examples +#' \dontrun{ #' vis_bar(data.frame(Sample = c("A", "B", "C"), Value = c(1, 2, 3))) +#' } #' @export vis_bar <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), .errorbars.off = FALSE, .stack = FALSE, .points = TRUE, .test = TRUE, .signif.label.size = 3.5, .errorbar.width = 0.2, .defgroupby = "Sample", .grouping.var = "Group", @@ -2441,9 +2473,11 @@ vis_bar <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), . #' @seealso [repDiversity] [vis] #' #' @examples +#' \dontrun{ #' data(immdata) #' dv <- repDiversity(immdata$data, "chao1") #' vis(dv) +#' } #' @export vis.immunr_chao1 <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), .errorbars.off = FALSE, .points = TRUE, .test = TRUE, .signif.label.size = 3.5, ...) { .data <- data.frame(Sample = row.names(.data), Value = .data[, 1]) @@ -2711,11 +2745,13 @@ vis.immunr_rarefaction <- function(.data, .by = NA, .meta = NA, #' @seealso [repExplore] [vis] #' #' @examples +#' \dontrun{ #' data(immdata) #' repExplore(immdata$data, "volume") %>% vis() #' repExplore(immdata$data, "count") %>% vis() #' repExplore(immdata$data, "len") %>% vis() #' repExplore(immdata$data, "clones") %>% vis() +#' } #' @export vis.immunr_exp_vol <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), .errorbars.off = FALSE, @@ -2829,6 +2865,7 @@ vis.immunr_exp_clones <- function(.data, .by = NA, .meta = NA, #' @seealso `get.kmers` #' #' @examples +#' \dontrun{ #' # Load necessary data and package. #' data(immdata) #' # Get 5-mers. @@ -2837,6 +2874,7 @@ vis.immunr_exp_clones <- function(.data, .by = NA, .meta = NA, #' p1 <- vis(imm.km, .position = "stack") #' p2 <- vis(imm.km, .position = "fill") #' p1 + p2 +#' } #' @export vis.immunr_kmer_table <- function(.data, .head = 100, .position = c("stack", "dodge", "fill"), .log = FALSE, ...) { .position <- switch(substr(.position[1], 1, 1), @@ -2915,6 +2953,7 @@ vis.immunr_kmer_table <- function(.data, .head = 100, .position = c("stack", "do #' @seealso [getKmers], [kmer_profile] #' #' @examples +#' \dontrun{ #' data(immdata) #' kmers <- getKmers(immdata$data[[1]], 5) #' ppm <- kmer_profile(kmers, "prob") @@ -2924,6 +2963,7 @@ vis.immunr_kmer_table <- function(.data, .head = 100, .position = c("stack", "do #' d <- kmer_profile(c("CASLL", "CASSQ", "CASGL")) #' vis_textlogo(d) #' vis_seqlogo(d) +#' } #' @export vis_textlogo <- function(.data, .replace.zero.with.na = TRUE, .width = 0.1, ...) { # ToDo: make different color schemas, for type of aminoacids (polarity, etc), etc @@ -2979,10 +3019,12 @@ vis_seqlogo <- function(.data, .scheme = "chemistry", ...) { #' A ggplot2 object. #' #' @examples +#' \dontrun{ #' data(immdata) #' getKmers(immdata$data[[1]], 5) %>% #' kmer_profile() %>% #' vis("seqlogo") +#' } #' @export vis_immunr_kmer_profile_main <- function(.data, .plot, ...) { if (.plot[1] == "text") { @@ -3050,6 +3092,7 @@ vis.immunr_kmer_profile_self <- function(.data, .plot = c("textlogo", "seqlogo") #' A ggplot2 object. #' #' @examples +#' \dontrun{ #' # Load an example data that comes with immunarch #' data(immdata) #' @@ -3096,6 +3139,7 @@ vis.immunr_kmer_profile_self <- function(.data, .plot = c("textlogo", "seqlogo") #' immdata$meta$Sample[sample_order] #' # And finally, we visualise the data: #' vis(tc, .order = sample_order) +#' } #' @export vis.immunr_dynamics <- function(.data, .plot = c("smooth", "area", "line"), .order = NA, .log = FALSE, ...) { if (!requireNamespace("ggalluvial", quietly = TRUE)) { @@ -3177,6 +3221,7 @@ vis.immunr_dynamics <- function(.data, .plot = c("smooth", "area", "line"), .ord #' A ggraph object. #' #' @examples +#' \dontrun{ #' data(bcrdata) #' bcr_data <- bcrdata$data #' @@ -3186,6 +3231,7 @@ vis.immunr_dynamics <- function(.data, .plot = c("smooth", "area", "line"), .ord #' repAlignLineage(.min_lineage_sequences = 2, .align_threads = 2, .nofail = TRUE) %>% #' repClonalFamily(.threads = 1, .nofail = TRUE) %>% #' vis() +#' } #' @export vis.clonal_family <- function(.data, ...) { if (inherits(.data, "clonal_family_df")) { @@ -3228,6 +3274,7 @@ vis.clonal_family <- function(.data, ...) { #' A ggraph object. #' #' @examples +#' \dontrun{ #' data(bcrdata) #' bcr_data <- bcrdata$data #' @@ -3242,6 +3289,7 @@ vis.clonal_family <- function(.data, ...) { #' if (!("step_failure_ignored" %in% class(clonal_family))) { #' vis(clonal_family[["full_clones"]][["TreeStats"]][[2]]) #' } +#' } #' @export vis.clonal_family_tree <- function(.data, ...) { if (!requireNamespace("ggraph", quietly = TRUE)) { diff --git a/R/v1_aaa_commons_vis.R b/R/v1_aaa_commons_vis.R new file mode 100644 index 00000000..63433ede --- /dev/null +++ b/R/v1_aaa_commons_vis.R @@ -0,0 +1,359 @@ +# +# 1) Look at this for examples: https://chatgpt.com/c/68eacc4b-785c-832a-88f5-b94086ad7f26 +# +# 2) Register in the registry. Registry should check if all visualisations are assigned to existing (!) classes. +# vis_airr_diversity_chao1 <- ... +# It is probably impossible to do... +# Should use https://stat.ethz.ch/R-manual/R-devel/RHOME/library/base/html/S3method.html +# +# 3) I need registry to control the class system in one place. One for assigning classes following a specific schema, the other one is for parsing classes. +# I probably need to write a short manual on the logic of this. And on the structure of the code. And on the phiolosophy / architectural design decisions. Same for immundata. +# +# 4) Key question: can I use different names? https://stackoverflow.com/questions/61482561/whats-the-preferred-means-for-defining-an-s3-method-in-an-r-package-without-int/61483612#61483612 +# https://vctrs.r-lib.org/reference/s3_register.html +# +# 5) [!!!] I still need some name for Roxygen to @inheritParams. There is no way around that. +# opt.1 - dynamically register S3 stuff, one big vis() or some weird names for docs +# opt.2 - pre-defined classes, vis() is constructed via @inheritParams +# Or... +# - https://github.com/r-lib/roxygen2/issues/1159 +# - https://github.com/rstudio/renv/blob/4a8bcb4605f085fbea5f29a76ad9a291ac2bd363/R/roxygen.R#L2-L26 + +#' @keywords internal +make_fixed_col_plot <- function(x_col, y_col, title, xlab, ylab) { + checkmate::assert_string(x_col) + checkmate::assert_string(y_col) + checkmate::assert_string(title) + checkmate::assert_string(xlab) + checkmate::assert_string(ylab) + + col_plot <- function(.data, fill = immundata::imd_schema("repertoire"), facet = NULL, dir = c("h", "v"), ...) { + checkmate::assert_data_frame(.data) + checkmate::assert_subset(c(x_col, y_col), choices = names(.data)) + + dir <- match.arg(dir) + + # factors in case the fill is continuous + if (!is.null(fill)) { + checkmate::assert_string(fill) + checkmate::assert_choice(fill, names(.data)) + } else { + fill <- immundata::imd_schema("repertoire") + } + .data[[fill]] <- as.factor(.data[[fill]]) + + if (!is.null(facet)) { + checkmate::assert_character(facet, any.missing = FALSE, min.len = 1, max.len = 2) + checkmate::assert_subset(facet, names(.data)) + } + + # core plot + p <- ggplot2::ggplot(.data, ggplot2::aes(x = .data[[x_col]], y = .data[[y_col]], fill = .data[[fill]])) + + if (fill == immundata::imd_schema("repertoire")) { + p <- p + + ggplot2::geom_col( + na.rm = TRUE, + position = ggplot2::position_dodge(), + colour = "grey30" + ) + } else { + len_vals <- sort(unique(.data[[x_col]])) + p <- p + + ggplot2::geom_vline(xintercept = len_vals, colour = "grey90", linewidth = 0.25) + + ggplot2::geom_boxplot( + mapping = ggplot2::aes(group = interaction(.data[[x_col]], .data[[fill]], drop = TRUE)), + na.rm = TRUE, + colour = "grey30" + ) + + ggplot2::geom_violin( + mapping = ggplot2::aes(group = interaction(.data[[x_col]], .data[[fill]], drop = TRUE)), + na.rm = TRUE, + colour = "grey30", + alpha = 0.3 + ) + } + + # one string -> one facet + # vector of two strings -> square facet + if (!is.null(facet)) { + if (length(facet) == 1) { + p <- p + ggplot2::facet_wrap(dir = dir, stats::as.formula(paste0("~", facet)), scales = "free_y") + } else { + p <- p + ggplot2::facet_grid(stats::as.formula(paste(facet[1], "~", facet[2])), + scales = "free_y" + ) + } + } + + # titles + p <- p + + ggplot2::ggtitle(title) + + ggplot2::xlab(xlab) + + ggplot2::ylab(ylab) + + # auto select the palette + if (!is.null(fill)) { + k <- length(unique(.data[[fill]])) + if (requireNamespace("ggsci", quietly = TRUE) && k <= 11) { + p <- p + ggsci::scale_fill_locuszoom(name = fill) + } else { + p <- p + ggplot2::scale_fill_viridis_d(option = "H") + } + } + + # light theme + if (requireNamespace("ggthemes", quietly = TRUE)) { + p <- p + ggthemes::theme_few() + } + + p + } + + col_plot +} + + +#' @keywords internal +make_dynam_col_plot <- function(y_default, title_default, position = c("dodge", "stack")) { + checkmate::assert_string(y_default) + checkmate::assert_string(title_default) + position <- match.arg(position) + + col_plot <- function(.data, xval = immundata::imd_schema("repertoire"), yval = y_default, fill = NULL, facet = NULL, title = title_default, dir = c("h", "v"), ...) { + checkmate::assert_data_frame(.data) + checkmate::assert_subset(c(xval, yval), choices = names(.data)) + + dir <- match.arg(dir) + + .data[[xval]] <- as.factor(.data[[xval]]) + + # factors in case the fill is continuous + if (!is.null(fill)) { + checkmate::assert_string(fill) + checkmate::assert_choice(fill, names(.data)) + .data[[fill]] <- as.factor(.data[[fill]]) + } + + if (!is.null(facet)) { + checkmate::assert_character(facet, any.missing = FALSE, min.len = 1, max.len = 2) + checkmate::assert_subset(facet, names(.data)) + } + + # check how many observation per group so we could select either bar or box plot + grp_vars <- c(xval, if (!is.null(fill)) fill else NULL) + n_by_grp <- .data |> + dplyr::group_by(dplyr::across(all_of(grp_vars))) |> + dplyr::summarise(n = sum(!is.na(.data[[yval]])), .groups = "drop") + all_single <- all(n_by_grp$n == 1) + + # core plot + p <- ggplot2::ggplot(.data, ggplot2::aes(x = .data[[xval]], y = .data[[yval]])) + + if (all_single) { + # if (xval == immundata::imd_schema("repertoire") || (!is.null(fill) && fill == immundata::imd_schema("repertoire"))) { + p <- p + + ggplot2::geom_col( + mapping = if (!is.null(fill)) ggplot2::aes(fill = .data[[fill]]) else NULL, + na.rm = TRUE, + position = position, + colour = "grey30" + ) + } else { + p <- p + + ggplot2::geom_boxplot( + mapping = if (!is.null(fill)) ggplot2::aes(group = interaction(.data[[xval]], .data[[fill]], drop = TRUE), fill = .data[[fill]]) else ggplot2::aes(fill = .data[[xval]]), + na.rm = TRUE, + colour = "grey30" + ) + + ggplot2::geom_violin( + mapping = if (!is.null(fill)) ggplot2::aes(group = interaction(.data[[xval]], .data[[fill]], drop = TRUE), fill = .data[[fill]]) else ggplot2::aes(fill = .data[[xval]]), + colour = "grey30", + alpha = 0.3, + position = if (!is.null(fill)) ggplot2::position_dodge(width = 0.75) else "identity" + ) + } + + + # one string -> one facet + # vector of two strings -> square facet + if (!is.null(facet)) { + if (length(facet) == 1) { + p <- p + ggplot2::facet_wrap(dir = dir, stats::as.formula(paste0("~", facet)), scales = "free_y") + } else { + p <- p + ggplot2::facet_grid(stats::as.formula(paste(facet[1], "~", facet[2])), + scales = "free_y" + ) + } + } + + # titles + p <- p + + ggplot2::ggtitle(title) + + # auto select the palette + if (!is.null(fill)) { + k <- length(unique(.data[[fill]])) + } else { + k <- length(unique(.data[[xval]])) + } + if (requireNamespace("ggsci", quietly = TRUE) && k <= 11) { + p <- p + ggsci::scale_fill_locuszoom(name = fill) + } else { + p <- p + ggplot2::scale_fill_viridis_d(option = "H") + } + + # light theme + if (requireNamespace("ggthemes", quietly = TRUE)) { + p <- p + ggthemes::theme_few() + + ggplot2::theme( + panel.grid = ggplot2::element_blank() + ) + + ggplot2::scale_x_discrete(guide = guide_axis(angle = 45)) + } + + p + } + + col_plot +} + + +#' @keywords internal +make_dotplot <- function(title_default, fill_default, size_default) { + checkmate::assert_string(title_default) + checkmate::assert_string(fill_default) + checkmate::assert_string(size_default) + + dotplot_matrix <- function(.data, + size_max_mm = 7, + row = NULL, # string: row id (e.g., "v_call") + col = NULL, # string or character vector: column id(s) (e.g., "Cluster" or c("Cluster","Tissue")) + value = NULL, # string: numeric column for values; if NULL and "n" exists, uses "n"; else counts + col_sep = " | ", # used when col has length > 1 + row_order = NULL, + col_order = NULL) { + # ---------- input checks ---------- + if (is.matrix(.data)) { + checkmate::assert_matrix(.data, mode = "numeric", any.missing = TRUE, min.rows = 1, min.cols = 1) + mat <- .data + } else { + checkmate::assert_data_frame(.data, min.rows = 1, min.cols = 3) + + # Infer sensible defaults if not provided + rep_col <- immundata::imd_schema("repertoire") + + if (is.null(row)) { + # default row key = first non-repertoire column + row <- setdiff(names(.data), rep_col)[1] + } + checkmate::assert_string(row) + checkmate::assert_choice(row, names(.data)) + + if (is.null(col)) { + # default columns = repertoire + col <- rep_col + } + checkmate::assert_character(col, any.missing = FALSE, min.len = 1) + checkmate::assert_subset(col, names(.data)) + + # value: prefer provided; else "n"; else count per cell + if (!is.null(value)) { + checkmate::assert_string(value) + checkmate::assert_choice(value, names(.data)) + checkmate::assert_numeric(.data[[value]], any.missing = TRUE) + } else if ("n" %in% names(.data)) { + value <- "n" + checkmate::assert_numeric(.data[[value]], any.missing = TRUE) + } else { + value <- NULL # we'll compute counts + } + + df <- .data + df[[row]] <- as.character(df[[row]]) + if (length(col) > 1L) { + df <- tidyr::unite(df, "__col__", tidyselect::all_of(col), sep = col_sep, remove = FALSE) + col_key <- "__col__" + } else { + col_key <- col + } + df[[col_key]] <- as.character(df[[col_key]]) + + # Aggregate to one value per (row, col) + if (is.null(value)) { + df_sum <- df |> + dplyr::group_by(.data[[row]], .data[[col_key]]) |> + dplyr::summarise(.val = dplyr::n(), .groups = "drop") + } else { + df_sum <- df |> + dplyr::group_by(.data[[row]], .data[[col_key]]) |> + dplyr::summarise(.val = sum(.data[[value]], na.rm = TRUE), .groups = "drop") + } + + # Pivot wider → numeric matrix + wide <- tidyr::pivot_wider( + df_sum, + names_from = tidyselect::all_of(col_key), + values_from = .val, + values_fill = 0 + ) + rn <- wide[[row]] + checkmate::assert_atomic_vector(rn, all.missing = FALSE, min.len = 1) + mat_df <- as.data.frame(wide, check.names = FALSE) + mat_df[[row]] <- NULL + mat <- as.matrix(mat_df) + rownames(mat) <- rn + } + + checkmate::assert_number(size_max_mm, lower = 0, finite = TRUE) + + # + # Plotting + # + rn <- rownames(mat) + if (is.null(rn)) rn <- as.character(seq_len(nrow(mat))) + cn <- colnames(mat) + if (is.null(cn)) cn <- as.character(seq_len(ncol(mat))) + + df <- as.data.frame(mat, check.names = FALSE) + df$row <- rn + df <- tidyr::pivot_longer(df, -row, names_to = "col", values_to = "value") + + # TODO: maybe make size relative to the source repertoire? + rng <- range(df$value, na.rm = TRUE) + df$size <- if (is.finite(diff(rng)) && diff(rng) > 0) (df$value - rng[1]) / diff(rng) else 0 + + if (is.null(row_order)) row_order <- rn + if (is.null(col_order)) col_order <- cn + df$row <- factor(df$row, levels = rev(row_order)) + df$col <- factor(df$col, levels = col_order) + + p <- ggplot2::ggplot(df, ggplot2::aes(x = col, y = row)) + + ggplot2::geom_point( + ggplot2::aes(size = size, fill = value), + colour = "grey30", + stroke = 0.3, + shape = 21, na.rm = TRUE + ) + + ggplot2::scale_size_area( + max_size = size_max_mm, + guide = ggplot2::guide_legend(title = size_default) + ) + + ggplot2::scale_fill_gradientn( + colors = c("#0F172A", "#243B55", "#FFE3A3", "#FFC107"), + na.value = "grey90", + guide = ggplot2::guide_colorbar(title = fill_default) + ) + + ggplot2::labs(x = NULL, y = NULL, title = title_default) + + ggplot2::coord_cartesian(clip = "off") + + ggthemes::theme_few(base_size = 12) + + ggplot2::theme( + panel.grid = ggplot2::element_blank(), + axis.text.x = ggplot2::element_text(angle = 90, vjust = 0.5, hjust = 1) + ) + + p + } + + dotplot_matrix +} diff --git a/R/v1_aaa_registry_utils.R b/R/v1_aaa_registry_utils.R index 7c8e3051..2e0f913c 100644 --- a/R/v1_aaa_registry_utils.R +++ b/R/v1_aaa_registry_utils.R @@ -29,7 +29,7 @@ register_airr_method <- function(family_name, method_name, fn) { } get_airr_method <- function(family_name, method_name, verbose = TRUE) { - # checkmate checks + # TODO: checkmate checks fam_env <- IMMUNARCH_METHOD_REGISTRY[[family_name]] @@ -54,8 +54,6 @@ get_airr_method <- function(family_name, method_name, verbose = TRUE) { } make_airr_dispatcher <- function(family_name) { - # checkmate for family_name - function(idata = NULL, method = NULL, ...) { checkmate::assert_r6(idata, "ImmunData", null.ok = TRUE) checkmate::assert_character(method, null.ok = TRUE) diff --git a/R/v1_airr_public.R b/R/v1_airr_public.R deleted file mode 100644 index 1eb65992..00000000 --- a/R/v1_airr_public.R +++ /dev/null @@ -1,144 +0,0 @@ -#' @title Public indices - pairwise repertoire overlap -#' -#' @description -#' `r lifecycle::badge("experimental")` -#' -#' A family of functions to quantify **public or shared receptors** between repertoire. -#' -#' ## Available functions -#' -#' Supported methods are the following. -#' -#' @param idata An `ImmunData` object. -#' @inheritParams airr_public_intersection -#' @inheritParams airr_public_jaccard -#' @inheritParams im_common_args -#' -#' @seealso [immundata::ImmunData] -#' -#' @examples -#' # Load data -#' immdata <- get_test_idata() |> agg_repertoires("Therapy") -#' -#' @name airr_public -#' @concept Public indices -NULL - - -#' @keywords internal -airr_public_intersection_impl <- function(idata) { - receptor_id_col <- immundata::imd_schema("receptor") - repertoire_id_col <- immundata::imd_schema("repertoire") - repertoire_ids <- idata$repertoires |> - pull({{ repertoire_id_col }}) |> - unique() - - result_matrix <- matrix(-1, nrow = length(repertoire_ids), ncol = length(repertoire_ids)) - - for (i in seq_along(repertoire_ids[-length(repertoire_ids)])) { - for (j in seq_along(repertoire_ids[(i + 1):length(repertoire_ids)])) { - rep_1_index <- repertoire_ids[i] - rep_2_index <- repertoire_ids[i + j] - - val_pub <- idata$annotations |> - filter(!!rlang::sym(repertoire_id_col) == rep_1_index, !!rlang::sym(repertoire_id_col) == rep_2_index) |> - distinct(!!rlang::sym(repertoire_id_col)) |> - count() |> - pull("n") - - result_matrix[rep_1_index, rep_2_index] <- val_pub - result_matrix[rep_2_index, rep_1_index] <- val_pub - } - } - - result_matrix -} - -#' @description `airr_public_intersection` - number of **shared receptors** between -#' each pair of repertoires (intersection size). Handy for quick overlap heatmaps, -#' QC of replicate similarity, or spotting donor-shared "public" clonotypes. -#' -#' @return -#' -#' ## `airr_public_intersection` -#' A **symmetric numeric matrix** where rows/columns are `repertoire_id` and each -#' cell is the count of shared unique receptors. The diagonal contains per-repertoire -#' richness (total unique receptors). Row/column names are repertoire IDs. -#' -#' @examples -#' # -#' # airr_public_intersection -#' # -#' m_pub <- airr_public_intersection(immdata) -#' -#' @rdname airr_public -#' @concept Public indices -#' @export -airr_public_intersection <- register_immunarch_method(airr_public_intersection_impl, "airr_public", "intersection") - - -#' @keywords internal -airr_public_jaccard_impl <- function(idata) { - receptor_id_col <- immundata::imd_schema("receptor") - repertoire_id_col <- immundata::imd_schema("repertoire") - repertoire_ids <- idata$repertoires |> - pull({{ repertoire_id_col }}) |> - unique() - - result_matrix <- matrix(-1, nrow = length(repertoire_ids), ncol = length(repertoire_ids)) - - for (i in seq_along(repertoire_ids[-length(repertoire_ids)])) { - for (j in seq_along(repertoire_ids[(i + 1):length(repertoire_ids)])) { - rep_1_index <- repertoire_ids[i] - rep_2_index <- repertoire_ids[i + j] - - repertoire_pair <- idata$annotations |> - filter(!!rlang::sym(repertoire_id_col) %in% c(rep_1_index, rep_2_index)) |> - select({{ repertoire_id_col }}, {{ receptor_id_col }}) - - rep_1 <- repertoire_pair |> - filter(!!rlang::sym(repertoire_id_col) == rep_1_index) |> - select({{ receptor_id_col }}) - rep_2 <- repertoire_pair |> - filter(!!rlang::sym(repertoire_id_col) == rep_2_index) |> - select({{ receptor_id_col }}) - - val_inter <- intersect(rep_1, rep_2) |> - count() |> - pull("n") - val_union <- union(rep_1, rep_2) |> - count() |> - pull("n") - - result_matrix[rep_1_index, rep_2_index] <- val_inter / val_union - result_matrix[rep_2_index, rep_1_index] <- val_inter / val_union - } - } - - result_matrix -} - - -#' @description `airr_public_jaccard` - **Jaccard similarity** of receptor -#' sets between repertoires (\eqn{A \cap B}{A cap B} / \eqn{A \cup B}{A cup B}). Best when comparing cohorts with -#' different sizes to get a scale-invariant overlap score. -#' -#' @inheritParams im_common_args -#' -#' @return -#' -#' ## `airr_public_jaccard` -#' A **symmetric numeric matrix** where rows/columns are `repertoire_id` and each -#' cell is the Jaccard similarity in `[0, 1]`. The diagonal is `1`. Row/column -#' names are repertoire IDs. -#' -#' @examples -#' # -#' # airr_public_jaccard -#' # -#' m_jac <- airr_public_jaccard(immdata) -#' -#' @rdname airr_public -#' @concept Public indices -#' @export -airr_public_jaccard <- register_immunarch_method(airr_public_jaccard_impl, "airr_public", "jaccard") diff --git a/R/v1_airr_clonality.R b/R/v1_clonality_airr.R similarity index 93% rename from R/v1_airr_clonality.R rename to R/v1_clonality_airr.R index 7b011f30..51a1ba4a 100644 --- a/R/v1_airr_clonality.R +++ b/R/v1_clonality_airr.R @@ -20,8 +20,14 @@ #' * Data container: [immundata::ImmunData] #' #' @examples +#' # Limit the number of threads used by the underlying DB for this session. +#' # Change this only if you know what you're doing (e.g., multi-user machines, shared CI/servers). +#' db_exec("SET threads TO 1") +#' #' # Load data +#' \dontrun{ #' immdata <- get_test_idata() |> agg_repertoires("Therapy") +#' } #' #' @name airr_clonality #' @concept Clonality @@ -79,7 +85,9 @@ airr_clonality_line_impl <- function(idata, limit = 100000) { #' # #' # airr_clonality_line #' # +#' \dontrun{ #' top_line <- airr_clonality_line(immdata, limit = 1000) +#' } #' #' @rdname airr_clonality #' @concept Clonality @@ -99,7 +107,7 @@ airr_clonality_rank_impl <- function(idata, bins <- sort(bins, decreasing = FALSE) - clonality_df <- core_clonality_rank(idata = idata, bins = bins) + clonality_df <- base_clonality_rank(idata = idata, bins = bins) clonality_df |> summarise( @@ -130,7 +138,9 @@ airr_clonality_rank_impl <- function(idata, #' # #' # airr_clonality_rank #' # +#' \dontrun{ #' rank_stat <- airr_clonality_rank(immdata, bins = c(10, 100)) +#' } #' #' @rdname airr_clonality #' @concept Clonality @@ -156,7 +166,7 @@ airr_clonality_prop_impl <- function( bins <- sort(bins, decreasing = TRUE) - clonality_df <- core_clonality_prop(idata = idata, bins = bins) + clonality_df <- base_clonality_prop(idata = idata, bins = bins) clonality_df |> summarise( @@ -188,7 +198,9 @@ airr_clonality_prop_impl <- function( #' # #' # airr_clonality_prop #' # +#' \dontrun{ #' prop_stat <- airr_clonality_prop(immdata) +#' } #' #' @rdname airr_clonality #' @concept Clonality diff --git a/R/v1_annotate_clonality.R b/R/v1_clonality_annotate.R similarity index 96% rename from R/v1_annotate_clonality.R rename to R/v1_clonality_annotate.R index 73a0452b..9e35e49b 100644 --- a/R/v1_annotate_clonality.R +++ b/R/v1_clonality_annotate.R @@ -36,7 +36,7 @@ annotate_clonality_rank_impl <- function(idata, bins <- sort(bins, decreasing = FALSE) - clonality_df <- core_clonality_rank(idata = idata, bins = bins) + clonality_df <- base_clonality_rank(idata = idata, bins = bins) by_cols <- c(immundata::imd_schema("receptor"), immundata::imd_schema("repertoire")) names(by_cols) <- c(immundata::imd_schema("receptor"), immundata::imd_schema("repertoire")) @@ -87,7 +87,7 @@ annotate_clonality_prop_impl <- function( bins <- sort(bins, decreasing = TRUE) - clonality_df <- core_clonality_prop(idata = idata, bins = bins) + clonality_df <- base_clonality_prop(idata = idata, bins = bins) by_cols <- c(immundata::imd_schema("receptor"), immundata::imd_schema("repertoire")) names(by_cols) <- c(immundata::imd_schema("receptor"), immundata::imd_schema("repertoire")) diff --git a/R/v1_core_clonality.R b/R/v1_clonality_base.R similarity index 94% rename from R/v1_core_clonality.R rename to R/v1_clonality_base.R index fcb91328..dbbb757b 100644 --- a/R/v1_core_clonality.R +++ b/R/v1_clonality_base.R @@ -1,5 +1,5 @@ #' @keywords internal -core_clonality_rank <- function(idata, bins) { +base_clonality_rank <- function(idata, bins) { checkmate::check_numeric(bins, lower = 1) bins <- sort(bins, decreasing = FALSE) @@ -33,7 +33,7 @@ core_clonality_rank <- function(idata, bins) { #' @keywords internal -core_clonality_prop <- function(idata, bins) { +base_clonality_prop <- function(idata, bins) { sql_expr <- paste0( "CASE ", paste0(map2_chr( diff --git a/R/v1_airr_diversity.R b/R/v1_diversity_airr.R similarity index 96% rename from R/v1_airr_diversity.R rename to R/v1_diversity_airr.R index 02a7d52b..e159e602 100644 --- a/R/v1_airr_diversity.R +++ b/R/v1_diversity_airr.R @@ -21,8 +21,13 @@ #' @seealso [immundata::ImmunData] #' #' @examples +#' # Limit the number of threads used by the underlying DB for this session. +#' # Change this only if you know what you're doing (e.g., multi-user machines, shared CI/servers). +#' db_exec("SET threads TO 1") #' # Load data +#' \dontrun{ #' immdata <- get_test_idata() |> agg_repertoires("Therapy") +#' } #' #' @name airr_diversity #' @concept Diversity @@ -100,8 +105,10 @@ airr_diversity_dxx_impl <- function(idata, perc = 50) { #' # #' # airr_diversity_dxx #' # +#' \dontrun{ #' d50 <- airr_diversity_dxx(immdata, perc = 50) #' d_multi <- airr_diversity_dxx(immdata, perc = c(20, 50, 80)) +#' } #' #' @rdname airr_diversity #' @concept Diversity @@ -151,7 +158,9 @@ airr_diversity_chao1_impl <- function(idata) { #' # #' # airr_diversity_chao1 #' # +#' \dontrun{ #' chao <- airr_diversity_chao1(immdata) +#' } #' #' @rdname airr_diversity #' @concept Diversity @@ -194,7 +203,9 @@ airr_diversity_shannon_impl <- function(idata) { #' # #' # airr_diversity_shannon #' # +#' \dontrun{ #' sh <- airr_diversity_shannon(immdata) +#' } #' #' @rdname airr_diversity #' @concept Diversity @@ -233,7 +244,9 @@ airr_diversity_pielou_impl <- function(idata) { #' # #' # airr_diversity_pielou #' # +#' \dontrun{ #' pj <- airr_diversity_pielou(immdata) +#' } #' #' @rdname airr_diversity #' @concept Diversity @@ -264,7 +277,9 @@ airr_diversity_index_impl <- function(idata) { #' # #' # airr_diversity_index #' # +#' \dontrun{ #' idx <- airr_diversity_index(immdata) +#' } #' #' @rdname airr_diversity #' @concept Diversity @@ -348,7 +363,9 @@ airr_diversity_hill_impl <- function(idata, q = 0:5) { #' # #' # airr_diversity_hill #' # +#' \dontrun{ #' hill <- airr_diversity_hill(immdata, q = c(0, 1, 2)) +#' } #' #' @rdname airr_diversity #' @concept Diversity diff --git a/R/v1_diversity_vis.R b/R/v1_diversity_vis.R new file mode 100644 index 00000000..27c7d695 --- /dev/null +++ b/R/v1_diversity_vis.R @@ -0,0 +1,63 @@ +#' @keywords internal +vis_airr_diversity_dxx_impl <- make_dynam_col_plot( + y_default = "dxx", + title_default = "Coverage diversity (Dxx)", + position = "dodge" +) +register_immunarch_visualisation( + vis_airr_diversity_dxx_impl, + "airr_diversity", + "dxx" +) + + +#' @keywords internal +vis_airr_diversity_chao1_impl <- make_dynam_col_plot( + y_default = "Estimator", + title_default = "Chao1 richness estimator", + position = "dodge" +) +register_immunarch_visualisation( + vis_airr_diversity_chao1_impl, + "airr_diversity", + "chao1" +) + + +#' @keywords internal +vis_airr_diversity_shannon_impl <- make_dynam_col_plot( + y_default = "shannon", + title_default = "Shannon entropy (bits)", + position = "dodge" +) +register_immunarch_visualisation( + vis_airr_diversity_shannon_impl, + "airr_diversity", + "shannon" +) + + +#' @keywords internal +vis_airr_diversity_pielou_impl <- make_dynam_col_plot( + y_default = "pielou", + title_default = "Pielou evenness", + position = "dodge" +) +register_immunarch_visualisation( + vis_airr_diversity_pielou_impl, + "airr_diversity", + "pielou" +) + + +#' @keywords internal +vis_airr_diversity_index_impl <- make_dynam_col_plot( + y_default = "hill_number", + title_default = "Hill diversity index (q = 1)", + position = "dodge" +) +register_immunarch_visualisation( + vis_airr_diversity_index_impl, + "airr_diversity", + "index" +) diff --git a/R/v1_public_airr.R b/R/v1_public_airr.R new file mode 100644 index 00000000..b77b1930 --- /dev/null +++ b/R/v1_public_airr.R @@ -0,0 +1,177 @@ +#' @title Public indices - pairwise repertoire overlap +#' +#' @description +#' `r lifecycle::badge("experimental")` +#' +#' A family of functions to quantify **public or shared receptors** between repertoire. +#' +#' ## Available functions +#' +#' Supported methods are the following. +#' +#' @param idata An `ImmunData` object. +#' @inheritParams airr_public_intersection +#' @inheritParams airr_public_jaccard +#' @inheritParams im_common_args +#' +#' @seealso [immundata::ImmunData] +#' +#' @examples +#' # Limit the number of threads used by the underlying DB for this session. +#' # Change this only if you know what you're doing (e.g., multi-user machines, shared CI/servers). +#' db_exec("SET threads TO 1") +#' # Load data +#' immdata <- get_test_idata() |> agg_repertoires("Therapy") +#' +#' @name airr_public +#' @concept Public indices +NULL + + +#' @keywords internal +airr_public_intersection_impl <- function(idata) { + receptor_id_col <- immundata::imd_schema("receptor") + repertoire_id_col <- immundata::imd_schema("repertoire") + repertoire_ids <- idata$repertoires |> + pull({{ repertoire_id_col }}) |> + unique() |> + sort() + + rep_labels <- idata$repertoires |> + dplyr::select(dplyr::all_of(c(repertoire_id_col, idata$schema_repertoire))) |> + tidyr::unite(".label", dplyr::all_of(idata$schema_repertoire), sep = "|", na.rm = TRUE) |> + dplyr::transmute(rep_id = .data[[repertoire_id_col]], label = .data$.label) + + result_matrix <- matrix(NA, nrow = length(repertoire_ids), ncol = length(repertoire_ids), dimnames = list(rep_labels$label, rep_labels$label)) + + target_cols <- c(immundata::imd_schema("receptor"), immundata::imd_schema("repertoire")) + rep_x <- paste0(immundata::imd_schema("repertoire"), ".x") + rep_y <- paste0(immundata::imd_schema("repertoire"), ".y") + pairs <- idata$annotations |> + select(all_of(target_cols)) |> + inner_join(idata$annotations |> select(all_of(target_cols)), by = immundata::imd_schema("receptor")) |> + filter(!!rlang::sym(rep_x) < !!rlang::sym(rep_y)) |> + summarise(n = n(), .by = all_of(c(rep_x, rep_y))) |> + collect() + + # yes-yes, I know it is inefficient + for (rep_i in 1:(length(repertoire_ids) - 1)) { + for (rep_j in (rep_i + 1):length(repertoire_ids)) { + val <- pairs |> + filter(!!rlang::sym(rep_x) == rep_i, !!rlang::sym(rep_y) == rep_j) |> + pull(n) + + val <- if (length(val) == 0) 0 else val + + result_matrix[rep_i, rep_j] <- val + result_matrix[rep_j, rep_i] <- val + } + } + + result_matrix +} + +#' @description `airr_public_intersection` - number of **shared receptors** between +#' each pair of repertoires (intersection size). Handy for quick overlap heatmaps, +#' QC of replicate similarity, or spotting donor-shared "public" clonotypes. +#' +#' @return +#' +#' ## `airr_public_intersection` +#' A **symmetric numeric matrix** where rows/columns are `repertoire_id` and each +#' cell is the count of shared unique receptors. The diagonal contains per-repertoire +#' richness (total unique receptors). Row/column names are repertoire IDs. +#' +#' @examples +#' # +#' # airr_public_intersection +#' # +#' \dontrun{ +#' m_pub <- airr_public_intersection(immdata) +#' } +#' +#' @rdname airr_public +#' @concept Public indices +#' @export +airr_public_intersection <- register_immunarch_method(airr_public_intersection_impl, "airr_public", "intersection", ) + + +#' @keywords internal +airr_public_jaccard_impl <- function(idata) { + receptor_id_col <- immundata::imd_schema("receptor") + repertoire_id_col <- immundata::imd_schema("repertoire") + repertoire_ids <- idata$repertoires |> + pull({{ repertoire_id_col }}) |> + unique() |> + sort() + + rep_labels <- idata$repertoires |> + dplyr::select(dplyr::all_of(c(repertoire_id_col, idata$schema_repertoire))) |> + tidyr::unite(".label", dplyr::all_of(idata$schema_repertoire), sep = "|", na.rm = TRUE) |> + dplyr::transmute(rep_id = .data[[repertoire_id_col]], label = .data$.label) + + result_matrix <- matrix(NA, nrow = length(repertoire_ids), ncol = length(repertoire_ids), dimnames = list(rep_labels$label, rep_labels$label)) + + target_cols <- c(immundata::imd_schema("receptor"), immundata::imd_schema("repertoire")) + rep_x <- paste0(immundata::imd_schema("repertoire"), ".x") + rep_y <- paste0(immundata::imd_schema("repertoire"), ".y") + pairs <- idata$annotations |> + select(all_of(target_cols)) |> + inner_join(idata$annotations |> select(all_of(target_cols)), by = immundata::imd_schema("receptor")) |> + filter(!!rlang::sym(rep_x) < !!rlang::sym(rep_y)) |> + summarise(n = n(), .by = all_of(c(rep_x, rep_y))) |> + collect() + + # yes-yes, I know it is inefficient + for (rep_i in 1:(length(repertoire_ids) - 1)) { + for (rep_j in (rep_i + 1):length(repertoire_ids)) { + inter_val <- pairs |> + filter(!!rlang::sym(rep_x) == rep_i, !!rlang::sym(rep_y) == rep_j) |> + pull(n) + inter_val <- if (length(inter_val) == 0) 0 else inter_val + + size_i <- idata$repertoires |> + filter(!!rlang::sym(repertoire_id_col) == rep_i) |> + pull(immundata::imd_schema("n_receptors")) + size_j <- idata$repertoires |> + filter(!!rlang::sym(repertoire_id_col) == rep_j) |> + pull(immundata::imd_schema("n_receptors")) + + union_val <- size_i + size_j - inter_val + + val <- ifelse(union_val > 0, inter_val / union_val, NA_real_) + + result_matrix[rep_i, rep_j] <- val + result_matrix[rep_j, rep_i] <- val + } + } + + result_matrix +} + + +#' @description `airr_public_jaccard` - **Jaccard similarity** of receptor +#' sets between repertoires (\eqn{A \cap B}{A cap B} / \eqn{A \cup B}{A cup B}). Best when comparing cohorts with +#' different sizes to get a scale-invariant overlap score. +#' +#' @inheritParams im_common_args +#' +#' @return +#' +#' ## `airr_public_jaccard` +#' A **symmetric numeric matrix** where rows/columns are `repertoire_id` and each +#' cell is the Jaccard similarity in `[0, 1]`. The diagonal is `1`. Row/column +#' names are repertoire IDs. +#' +#' @examples +#' # +#' # airr_public_jaccard +#' # +#' \dontrun{ +#' m_jac <- airr_public_jaccard(immdata) +#' } +#' +#' @rdname airr_public +#' @concept Public indices +#' @export +airr_public_jaccard <- register_immunarch_method(airr_public_jaccard_impl, "airr_public", "jaccard") diff --git a/R/v1_public_vis.R b/R/v1_public_vis.R new file mode 100644 index 00000000..567873ac --- /dev/null +++ b/R/v1_public_vis.R @@ -0,0 +1,18 @@ +#' @keywords internal +vis_airr_public_intersection_impl <- make_dotplot( + title_default = "No. of public receptors", + size_default = "No. receptors", + fill_default = "No. receptors" +) + +register_immunarch_visualisation(vis_airr_public_intersection_impl, "airr_public", "intersection") + + +#' @keywords internal +vis_airr_public_jaccard_impl <- make_dotplot( + title_default = "Jaccard similarity index", + size_default = "Value", + fill_default = "Value" +) + +register_immunarch_visualisation(vis_airr_public_jaccard_impl, "airr_public", "jaccard") diff --git a/R/v1_airr_stats.R b/R/v1_stats_airr.R similarity index 96% rename from R/v1_airr_stats.R rename to R/v1_stats_airr.R index feac3bee..99cdaa19 100644 --- a/R/v1_airr_stats.R +++ b/R/v1_stats_airr.R @@ -18,8 +18,14 @@ #' @seealso [immundata::ImmunData] #' #' @examples +#' # Limit the number of threads used by the underlying DB for this session. +#' # Change this only if you know what you're doing (e.g., multi-user machines, shared CI/servers). +#' db_exec("SET threads TO 2") +#' #' # Load data +#' \dontrun{ #' immdata <- get_test_idata() |> agg_repertoires("Therapy") +#' } #' #' @name airr_stats #' @concept Key AIRR statistics @@ -90,7 +96,10 @@ airr_stats_chains_impl <- function(idata, locus_col = NA) { #' # #' # airr_stats_chains #' # +#' +#' \dontrun{ #' airr_stats_chains(immdata) +#' } #' #' @rdname airr_stats #' @concept Key AIRR statistics @@ -140,7 +149,10 @@ airr_stats_lengths_impl <- function(idata, seq_col = "cdr3_aa") { #' # #' # airr_stats_lengths #' # +#' +#' \dontrun{ #' airr_stats_lengths(immdata) +#' } #' #' @rdname airr_stats #' @concept Key AIRR statistics @@ -213,6 +225,8 @@ airr_stats_genes_impl <- function(idata, gene_col = "v_call", level = c("recepto #' # #' # airr_stats_genes #' # +#' +#' \dontrun{ #' # V gene usage by receptor count #' airr_stats_genes(immdata, gene_col = "v_call", level = "receptor") #' @@ -221,6 +235,7 @@ airr_stats_genes_impl <- function(idata, gene_col = "v_call", level = c("recepto #' #' # Split by locus (TRA/TRB/... if locus column exists) #' airr_stats_genes(immdata, gene_col = "v_call", level = "receptor", by = "locus") +#' } #' #' @rdname airr_stats #' @concept Key AIRR statistics diff --git a/R/v1_stats_vis.R b/R/v1_stats_vis.R new file mode 100644 index 00000000..ed87e1f4 --- /dev/null +++ b/R/v1_stats_vis.R @@ -0,0 +1,28 @@ +#' @keywords internal +vis_airr_stats_chains_impl <- make_dynam_col_plot( + y_default = "n_receptors", + title_default = "No. receptors per sample", + position = "dodge" +) + +register_immunarch_visualisation(vis_airr_stats_chains_impl, "airr_stats", "chains") + + +#' @keywords internal +vis_airr_stats_lengths_impl <- make_fixed_col_plot( + x_col = "seq_len", + y_col = "prop", + title = "CDR3 length distribution", xlab = "CDR3 length", ylab = "Proportion" +) + +register_immunarch_visualisation(vis_airr_stats_lengths_impl, "airr_stats", "lengths") + + +#' @keywords internal +vis_airr_stats_genes_impl <- make_dotplot( + title_default = "Gene usage", + size_default = "Proportion (all data)", + fill_default = "No. Receptors" +) + +register_immunarch_visualisation(vis_airr_stats_genes_impl, "airr_stats", "genes") diff --git a/R/zzz.R b/R/zzz.R index b9a94425..71cdd637 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -30,6 +30,40 @@ immunarch_v1_updates <- c( .onLoad <- function(libname, pkgname) { + # register_immunarch_visualisation(vis_airr_stats_lengths_impl, "airr_stats", "lengths") + # register_immunarch_visualisation(vis_airr_stats_chains_impl, "airr_stats", "chains") + # register_immunarch_visualisation(vis_airr_stats_genes_impl, "airr_stats", "genes") + # + # register_immunarch_visualisation( + # vis_airr_diversity_dxx_impl, + # "airr_diversity", + # "dxx" + # ) + # register_immunarch_visualisation( + # vis_airr_diversity_chao1_impl, + # "airr_diversity", + # "chao1" + # ) + # register_immunarch_visualisation( + # vis_airr_diversity_shannon_impl, + # "airr_diversity", + # "shannon" + # ) + # register_immunarch_visualisation( + # vis_airr_diversity_pielou_impl, + # "airr_diversity", + # "pielou" + # ) + # register_immunarch_visualisation( + # vis_airr_diversity_index_impl, + # "airr_diversity", + # "index" + # ) + # + # + # register_immunarch_visualisation(vis_airr_public_intersection_impl, "airr_public", "intersection") + # register_immunarch_visualisation(vis_airr_public_jaccard_impl, "airr_public", "jaccard") + op <- options() op.immunarch <- list( immunarch.autojoin = FALSE # default diff --git a/README.md b/README.md index 2acccc21..6a2c98b5 100644 --- a/README.md +++ b/README.md @@ -166,10 +166,11 @@ library(immunarch) immdata <- get_test_idata() |> agg_repertoires("Therapy") # In just 4 lines of code you get the essential AIRR statistics -airr_stats_genes(immdata, gene_col = "v_call") -airr_public_jaccard(immdata) +airr_stats_genes(immdata, gene_col = "v_call") |> vis() +airr_public_jaccard(immdata) |> vis() +airr_diversity_pielou(immdata) |> vis() +airr_diversity_chao1(immdata) |> vis() airr_clonality_prop(immdata) -airr_diversity_pielou(immdata) # Use your own data by reading sample files from the metadata file mdtable <- read_metadata("data/metadata.csv") diff --git a/_pkgdown.yml b/_pkgdown.yml index cb97fe46..0491da16 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -22,6 +22,7 @@ articles: subtitle: "Deprecated" desc: ~ contents: + - '`immunarch_threads`' - '`web_only_v0/introduction`' - '`web_only_v0/data`' - '`web_only_v0/v21_singlecell`' @@ -35,7 +36,6 @@ articles: - '`web_only_v0/v8_tracking`' - '`web_only_v0/v9_kmers`' - '`web_only_v0/v11_db`' - - '`web_only_v0/community`' - '`web_only_v0/repFilter_v3`' - '`web_only_v0/v10_prop`' - '`web_only_v0/BCRpipeline`' @@ -44,14 +44,14 @@ navbar: bg: dark type: dark structure: - left: [tutorial, articles, reference] + left: [tutorial, migration, articles, reference] right: [github] components: home: ~ news: ~ tutorial: text: "Immunarch v1.0" - href: https://immunomind.github.io/docs/tutorials/single-cell/ + href: https://immunomind.github.io/docs/tutorials/single_cell/ migration: text: "Migration Guide" href: https://immunomind.github.io/docs/tutorials/migration/ @@ -146,6 +146,7 @@ reference: - subtitle: Clonality - contents: - starts_with("airr_clonality") + - starts_with("annotate_clonality") - subtitle: Diversity - contents: @@ -164,6 +165,7 @@ reference: - -starts_with("airr_clonality") - -starts_with("airr_diversity") - -starts_with("airr_public") + - -starts_with("annotate_clonality") - title: Under Question, v0.9 -> v1.0 diff --git a/data/scdata.rda b/data/scdata.rda deleted file mode 100644 index 335c7c1b..00000000 Binary files a/data/scdata.rda and /dev/null differ diff --git a/man/airr_clonality.Rd b/man/airr_clonality.Rd index 4ee7aa34..e43e0895 100644 --- a/man/airr_clonality.Rd +++ b/man/airr_clonality.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/v1_airr_clonality.R +% Please edit documentation in R/v1_clonality_airr.R \name{airr_clonality} \alias{airr_clonality} \alias{airr_clonality_line} @@ -103,23 +103,35 @@ Each receptor is assigned to a named bin according to its \code{proportion} descending order; unmatched receptors fall into \code{"Ultra-rare"}. } \examples{ +# Limit the number of threads used by the underlying DB for this session. +# Change this only if you know what you're doing (e.g., multi-user machines, shared CI/servers). +db_exec("SET threads TO 1") + # Load data +\dontrun{ immdata <- get_test_idata() |> agg_repertoires("Therapy") +} # # airr_clonality_line # +\dontrun{ top_line <- airr_clonality_line(immdata, limit = 1000) +} # # airr_clonality_rank # +\dontrun{ rank_stat <- airr_clonality_rank(immdata, bins = c(10, 100)) +} # # airr_clonality_prop # +\dontrun{ prop_stat <- airr_clonality_prop(immdata) +} } \seealso{ diff --git a/man/airr_diversity.Rd b/man/airr_diversity.Rd index f6e7b710..8f49bba6 100644 --- a/man/airr_diversity.Rd +++ b/man/airr_diversity.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/v1_airr_diversity.R +% Please edit documentation in R/v1_diversity_airr.R \name{airr_diversity} \alias{airr_diversity} \alias{airr_diversity_dxx} @@ -166,39 +166,56 @@ emphasizes abundant receptors. Perfect when you want a \strong{diversity profile that tunes sensitivity to rare vs. abundant clonotypes. } \examples{ +# Limit the number of threads used by the underlying DB for this session. +# Change this only if you know what you're doing (e.g., multi-user machines, shared CI/servers). +db_exec("SET threads TO 1") # Load data +\dontrun{ immdata <- get_test_idata() |> agg_repertoires("Therapy") +} # # airr_diversity_dxx # +\dontrun{ d50 <- airr_diversity_dxx(immdata, perc = 50) d_multi <- airr_diversity_dxx(immdata, perc = c(20, 50, 80)) +} # # airr_diversity_chao1 # +\dontrun{ chao <- airr_diversity_chao1(immdata) +} # # airr_diversity_shannon # +\dontrun{ sh <- airr_diversity_shannon(immdata) +} # # airr_diversity_pielou # +\dontrun{ pj <- airr_diversity_pielou(immdata) +} # # airr_diversity_index # +\dontrun{ idx <- airr_diversity_index(immdata) +} # # airr_diversity_hill # +\dontrun{ hill <- airr_diversity_hill(immdata, q = c(0, 1, 2)) +} } \seealso{ diff --git a/man/airr_public.Rd b/man/airr_public.Rd index f6cde9c2..8e473962 100644 --- a/man/airr_public.Rd +++ b/man/airr_public.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/v1_airr_public.R +% Please edit documentation in R/v1_public_airr.R \name{airr_public} \alias{airr_public} \alias{airr_public_intersection} @@ -61,18 +61,25 @@ sets between repertoires (\eqn{A \cap B}{A cap B} / \eqn{A \cup B}{A cup B}). Be different sizes to get a scale-invariant overlap score. } \examples{ +# Limit the number of threads used by the underlying DB for this session. +# Change this only if you know what you're doing (e.g., multi-user machines, shared CI/servers). +db_exec("SET threads TO 1") # Load data immdata <- get_test_idata() |> agg_repertoires("Therapy") # # airr_public_intersection # +\dontrun{ m_pub <- airr_public_intersection(immdata) +} # # airr_public_jaccard # +\dontrun{ m_jac <- airr_public_jaccard(immdata) +} } \seealso{ diff --git a/man/airr_stats.Rd b/man/airr_stats.Rd index b3bba5b1..3c687f17 100644 --- a/man/airr_stats.Rd +++ b/man/airr_stats.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/v1_airr_stats.R +% Please edit documentation in R/v1_stats_airr.R \name{airr_stats} \alias{airr_stats} \alias{airr_stats_chains} @@ -121,22 +121,36 @@ cohort comparisons, flagging clonal expansions, and producing ML-ready features for repertoire-level ML tasks. } \examples{ +# Limit the number of threads used by the underlying DB for this session. +# Change this only if you know what you're doing (e.g., multi-user machines, shared CI/servers). +db_exec("SET threads TO 2") + # Load data +\dontrun{ immdata <- get_test_idata() |> agg_repertoires("Therapy") +} # # airr_stats_chains # + +\dontrun{ airr_stats_chains(immdata) +} # # airr_stats_lengths # + +\dontrun{ airr_stats_lengths(immdata) +} # # airr_stats_genes # + +\dontrun{ # V gene usage by receptor count airr_stats_genes(immdata, gene_col = "v_call", level = "receptor") @@ -145,6 +159,7 @@ airr_stats_genes(immdata, gene_col = "v_call", level = "barcode") # Split by locus (TRA/TRB/... if locus column exists) airr_stats_genes(immdata, gene_col = "v_call", level = "receptor", by = "locus") +} } \seealso{ diff --git a/man/annotate_clonality.Rd b/man/annotate_clonality.Rd index be815b2c..47ddf9ed 100644 --- a/man/annotate_clonality.Rd +++ b/man/annotate_clonality.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/v1_annotate_clonality.R +% Please edit documentation in R/v1_clonality_annotate.R \name{annotate_clonality} \alias{annotate_clonality} \alias{annotate_clonality_rank} diff --git a/man/im_common_args.Rd b/man/im_common_args.Rd index 247c712a..5333ccc6 100644 --- a/man/im_common_args.Rd +++ b/man/im_common_args.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/aaa-registry.R \name{im_common_args} \alias{im_common_args} -\title{Common arguments for immundata helpers} +\title{Common arguments for immunarch helpers} \usage{ im_common_args( autojoin = getOption("immundata.autojoin", TRUE), @@ -18,6 +18,6 @@ columns, and \code{value}; useful for visualizations) or \code{"wide"} (wide/unm with each row corresponding to a specific repertoire / pair of repertoires; useful for Machine Learning).} } \description{ -Common arguments for immundata helpers +Common arguments for immunarch helpers } \keyword{internal} diff --git a/man/inc_overlap.Rd b/man/inc_overlap.Rd index 743ccaec..b4f0deb5 100644 --- a/man/inc_overlap.Rd +++ b/man/inc_overlap.Rd @@ -57,8 +57,10 @@ List with overlap matrices. For reference please look up https://www.pnas.org/content/111/16/5980 (Fig. 4). } \examples{ +\dontrun{ data(immdata) ov <- repOverlap(immdata$data, "inc+overlap", .step = 100, .verbose.inc = FALSE, .verbose = FALSE) vis(ov) } +} \concept{overlap} diff --git a/man/repFilter.Rd b/man/repFilter.Rd index d136490c..6e7895ac 100644 --- a/man/repFilter.Rd +++ b/man/repFilter.Rd @@ -61,28 +61,4 @@ Default value: 'exact'. \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } -\examples{ -data(immdata) - -# Select samples with status "MS" -repFilter(immdata, "by.meta", list(Status = include("MS"))) - -# Select samples without status "MS" -repFilter(immdata, "by.meta", list(Status = exclude("MS"))) - -# Select samples from lanes "A" and "B" with age > 15 -repFilter(immdata, "by.meta", list(Lane = include("A", "B"), Age = morethan(15))) - -# Select samples that are not from lanes "A" and "B" -repFilter(immdata, "by.meta", list(Lane = exclude("A", "B"))) - -# Select samples with a number of clonotypes from 1000 to 5000 -repFilter(immdata, "by.repertoire", list(n_clonotypes = interval(1000, 5000))) - -# Select clonotypes in all samples with alpha chains -repFilter(immdata, "by.clonotype", - list(V.name = include("AV"), J.name = include("AJ")), - .match = "substring" -) -} \concept{filters} diff --git a/man/scdata.Rd b/man/scdata.Rd deleted file mode 100644 index b395e3bd..00000000 --- a/man/scdata.Rd +++ /dev/null @@ -1,26 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/v0_data_docs.R -\docType{data} -\name{scdata} -\alias{scdata} -\title{Paired chain immune repertoire dataset} -\format{ -A list of four elements: -"data" is a list with data frames with clonotype tables. -"meta" is a metadata table. -"bc_patients" is a list of barcodes corresponding to specific patients. -"bc_clusters" is a list of barcodes corresponding to specific cell clusters. -\describe{ -\item{data}{List of immune repertoire data frames.} -\item{meta}{Metadata} -... -} -} -\usage{ -scdata -} -\description{ -A dataset with paired chain IG data for testing and examplatory purposes. -} -\concept{data} -\keyword{datasets} diff --git a/man/vis.Rd b/man/vis.Rd index 22f92818..3fcd2ca6 100644 --- a/man/vis.Rd +++ b/man/vis.Rd @@ -74,6 +74,7 @@ Additionaly, we provide a wrapper functions for visualisations of common data ty } } \examples{ +\dontrun{ # Load the test data data(immdata) @@ -87,7 +88,7 @@ vis(gu) dv <- repDiversity(immdata$data) vis(dv) } +} \seealso{ \link{fixVis} for precise manipulation of plots. } -\concept{vis} diff --git a/man/vis.clonal_family.Rd b/man/vis.clonal_family.Rd index dcdcc33d..b6692274 100644 --- a/man/vis.clonal_family.Rd +++ b/man/vis.clonal_family.Rd @@ -18,6 +18,7 @@ A ggraph object. \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ +\dontrun{ data(bcrdata) bcr_data <- bcrdata$data @@ -28,4 +29,5 @@ clonal_family <- bcr_data \%>\% repClonalFamily(.threads = 1, .nofail = TRUE) \%>\% vis() } +} \concept{phylip} diff --git a/man/vis.clonal_family_tree.Rd b/man/vis.clonal_family_tree.Rd index d88d3feb..2b9ab689 100644 --- a/man/vis.clonal_family_tree.Rd +++ b/man/vis.clonal_family_tree.Rd @@ -18,6 +18,7 @@ A ggraph object. \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ +\dontrun{ data(bcrdata) bcr_data <- bcrdata$data @@ -33,4 +34,5 @@ if (!("step_failure_ignored" \%in\% class(clonal_family))) { vis(clonal_family[["full_clones"]][["TreeStats"]][[2]]) } } +} \concept{phylip} diff --git a/man/vis.immunr_chao1.Rd b/man/vis.immunr_chao1.Rd index 8f8f9384..c8667aa2 100644 --- a/man/vis.immunr_chao1.Rd +++ b/man/vis.immunr_chao1.Rd @@ -71,10 +71,12 @@ P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/H You can execute the command \code{?p.adjust} in the R console to see more. } \examples{ +\dontrun{ data(immdata) dv <- repDiversity(immdata$data, "chao1") vis(dv) } +} \seealso{ \link{repDiversity} \link{vis} } diff --git a/man/vis.immunr_clonal_prop.Rd b/man/vis.immunr_clonal_prop.Rd index 7834b015..ea88dfed 100644 --- a/man/vis.immunr_clonal_prop.Rd +++ b/man/vis.immunr_clonal_prop.Rd @@ -68,6 +68,7 @@ P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/H You can execute the command \code{?p.adjust} in the R console to see more. } \examples{ +\dontrun{ data(immdata) clp <- repClonality(immdata$data, "clonal.prop") vis(clp) @@ -76,6 +77,7 @@ hom <- repClonality(immdata$data, "homeo") # Remove p values and points from the plot vis(hom, .by = "Status", .meta = immdata$meta, .test = FALSE, .points = FALSE) } +} \seealso{ \link{repClonality} \link{vis} } diff --git a/man/vis.immunr_dynamics.Rd b/man/vis.immunr_dynamics.Rd index 668ff6e6..9c13d477 100644 --- a/man/vis.immunr_dynamics.Rd +++ b/man/vis.immunr_dynamics.Rd @@ -25,6 +25,7 @@ A ggplot2 object. \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ +\dontrun{ # Load an example data that comes with immunarch data(immdata) @@ -72,4 +73,5 @@ immdata$meta$Sample[sample_order] # And finally, we visualise the data: vis(tc, .order = sample_order) } +} \concept{dynamics} diff --git a/man/vis.immunr_exp_vol.Rd b/man/vis.immunr_exp_vol.Rd index b8e54b15..b2c75f55 100644 --- a/man/vis.immunr_exp_vol.Rd +++ b/man/vis.immunr_exp_vol.Rd @@ -68,12 +68,14 @@ P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/H You can execute the command \code{?p.adjust} in the R console to see more. } \examples{ +\dontrun{ data(immdata) repExplore(immdata$data, "volume") \%>\% vis() repExplore(immdata$data, "count") \%>\% vis() repExplore(immdata$data, "len") \%>\% vis() repExplore(immdata$data, "clones") \%>\% vis() } +} \seealso{ \link{repExplore} \link{vis} } diff --git a/man/vis.immunr_gene_usage.Rd b/man/vis.immunr_gene_usage.Rd index c252977b..941cc409 100644 --- a/man/vis.immunr_gene_usage.Rd +++ b/man/vis.immunr_gene_usage.Rd @@ -35,6 +35,7 @@ A ggplot2 object, pheatmap or circlize object. Visualise distributions of genes using heatmaps or other plots. } \examples{ +\dontrun{ data(immdata) gu <- geneUsage(immdata$data[[1]]) @@ -44,6 +45,7 @@ gu <- geneUsage(immdata$data) vis(gu, .by = "Status", .meta = immdata$meta) vis(gu, "box", .by = "Status", .meta = immdata$meta) } +} \seealso{ \link{geneUsage} } diff --git a/man/vis.immunr_hclust.Rd b/man/vis.immunr_hclust.Rd index 0499dc8f..a0e3d6f6 100644 --- a/man/vis.immunr_hclust.Rd +++ b/man/vis.immunr_hclust.Rd @@ -27,10 +27,12 @@ Visualisation of the results of hierarchical clustering. For other clustering visualisations see \link{vis.immunr_kmeans}. } \examples{ +\dontrun{ data(immdata) ov <- repOverlap(immdata$data) repOverlapAnalysis(ov, "mds+hclust") \%>\% vis() } +} \seealso{ \link{vis}, \link{repOverlapAnalysis}, \link{geneUsageAnalysis} } diff --git a/man/vis.immunr_inc_overlap.Rd b/man/vis.immunr_inc_overlap.Rd index a065de3d..f9a7ced9 100644 --- a/man/vis.immunr_inc_overlap.Rd +++ b/man/vis.immunr_inc_overlap.Rd @@ -24,11 +24,13 @@ A ggplot2 object. \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ +\dontrun{ data(immdata) tmp <- repOverlap(immdata$data[1:4], "inc+overlap", .verbose.inc = FALSE, .verbose = FALSE) vis(tmp, .target = 1) vis(tmp, .grid = TRUE) } +} \seealso{ \link{repOverlap} } diff --git a/man/vis.immunr_kmeans.Rd b/man/vis.immunr_kmeans.Rd index ce090099..1063518b 100644 --- a/man/vis.immunr_kmeans.Rd +++ b/man/vis.immunr_kmeans.Rd @@ -45,10 +45,12 @@ Visualisation of the results of K-means and DBSCAN clustering. For hierarhical clustering visualisations see \link{vis.immunr_hclust}. } \examples{ +\dontrun{ data(immdata) ov <- repOverlap(immdata$data) repOverlapAnalysis(ov, "mds+kmeans") \%>\% vis() } +} \seealso{ \link{vis}, \link{repOverlapAnalysis}, \link{geneUsageAnalysis} } diff --git a/man/vis.immunr_kmer_table.Rd b/man/vis.immunr_kmer_table.Rd index f9d513a2..295616c0 100644 --- a/man/vis.immunr_kmer_table.Rd +++ b/man/vis.immunr_kmer_table.Rd @@ -32,6 +32,7 @@ A ggplot2 object. Plot a distribution (bar plot) of the most frequent kmers in a data. } \examples{ +\dontrun{ # Load necessary data and package. data(immdata) # Get 5-mers. @@ -41,6 +42,7 @@ p1 <- vis(imm.km, .position = "stack") p2 <- vis(imm.km, .position = "fill") p1 + p2 } +} \seealso{ \code{get.kmers} } diff --git a/man/vis.immunr_mds.Rd b/man/vis.immunr_mds.Rd index ba731d9e..7a2a4c85 100644 --- a/man/vis.immunr_mds.Rd +++ b/man/vis.immunr_mds.Rd @@ -62,8 +62,10 @@ Other visualisation methods: } } \examples{ +\dontrun{ data(immdata) ov <- repOverlap(immdata$data) repOverlapAnalysis(ov, "mds") \%>\% vis() } +} \concept{post_analysis} diff --git a/man/vis.immunr_ov_matrix.Rd b/man/vis.immunr_ov_matrix.Rd index 1982dfcc..f6a521ac 100644 --- a/man/vis.immunr_ov_matrix.Rd +++ b/man/vis.immunr_ov_matrix.Rd @@ -34,6 +34,7 @@ Visualises matrices with overlap values or gene usage distances among samples. For details see the links below. } \examples{ +\dontrun{ data(immdata) ov <- repOverlap(immdata$data) vis(ov) @@ -41,4 +42,5 @@ vis(ov, "heatmap") vis(ov, "heatmap2") vis(ov, "circos") } +} \concept{overlap} diff --git a/man/vis.immunr_public_repertoire.Rd b/man/vis.immunr_public_repertoire.Rd index 691a3477..9f64254e 100644 --- a/man/vis.immunr_public_repertoire.Rd +++ b/man/vis.immunr_public_repertoire.Rd @@ -27,6 +27,7 @@ A ggplot2 object. \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ +\dontrun{ data(immdata) immdata$data <- lapply(immdata$data, head, 300) pr <- pubRep(immdata$data, .verbose = FALSE) @@ -35,4 +36,5 @@ vis(pr, "freq", .type = "none") vis(pr, "clonotypes", 1, 2) } +} \concept{pubrep} diff --git a/man/vis.immunr_public_statistics.Rd b/man/vis.immunr_public_statistics.Rd index c794b99e..ff9ac4e5 100644 --- a/man/vis.immunr_public_statistics.Rd +++ b/man/vis.immunr_public_statistics.Rd @@ -20,9 +20,11 @@ A ggplot2 object. Visualise public clonotype frequencies. } \examples{ +\dontrun{ data(immdata) immdata$data <- lapply(immdata$data, head, 2000) pr <- pubRep(immdata$data, .verbose = FALSE) pubRepStatistics(pr) \%>\% vis() } +} \concept{pubrep} diff --git a/man/vis_bar.Rd b/man/vis_bar.Rd index 10e33e93..e9761f49 100644 --- a/man/vis_bar.Rd +++ b/man/vis_bar.Rd @@ -83,6 +83,8 @@ A ggplot2 object. \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ +\dontrun{ vis_bar(data.frame(Sample = c("A", "B", "C"), Value = c(1, 2, 3))) } +} \concept{vis} diff --git a/man/vis_box.Rd b/man/vis_box.Rd index 8619aa74..7bc595ca 100644 --- a/man/vis_box.Rd +++ b/man/vis_box.Rd @@ -74,8 +74,10 @@ A ggplot2 object. Visualisation of distributions using ggplot2-based boxplots. } \examples{ +\dontrun{ vis_box(data.frame(Sample = sample(c("A", "B", "C"), 100, TRUE), Value = rnorm(100)), .melt = FALSE) } +} \seealso{ \link{vis.immunr_gene_usage}, \link{geneUsage} } diff --git a/man/vis_circos.Rd b/man/vis_circos.Rd index 590fa615..80206ef8 100644 --- a/man/vis_circos.Rd +++ b/man/vis_circos.Rd @@ -23,10 +23,12 @@ Visualise matrices with the \link[circlize:chordDiagram]{circlize::chordDiagram} from the circlize package. } \examples{ +\dontrun{ data(immdata) ov <- repOverlap(immdata$data) vis(ov, .plot = "circos") } +} \seealso{ \link{vis}, \link{repOverlap}. } diff --git a/man/vis_heatmap.Rd b/man/vis_heatmap.Rd index 412becb5..9d9e5c6b 100644 --- a/man/vis_heatmap.Rd +++ b/man/vis_heatmap.Rd @@ -63,12 +63,14 @@ Fast and easy visualisations of matrices or data frames with functions based on the ggplot2 package. } \examples{ +\dontrun{ data(immdata) ov <- repOverlap(immdata$data) vis_heatmap(ov) gu <- geneUsage(immdata$data, "hs.trbj") vis_heatmap(gu) } +} \seealso{ \link{vis}, \link{repOverlap}. } diff --git a/man/vis_heatmap2.Rd b/man/vis_heatmap2.Rd index 87fa2055..2259ee7d 100644 --- a/man/vis_heatmap2.Rd +++ b/man/vis_heatmap2.Rd @@ -39,10 +39,12 @@ Visualise matrices with the functions based on the \link[pheatmap:pheatmap]{phea package with minimum amount of arguments. } \examples{ +\dontrun{ data(immdata) ov <- repOverlap(immdata$data) vis_heatmap2(ov) } +} \seealso{ \link{vis}, \link{repOverlap} } diff --git a/man/vis_hist.Rd b/man/vis_hist.Rd index 900d95fe..4b712461 100644 --- a/man/vis_hist.Rd +++ b/man/vis_hist.Rd @@ -83,6 +83,7 @@ P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/H You can execute the command \code{?p.adjust} in the R console to see more. } \examples{ +\dontrun{ data(immdata) imm_gu <- geneUsage(immdata$data[[1]]) vis(imm_gu, @@ -95,6 +96,7 @@ vis(imm_gu, theme(axis.text.x = element_text(angle = 75, vjust = 1)) ) } +} \seealso{ \link{vis.immunr_gene_usage}, \link{geneUsage} } diff --git a/man/vis_immunr_kmer_profile_main.Rd b/man/vis_immunr_kmer_profile_main.Rd index 8362f4f4..5a2a3a74 100644 --- a/man/vis_immunr_kmer_profile_main.Rd +++ b/man/vis_immunr_kmer_profile_main.Rd @@ -25,9 +25,11 @@ A ggplot2 object. #' \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ +\dontrun{ data(immdata) getKmers(immdata$data[[1]], 5) \%>\% kmer_profile() \%>\% vis("seqlogo") } +} \concept{kmers} diff --git a/man/vis_public_clonotypes.Rd b/man/vis_public_clonotypes.Rd index f774d4c5..3c547f28 100644 --- a/man/vis_public_clonotypes.Rd +++ b/man/vis_public_clonotypes.Rd @@ -53,10 +53,12 @@ A ggplot2 object. Visualise correlation of public clonotype frequencies in pairs of repertoires. } \examples{ +\dontrun{ data(immdata) pr <- pubRep(immdata$data, .verbose = FALSE) vis(pr, "clonotypes", 1, 2) } +} \seealso{ \link{pubRep}, \link{vis.immunr_public_repertoire} } diff --git a/man/vis_public_frequencies.Rd b/man/vis_public_frequencies.Rd index 8cbdbc01..e9013bca 100644 --- a/man/vis_public_frequencies.Rd +++ b/man/vis_public_frequencies.Rd @@ -39,6 +39,7 @@ A ggplot2 object. Visualise public clonotype frequencies. } \examples{ +\dontrun{ data(immdata) immdata$data <- lapply(immdata$data, head, 500) pr <- pubRep(immdata$data, .verbose = FALSE) @@ -47,4 +48,5 @@ vis(pr, "freq", .type = "none") vis(pr, "freq", .type = "mean") vis(pr, "freq", .by = "Status", .meta = immdata$meta) } +} \concept{pubrep} diff --git a/man/vis_textlogo.Rd b/man/vis_textlogo.Rd index 1bc76907..f8477c30 100644 --- a/man/vis_textlogo.Rd +++ b/man/vis_textlogo.Rd @@ -37,6 +37,7 @@ are no big differences between occurences of amino acids in the motif. with clear differences in their occurrences. } \examples{ +\dontrun{ data(immdata) kmers <- getKmers(immdata$data[[1]], 5) ppm <- kmer_profile(kmers, "prob") @@ -47,6 +48,7 @@ d <- kmer_profile(c("CASLL", "CASSQ", "CASGL")) vis_textlogo(d) vis_seqlogo(d) } +} \seealso{ \link{getKmers}, \link{kmer_profile} } diff --git a/tests/testthat.R b/tests/testthat.R index 0d8bc1e3..f9c7dfa6 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,3 +1,11 @@ +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/testing-design.html#sec-tests-files-overview +# * https://testthat.r-lib.org/articles/special-files.html + library(testthat) library(immunarch) diff --git a/tests/testthat/test-vis_airr_stats_length.R b/tests/testthat/test-vis_airr_stats_length.R new file mode 100644 index 00000000..2d85f4c9 --- /dev/null +++ b/tests/testthat/test-vis_airr_stats_length.R @@ -0,0 +1,31 @@ +test_that("vis() for airr_stats_lengths builds plots", { + skip_on_cran() + skip_if_not_installed("ggplot2") + + idata <- get_test_immundata() |> agg_repertoires("Therapy") + res_lengths <- idata |> airr_stats_lengths() + p1 <- vis(res_lengths, fill = "Therapy") + expect_s3_class(p1, "ggplot") + expect_error(suppressWarnings(ggplot2::ggplot_build(p1)), NA) + + p2 <- vis(res_lengths, facet = "Therapy") + expect_s3_class(p2, "ggplot") + expect_error(suppressWarnings(ggplot2::ggplot_build(p2)), NA) + expect_true(inherits(p2$facet, "FacetWrap")) + + p3 <- vis(res_lengths, fill = "Therapy", facet = "imd_repertoire_id") + expect_s3_class(p3, "ggplot") + expect_error(suppressWarnings(ggplot2::ggplot_build(p3)), NA) + expect_true(inherits(p3$facet, "FacetWrap")) + + p4 <- vis(res_lengths, fill = "seq_len", facet = "imd_repertoire_id") + expect_s3_class(p4, "ggplot") + expect_error(suppressWarnings(ggplot2::ggplot_build(p4)), NA) + expect_true(inherits(p4$facet, "FacetWrap")) + + if (!all(c("Therapy", "imd_repertoire_id") %in% names(res_lengths))) skip("Required columns missing") + p5 <- vis(res_lengths, fill = "seq_len", facet = c("Therapy", "imd_repertoire_id")) + expect_s3_class(p5, "ggplot") + expect_error(suppressWarnings(ggplot2::ggplot_build(p5)), NA) + expect_true(inherits(p5$facet, "FacetGrid")) +}) diff --git a/vignettes/immunarch.Rmd b/vignettes/immunarch.Rmd index 4617b0f2..2657f776 100644 --- a/vignettes/immunarch.Rmd +++ b/vignettes/immunarch.Rmd @@ -1,14 +1,12 @@ --- -title: "immunarch" -output: html_document +title: "Immunarch overview" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Immunarch overview} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} --- - - # 🧬 immunarch – Multi-modal immune repertoire analysis in R `immunarch` brings a comprehensive analytics toolkit to build reproducible analysis pipelines for Adaptive Immune Receptor Repertoire (AIRR) data with a particular focus on designing personalized immunotherapies and vaccines. Key features are: diff --git a/vignettes/immunarch_threads.Rmd b/vignettes/immunarch_threads.Rmd new file mode 100644 index 00000000..a73b3f2c --- /dev/null +++ b/vignettes/immunarch_threads.Rmd @@ -0,0 +1,45 @@ +--- +title: "Limit the number of threads used by immunarch" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Limit the number of threads used by immunarch} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +## What is happening under the hood? + +`immunarch` uses `immundata`, which uses `duckplyr`, which runs queries in **DuckDB**. It is quite a journey from the data to your plots. + +DuckDB can use many CPU cores by default to run faster, but sometimes you want to limit this. + +## Why limit threads? + +* On shared machines (servers, CI), many threads can slow down other users. +* In tutorials, fewer threads make examples more predictable and easier to reproduce. +* Lower threads = lower CPU load (but slower queries). + +## How to limit the number of threads + +Put this near the start of your tutorial/script: + +```{r eval=FALSE} +# Limit the number of CPU threads used by DuckDB in this R session +duckplyr::db_exec("SET threads TO 1") +``` + +Change later (example: use 4 threads) or reset to default: + +```{r eval=FALSE} +duckplyr::db_exec("SET threads TO 4") # use 4 threads +# or, if supported in your environment: +duckplyr::db_exec("RESET threads") # back to DuckDB default +``` + +## References + +* `duckplyr` - `dplyr` powered by DuckDB: https://duckplyr.tidyverse.org (CRAN: duckplyr). + +* `db_exec` - https://duckplyr.tidyverse.org/reference/db_exec.html + +* **DuckDB** configuration docs - thread/memory settings and more: https://duckdb.org/docs/stable/configuration/overview.html diff --git a/vignettes/web_only_v0/community.Rmd b/vignettes/web_only_v0/community.Rmd deleted file mode 100644 index 2a5751a0..00000000 --- a/vignettes/web_only_v0/community.Rmd +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "ImmunoMinds Community" -output: html_document ---- - -```{r setup, include=FALSE} -knitr::opts_chunk$set(echo = TRUE) -``` - -## R Markdown - -This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see . - -When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this: - -```{r cars} -summary(cars) -``` - -## Including Plots - -You can also embed plots, for example: - -```{r pressure, echo=FALSE} -plot(pressure) -``` - -Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot. diff --git a/vignettes/web_only_v0/repFilter_v3.Rmd b/vignettes/web_only_v0/repFilter_v3.Rmd index 1d964c51..3805cdfb 100644 --- a/vignettes/web_only_v0/repFilter_v3.Rmd +++ b/vignettes/web_only_v0/repFilter_v3.Rmd @@ -27,6 +27,7 @@ output: # knitr::knit_hooks$set(optipng = knitr::hook_optipng) # knitr::opts_chunk$set(optipng = '-o7') +knitr::opts_chunk$set(eval = FALSE) knitr::opts_chunk$set(echo = TRUE) knitr::opts_chunk$set(fig.align = "center") knitr::opts_chunk$set(fig.width = 12)