diff --git a/.Rbuildignore b/.Rbuildignore index cc6e0d44..2b42f0ac 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -22,3 +22,9 @@ ^.github$ ^.RDataFiles$ ^.idea$ +^cran-comments\.md$ +^vignettes/*_files$ +^wip-.* +^vignettes/articles$ +^vignettes/.quarto$ +^CRAN-SUBMISSION$ diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml new file mode 100644 index 00000000..bfc9f4db --- /dev/null +++ b/.github/workflows/pkgdown.yaml @@ -0,0 +1,49 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + release: + types: [published] + workflow_dispatch: + +name: pkgdown.yaml + +permissions: read-all + +jobs: + pkgdown: + runs-on: ubuntu-latest + # Only restrict concurrency for non-PR jobs + concurrency: + group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::pkgdown, local::. + needs: website + + - name: Build site + run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) + shell: Rscript {0} + + - name: Deploy to GitHub pages 🚀 + if: github.event_name != 'pull_request' + uses: JamesIves/github-pages-deploy-action@v4.5.0 + with: + clean: false + branch: gh-pages + folder: docs diff --git a/.gitignore b/.gitignore index 28c2b28c..a10450c6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ src/*.dll docs/* .idea/* vignettes/web_only/*.html +immunr.Rproj +cran-comments.md +wip-* diff --git a/DESCRIPTION b/DESCRIPTION index eeca17eb..0123266b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,80 +1,63 @@ Package: immunarch Type: Package -Title: Bioinformatics Analysis of T-Cell and B-Cell Immune Repertoires -Version: 0.9.1 +Title: Multi-Modal Immune Repertoire Analytics for Immunotherapy and Vaccine Design in R +Version: 0.10.0 Authors@R: c( - person("Vadim I.", "Nazarov", , "support@immunomind.io", c("aut", "cre")), + person("Vadim I.", "Nazarov", , "support@immunomind.com", role = c("aut", "cre"), + comment = c(ORCID = "0000-0003-3659-2709")), person("Vasily O.", "Tsvetkov", , role = "aut"), - person("Siarhei", "Fiadziushchanka", , role = "aut"), - person("Eugene", "Rumynskiy", , role = "aut"), person("Aleksandr A.", "Popov", , role = "aut"), - person("Ivan", "Balashov", , role = "aut"), - person("Maria", "Samokhina", , role = "aut"), - person("Anna", "Lorenc", , role = "ctb"), - person("Daniel J.", "Moore", , role = "ctb"), - person("Victor", "Greiff", , role = "ctb"), - person("ImmunoMind", role = c("cph", "fnd")) + person("Ivan", "Balashov", , role = "aut") ) -Contact: support@immunomind.io -Description: A comprehensive framework for bioinformatics exploratory analysis of bulk and single-cell - T-cell receptor and antibody repertoires. It provides seamless data loading, analysis and - visualisation for AIRR (Adaptive Immune Receptor Repertoire) data, both bulk immunosequencing (RepSeq) - and single-cell sequencing (scRNAseq). Immunarch implements most of the widely used AIRR analysis methods, - such as: clonality analysis, estimation of repertoire similarities in distribution of clonotypes - and gene segments, repertoire diversity analysis, annotation of clonotypes using external immune receptor - databases and clonotype tracking in vaccination and cancer studies. A successor to our - previously published 'tcR' immunoinformatics package (Nazarov 2015) . -License: Apache License (== 2.0) -URL: https://immunarch.com/, https://github.com/immunomind/immunarch +Contact: support@immunomind.com +Description: A comprehensive analytics framework for building reproducible pipelines on T-cell and B-cell immune receptor repertoire data. + Delivers multi-modal immune profiling (bulk, single-cell, CITE-seq/AbSeq, spatial, immunogenicity data), + feature engineering (ML-ready feature tables and matrices), and biomarker discovery workflows + (cohort comparisons, longitudinal tracking, repertoire similarity, enrichment). + Provides a user-friendly interface to widely used AIRR methods — + clonality/diversity, V(D)J usage, similarity, annotation, tracking, and many more. + 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 BugReports: https://github.com/immunomind/immunarch/issues +Depends: + R (>= 4.1.0), + ggplot2 (>= 3.1.0), + immundata (>= 0.0.5), + patchwork Imports: - factoextra (>= 1.0.4), - fpc, - UpSetR (>= 1.4.0), + dplyr, + dtplyr (>= 1.0.0), + data.table (>= 1.12.6), + cli, pheatmap (>= 1.0.12), - ggrepel (>= 0.8.0), reshape2 (>= 1.4.2), circlize, - MASS (>= 7.3), - Rtsne (>= 0.15), - readxl (>= 1.3.1), - shiny (>= 1.4.0), - shinythemes, airr, - ggseqlogo, - ggalluvial (>= 0.10.0), Rcpp (>= 1.0), magrittr, methods, scales, - ggpubr (>= 0.2), - rlang (>= 0.4), + rlang, plyr, - purrr, stringdist, - jsonlite, readr, stringr, tibble, tidyselect, tidyr, - igraph, ape, doParallel, rlist, utils, glue, - phangorn, - uuid, - stringi, - ggraph -Depends: - R (>= 4.0.0), - ggplot2 (>= 3.1.0), - dplyr (>= 0.8.0), - dtplyr (>= 1.0.0), - data.table (>= 1.12.6), - patchwork + checkmate, + duckplyr (>= 1.1.0), + dbplyr, + lifecycle, + purrr, + stats LinkingTo: Rcpp Suggests: knitr (>= 1.8), @@ -82,9 +65,28 @@ Suggests: testthat (>= 2.1.0), pkgdown (>= 0.1.0), assertthat, - rmarkdown -VignetteBuilder: knitr + rmarkdown, + factoextra (>= 1.0.4), + fpc, + ggpubr (>= 0.2), + ggraph, + ggseqlogo, + igraph, + phangorn, + ggalluvial (>= 0.10.0), + UpSetR (>= 1.4.0), + ggrepel (>= 0.8.0), + shiny (>= 1.4.0), + shinythemes, + quarto, + MASS (>= 7.3), + Rtsne (>= 0.15) +VignetteBuilder: + knitr, + quarto Encoding: UTF-8 -RoxygenNote: 7.3.1 +RoxygenNote: 7.3.3 LazyData: true LazyDataCompression: xz +Roxygen: list(markdown = TRUE) +Config/Needs/website: rmarkdown diff --git a/NAMESPACE b/NAMESPACE index db875b92..e9f001af 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -46,6 +46,22 @@ S3method(vis,immunr_spectr_nogene) S3method(vis,immunr_top_prop) S3method(vis,immunr_tsne) S3method(vis,step_failure_ignored) +export(airr_clonality_line) +export(airr_clonality_prop) +export(airr_clonality_rank) +export(airr_diversity_chao1) +export(airr_diversity_dxx) +export(airr_diversity_hill) +export(airr_diversity_index) +export(airr_diversity_pielou) +export(airr_diversity_shannon) +export(airr_public_intersection) +export(airr_public_jaccard) +export(airr_stats_chains) +export(airr_stats_genes) +export(airr_stats_lengths) +export(annotate_clonality_prop) +export(annotate_clonality_rank) export(apply_asymm) export(apply_symm) export(bunch_translate) @@ -61,6 +77,7 @@ export(geneUsageAnalysis) export(gene_stats) export(getKmers) export(get_genes) +export(get_immunarch_news) export(immunr_dbscan) export(immunr_hclust) export(immunr_kmeans) @@ -75,6 +92,7 @@ export(js_div) export(kl_div) export(kmer_profile) export(lessthan) +export(list_immunarch_news) export(morethan) export(noncoding) export(outofframes) @@ -120,12 +138,27 @@ export(vis_textlogo) import(ggplot2) importFrom(Rcpp,cppFunction) importFrom(Rcpp,sourceCpp) -importFrom(UpSetR,fromExpression) -importFrom(UpSetR,upset) importFrom(ape,as.DNAbin) importFrom(ape,clustal) importFrom(ape,read.tree) +importFrom(checkmate,assert_character) +importFrom(checkmate,assert_choice) +importFrom(checkmate,assert_data_frame) +importFrom(checkmate,assert_logical) +importFrom(checkmate,assert_numeric) +importFrom(checkmate,assert_r6) importFrom(circlize,chordDiagram) +importFrom(cli,cli_alert_info) +importFrom(cli,cli_alert_success) +importFrom(cli,cli_alert_warning) +importFrom(cli,cli_bullets) +importFrom(cli,cli_end) +importFrom(cli,cli_h1) +importFrom(cli,cli_inform) +importFrom(cli,cli_par) +importFrom(cli,cli_text) +importFrom(cli,spark_line) +importFrom(cli,start_app) importFrom(data.table,":=") importFrom(data.table,as.data.table) importFrom(data.table,data.table) @@ -136,12 +169,16 @@ importFrom(data.table,setDF) importFrom(data.table,setDT) importFrom(data.table,setcolorder) importFrom(data.table,setnames) +importFrom(dbplyr,sql) importFrom(doParallel,registerDoParallel) importFrom(doParallel,stopImplicitCluster) +importFrom(dplyr,all_of) importFrom(dplyr,arrange) importFrom(dplyr,as_tibble) importFrom(dplyr,collect) +importFrom(dplyr,compute) importFrom(dplyr,contains) +importFrom(dplyr,count) importFrom(dplyr,cur_group_id) importFrom(dplyr,desc) importFrom(dplyr,distinct) @@ -152,50 +189,38 @@ importFrom(dplyr,group_by) importFrom(dplyr,group_by_at) importFrom(dplyr,group_keys) importFrom(dplyr,group_map) +importFrom(dplyr,intersect) importFrom(dplyr,left_join) importFrom(dplyr,mutate) importFrom(dplyr,n) importFrom(dplyr,one_of) importFrom(dplyr,pull) importFrom(dplyr,rename) +importFrom(dplyr,right_join) importFrom(dplyr,row_number) importFrom(dplyr,rowwise) importFrom(dplyr,select) importFrom(dplyr,select_) importFrom(dplyr,select_if) +importFrom(dplyr,slice_head) importFrom(dplyr,summarise) importFrom(dplyr,tally) importFrom(dplyr,top_n) +importFrom(dplyr,transmute) importFrom(dplyr,ungroup) +importFrom(dplyr,union) +importFrom(dplyr,union_all) importFrom(dtplyr,lazy_dt) -importFrom(factoextra,fviz_cluster) -importFrom(factoextra,fviz_dend) -importFrom(factoextra,fviz_nbclust) -importFrom(factoextra,fviz_pca_ind) -importFrom(factoextra,hcut) -importFrom(fpc,dbscan) -importFrom(ggalluvial,geom_flow) -importFrom(ggalluvial,geom_stratum) -importFrom(ggpubr,compare_means) -importFrom(ggpubr,geom_signif) -importFrom(ggpubr,ggscatter) -importFrom(ggpubr,rotate_x_text) -importFrom(ggpubr,stat_compare_means) -importFrom(ggpubr,theme_pubr) -importFrom(ggraph,geom_edge_diagonal) -importFrom(ggraph,geom_node_point) -importFrom(ggraph,ggraph) -importFrom(ggraph,theme_graph) -importFrom(ggseqlogo,geom_logo) -importFrom(ggseqlogo,theme_logo) +importFrom(duckplyr,as_duckdb_tibble) +importFrom(duckplyr,as_tbl) importFrom(glue,glue) importFrom(grDevices,colorRampPalette) importFrom(graphics,plot) importFrom(grid,gpar) importFrom(grid,rectGrob) -importFrom(igraph,clusters) -importFrom(igraph,graph_from_data_frame) -importFrom(jsonlite,read_json) +importFrom(immundata,ImmunData) +importFrom(immundata,imd_schema) +importFrom(lifecycle,deprecated) importFrom(magrittr,"%<>%") importFrom(magrittr,"%>%") importFrom(magrittr,extract2) @@ -209,23 +234,15 @@ importFrom(parallel,parApply) importFrom(parallel,stopCluster) importFrom(patchwork,plot_annotation) importFrom(patchwork,wrap_plots) -importFrom(phangorn,write.phyDat) importFrom(pheatmap,pheatmap) importFrom(plyr,.) importFrom(plyr,adply) importFrom(plyr,dlply) importFrom(plyr,mapvalues) -importFrom(purrr,imap) -importFrom(purrr,map) -importFrom(purrr,map2) -importFrom(purrr,map2_chr) importFrom(purrr,map2_df) -importFrom(purrr,map2_lgl) importFrom(purrr,map_chr) importFrom(purrr,map_df) importFrom(purrr,map_dfr) -importFrom(purrr,map_lgl) -importFrom(purrr,pmap) importFrom(readr,col_character) importFrom(readr,col_double) importFrom(readr,col_guess) @@ -236,38 +253,18 @@ importFrom(readr,read_csv) importFrom(readr,read_delim) importFrom(readr,read_tsv) importFrom(readr,write_lines) -importFrom(readxl,read_xlsx) importFrom(reshape2,melt) +importFrom(rlang,.data) +importFrom(rlang,.env) +importFrom(rlang,as_function) +importFrom(rlang,global_env) +importFrom(rlang,inject) +importFrom(rlang,is_logical) +importFrom(rlang,is_true) +importFrom(rlang,set_names) importFrom(rlang,sym) importFrom(rlist,list.remove) importFrom(scales,percent) -importFrom(shiny,actionButton) -importFrom(shiny,br) -importFrom(shiny,checkboxInput) -importFrom(shiny,downloadButton) -importFrom(shiny,downloadHandler) -importFrom(shiny,fluidPage) -importFrom(shiny,mainPanel) -importFrom(shiny,observe) -importFrom(shiny,observeEvent) -importFrom(shiny,plotOutput) -importFrom(shiny,renderPlot) -importFrom(shiny,renderText) -importFrom(shiny,renderUI) -importFrom(shiny,selectInput) -importFrom(shiny,sidebarLayout) -importFrom(shiny,sidebarPanel) -importFrom(shiny,sliderInput) -importFrom(shiny,splitLayout) -importFrom(shiny,tabPanel) -importFrom(shiny,tabsetPanel) -importFrom(shiny,textAreaInput) -importFrom(shiny,textInput) -importFrom(shiny,textOutput) -importFrom(shiny,titlePanel) -importFrom(shiny,uiOutput) -importFrom(shiny,updateSliderInput) -importFrom(shinythemes,shinytheme) importFrom(stats,as.dist) importFrom(stats,cmdscale) importFrom(stats,cor) @@ -278,8 +275,8 @@ importFrom(stats,na.omit) importFrom(stats,prcomp) importFrom(stats,qnorm) importFrom(stats,rmultinom) +importFrom(stats,runif) importFrom(stringdist,stringdistmatrix) -importFrom(stringi,stri_replace_all_fixed) importFrom(stringr,boundary) importFrom(stringr,fixed) importFrom(stringr,str_c) @@ -298,17 +295,19 @@ importFrom(stringr,str_sub) importFrom(stringr,str_trim) importFrom(tibble,rownames_to_column) importFrom(tibble,tibble) +importFrom(tidyr,as_tibble) importFrom(tidyr,drop_na) importFrom(tidyr,unite) importFrom(tidyr,unnest) importFrom(tidyselect,all_of) importFrom(tidyselect,any_of) importFrom(tidyselect,starts_with) +importFrom(utils,adist) importFrom(utils,capture.output) +importFrom(utils,globalVariables) importFrom(utils,packageVersion) importFrom(utils,read.table) importFrom(utils,setTxtProgressBar) importFrom(utils,tail) importFrom(utils,txtProgressBar) -importFrom(uuid,UUIDgenerate) useDynLib(immunarch, .registration = TRUE) diff --git a/R/aaa-registry.R b/R/aaa-registry.R new file mode 100644 index 00000000..10c6f1bf --- /dev/null +++ b/R/aaa-registry.R @@ -0,0 +1,184 @@ +IMMUNARCH_METHOD_REGISTRY <- new.env(parent = emptyenv()) + + +#' Common arguments for immundata 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)`. +#' @param format String. One of `"long"` ("long" tibble with `imd_repertoire_id`, facet +#' columns, and `value`; useful for visualizations) or `"wide"` (wide/unmelted table of features, +#' with each row corresponding to a specific repertoire / pair of repertoires; useful for Machine Learning). +im_common_args <- function( + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide")) {} # nocov + + +im_method <- function(core, family, name, required_cols = NULL, need_repertoires = TRUE) { + checkmate::assert_function(core, args = c("idata")) + checkmate::assert_string(family) + checkmate::assert_string(name) + checkmate::assert_logical(need_repertoires) + + core_fmls <- formals(core) + if (!"idata" %in% names(core_fmls)) { + cli::cli_abort("Core method must declare an {.code idata} argument.") + } + if (any(c("autojoin", "format", "features") %in% names(core_fmls))) { + cli::cli_abort("Core method must not declare {.code autojoin}, {.code format}, or {.code features}.") + } + + # required_cols = columns expected in idata$annotations + if (!is.null(required_cols)) { + checkmate::assert_character(required_cols, any.missing = FALSE) + } + + wrapper <- function() { } + formals(wrapper) <- c( + core_fmls, + formals(im_common_args) + ) + environment(wrapper) <- environment() + + body(wrapper) <- substitute( + { + format <- match.arg(format) + checkmate::assert_r6(idata, "ImmunData") + + if (need_repertoires) { + if (is.null(idata$schema_repertoire)) { + cli::cli_abort("Repertoire aggregation is needed for this function. Run {.code ?agg_repertoires} for more info.") + } + } + + # For each argument name in `required_cols`, fetch its runtime value + # and ensure the referenced columns exist in idata$annotations. + if (length(required_cols)) { + ann_cols <- colnames(idata$annotations) + for (.arg in required_cols) { + .val <- get(.arg, inherits = TRUE) + + # Just in case + if (is.null(.val) || (length(.val) == 1 && is.na(.val))) next + + # Allow symbols or character vectors + if (rlang::is_symbol(.val)) { + .val <- rlang::as_string(.val) + } + + if (!is.character(.val)) { + cli::cli_abort("Argument {.code {.arg}} must be a character (column name) or character vector; got a {.code {class(.val)[1]}}.") + } + + missing <- setdiff(.val, ann_cols) + if (length(missing)) { + suggest <- function(x, pool, n = 3) { + if (!length(pool)) { + return(character()) + } + d <- utils::adist(x, pool) + pool[order(d)][seq_len(min(n, length(pool)))] + } + hints <- unique(unlist(lapply(missing, suggest, pool = ann_cols, n = 3))) + cli::cli_abort("Passed column name(s) [{.code {missing}}] is not in the input ImmunData. Did you mean [{.code {hints}}]?") + } + } + } + + # Call core with its own formals + .core_args <- mget(names(core_fmls), inherits = TRUE) + out <- do.call(core, .core_args) + + # Autojoin: join repertoire metadata if requested and applicable (!) + if (isTRUE(autojoin) && !is.null(idata$repertoires)) { + rep_col <- immundata::imd_schema("repertoire") + if (!is.null(rep_col) && rep_col %in% names(out)) { + out <- dplyr::left_join(out, idata$repertoires |> select(all_of(c(rep_col, idata$schema_repertoire))), by = rep_col) + } + } + + out + }, + list(core = core, core_fmls = core_fmls, required_cols = required_cols) + ) + + wrapper +} + + +#' Register an Immunarch method (developer) +#' +#' `r lifecycle::badge("experimental")` +#' +#' Wrap a core implementation into a user-facing function and (optionally) +#' register it in the in-memory method registry. The wrapper **adds common +#' arguments** and **runs safety checks** so your core stays minimal. +#' +#' ## What your core must look like +#' * Signature: `function(idata, ...)` +#' * **Must not** declare `autojoin`, `format`, or `features` - these are added by the wrapper. +#' +#' ## What the wrapper adds +#' * Common args from `im_common_args()`: `autojoin`, `format`, `features` +#' (with `autojoin` default controlled by `getOption("immunarch.autojoin", FALSE)`). +#' * Validates `idata` is an [immundata::ImmunData] object. +#' * Ensures all columns in `required_cols` exist in `idata$annotations`. +#' * If `autojoin = TRUE` and the result is a data frame containing the repertoire id +#' column (`immundata::imd_schema("repertoire")`), joins repertoire metadata from +#' `idata$repertoires`. +#' +#' @param core A function with signature `function(idata, ...)`. This is your core +#' implementation; it must accept an `ImmunData` as the first argument and **must not** +#' declare `autojoin`, `format`, or `features`. +#' @param family String. Method family name used for dispatch (e.g., `"airr_stats"`). +#' @param name String. Method name within the family (e.g., `"lengths"`). +#' @param register_family Logical (default `TRUE`). If `TRUE`, attempts to create/ensure +#' the family environment by calling `register_airr_family()` when available. +#' @param required_cols Character vector of column names that **must** be present in +#' `idata$annotations`. Use this to declare the minimal input schema your core needs. +#' @param need_repertoires Logical. Use this to declare the necessity of having aggregated +#' repertoires. +#' +#' @return A **function** - the user-facing wrapper around `core`. Typical usage is to +#' assign it to the exported symbol of the method, e.g.: +#' `airr_stats_lengths <- register_immunarch_method(...)`. +#' +#' @examples +#' \dontrun{ +#' # Minimal core implementation (must accept `idata`) +#' airr_stats_lengths_impl <- function(idata, seq_col = "cdr3_aa") { +#' dplyr::as_tibble(idata$annotations) |> +#' dplyr::distinct(.data[[immundata::imd_schema("repertoire")]], .data[[seq_col]]) |> +#' dplyr::mutate(seq_len = nchar(.data[[seq_col]])) |> +#' dplyr::count(.data[[immundata::imd_schema("repertoire")]], seq_len, name = "n") +#' } +#' +#' # Register and expose a user-facing function +#' airr_stats_lengths <- register_immunarch_method( +#' core = airr_stats_lengths_impl, +#' family = "airr_stats", +#' name = "lengths", +#' required_cols = c("cdr3_aa", immundata::imd_schema("repertoire")) +#' ) +#' +#' # Optional: call via dispatcher +#' # make_airr_dispatcher("airr_stats")(idata = immdata, method = "lengths") +#' } +#' +#' @keywords internal +register_immunarch_method <- function(core, family, name, register_family = TRUE, required_cols = NULL, need_repertoires = TRUE) { + fn <- im_method(core, family, name, required_cols = required_cols, need_repertoires = need_repertoires) + + if (isTRUE(register_family) && exists("register_airr_family", mode = "function", inherits = TRUE)) { + try(register_airr_family(family), silent = TRUE) + } + + if (exists("register_airr_method", mode = "function", inherits = TRUE)) { + try(register_airr_method( + family_name = family, + method_name = name, + fn = fn + ), silent = TRUE) + } + + fn +} diff --git a/R/clustering.R b/R/clustering.R deleted file mode 100644 index 497c71e7..00000000 --- a/R/clustering.R +++ /dev/null @@ -1,93 +0,0 @@ -#' Clustering of objects or distance matrices -#' -#' @concept post_analysis -#' -#' @aliases immunr_hclust immunr_kmeans immunr_dbscan -#' -#' @importFrom fpc dbscan -#' @importFrom factoextra hcut fviz_nbclust -#' @importFrom stats kmeans as.dist cmdscale dist -#' -#' @description Clusters the data with one of the following methods: -#' -#' - \code{immunr_hclust} clusters the data using the hierarchical clustering from \link[factoextra]{hcut}; -#' -#' - \code{immunr_kmeans} clusters the data using the K-means algorithm from \link{kmeans}; -#' -#' - \code{immunr_dbscan} clusters the data using the DBSCAN algorithm from \link[fpc]{dbscan}. -#' -#' @usage -#' immunr_hclust(.data, .k = 2, .k.max = nrow(.data) - 1, .method = "complete", .dist = TRUE) -#' -#' immunr_kmeans(.data, .k = 2, .k.max = as.integer(sqrt(nrow(.data))) + 1, -#' .method = c("silhouette", "gap_stat")) -#' -#' immunr_dbscan(.data, .eps, .dist = TRUE) -#' -#' @param .data Matrix or data frame with features, distance matrix or output from \link{repOverlapAnalysis} or \link{geneUsageAnalysis} functions. -#' -#' @param .k The number of clusters to create, defined as \code{k} to \link[factoextra]{hcut} or as \code{centers} to \link{kmeans}. -#' -#' @param .k.max Limits the maximum number of clusters. It is passed as \code{k.max} to \link{fviz_nbclust} for \code{immunr_hclust} and \code{immunr_kmeans}. -#' -#' @param .eps Local radius for expanding clusters, minimal distance between points to expand clusters. Passed as \code{eps} to \link[fpc]{dbscan}. -#' -#' @param .method Passed to \link[factoextra]{hcut} or as \link{fviz_nbclust}. -#' -#' In case of \link[factoextra]{hcut} the agglomeration method is going to be used (argument \code{hc_method}). -#' -#' In case of \link{fviz_nbclust} it is the method to be used for estimating the optimal number of clusters (argument \code{method}). -#' -#' @param .dist If TRUE then ".data" is expected to be a distance matrix. If FALSE then the euclidean distance is computed for the input objects. -#' -#' @return -#' \code{immunr_hclust} - list with two elements. The first element is an output from \link{hcut}. -#' The second element is an output from \link{fviz_nbclust} -#' -#' \code{immunr_kmeans} - list with three elements. The first element is an output from \link{kmeans}. -#' The second element is an output from \link{fviz_nbclust}. -#' The third element is the input dataset \code{.data}. -#' -#' \code{immunr_dbscan} - list with two elements. The first element is an output from \link{dbscan}. -#' The second element is the input dataset \code{.data}. -#' -#' @examples -#' data(immdata) -#' gu <- geneUsage(immdata$data, .norm = TRUE) -#' immunr_hclust(t(as.matrix(gu[, -1])), .dist = FALSE) -#' -#' gu[is.na(gu)] <- 0 -#' immunr_kmeans(t(as.matrix(gu[, -1]))) -#' @export immunr_hclust immunr_kmeans immunr_dbscan -immunr_hclust <- function(.data, .k = 2, .k.max = nrow(.data) - 1, .method = "complete", .dist = TRUE) { - if (.dist) { - dist_mat <- as.dist(.data) - } else { - dist_mat <- dist(.data) - } - res <- list( - hcut = add_class(hcut(dist_mat, k = .k, hc_method = .method), "immunr_hcut"), - nbclust = add_class(fviz_nbclust(.data, hcut, k.max = .k.max), "immunr_nbclust") - ) - add_class(res, "immunr_hclust") -} - -immunr_kmeans <- function(.data, .k = 2, .k.max = as.integer(sqrt(nrow(.data))) + 1, .method = c("silhouette", "gap_stat")) { - res <- list( - kmeans = add_class(kmeans(.data, .k), "immunr_kmeans"), - nbclust = add_class(fviz_nbclust(.data, kmeans, k.max = .k.max, .method[1]), "immunr_nbclust"), - data = .data - ) - add_class(res, "immunr_kmeans") -} - -immunr_dbscan <- function(.data, .eps, .dist = TRUE) { - if (.dist) { - .data <- as.dist(.data) - method <- "dist" - } else { - method <- "hybrid" - } - res <- list(dbscan = fpc::dbscan(.data, eps = .eps, method = method), data = .data) - add_class(res, "immunr_dbscan") -} diff --git a/R/globals.R b/R/globals.R new file mode 100644 index 00000000..468d578a --- /dev/null +++ b/R/globals.R @@ -0,0 +1,16 @@ +utils::globalVariables(c( + "index", + "richness", + "shannon", + "dd", + "counts", + "annotate_immundata", + "ch", + "clonal_prop_bin", + "clonal_rank_bin", + "prop" +)) + +#' @keywords internal +#' @importFrom rlang as_function inject global_env is_logical is_true set_names .data .env +NULL diff --git a/R/immunarch-package.R b/R/immunarch-package.R index bd1d6689..0d1915b5 100644 --- a/R/immunarch-package.R +++ b/R/immunarch-package.R @@ -1,5 +1,62 @@ ## usethis namespace: start +#' @importFrom checkmate assert_character +#' @importFrom checkmate assert_choice +#' @importFrom checkmate assert_data_frame +#' @importFrom checkmate assert_logical +#' @importFrom checkmate assert_numeric +#' @importFrom checkmate assert_r6 +#' @importFrom cli cli_alert_info +#' @importFrom cli cli_alert_success +#' @importFrom cli cli_alert_warning +#' @importFrom cli cli_bullets +#' @importFrom cli cli_end +#' @importFrom cli cli_h1 +#' @importFrom cli cli_inform +#' @importFrom cli cli_par +#' @importFrom cli cli_text +#' @importFrom cli spark_line +#' @importFrom cli start_app +#' @importFrom dbplyr sql +#' @importFrom dplyr all_of +#' @importFrom dplyr arrange +#' @importFrom dplyr compute +#' @importFrom dplyr count +#' @importFrom dplyr distinct +#' @importFrom dplyr filter +#' @importFrom dplyr intersect +#' @importFrom dplyr left_join +#' @importFrom dplyr mutate +#' @importFrom dplyr n +#' @importFrom dplyr pull +#' @importFrom dplyr right_join +#' @importFrom dplyr select +#' @importFrom dplyr slice_head +#' @importFrom dplyr summarise +#' @importFrom dplyr transmute +#' @importFrom dplyr union +#' @importFrom dplyr union_all +#' @importFrom duckplyr as_duckdb_tibble +#' @importFrom duckplyr as_tbl +#' @importFrom immundata imd_schema +#' @importFrom immundata ImmunData +#' @importFrom lifecycle deprecated +#' @importFrom purrr map_df +#' @importFrom purrr map_dfr +#' @importFrom purrr map2_df #' @importFrom Rcpp sourceCpp +#' @importFrom rlang .data +#' @importFrom rlang .env +#' @importFrom rlang as_function +#' @importFrom rlang global_env +#' @importFrom rlang inject +#' @importFrom rlang is_logical +#' @importFrom rlang is_true +#' @importFrom rlang set_names +#' @importFrom rlang sym +#' @importFrom stats runif +#' @importFrom tidyr as_tibble +#' @importFrom utils adist +#' @importFrom utils globalVariables #' @useDynLib immunarch, .registration = TRUE ## usethis namespace: end NULL diff --git a/R/immunarch-remaster.R b/R/immunarch-remaster.R deleted file mode 100644 index 27bb962c..00000000 --- a/R/immunarch-remaster.R +++ /dev/null @@ -1,25 +0,0 @@ -# .check_immundata <- function (.object) { -# if (!is.instance(.object, "ImmunData")) { -# stop("Error: the input object is not of class ImmunData. Immunarch works on ImmunData only. Helpful manual: ...") -# } -# } -# -# .repertoire_overlap <- function (.data, .method, .verbose = TRUE, ...) { -# check_immundata(.data) -# } -# -# .gene_usage <- function (.data, .gene, .type, .use_counts, .norm, .gene_vec) { -# -# } -# -# .repertoire_diversity <- function (.data, .method, .verbose = TRUE, ...) { -# -# } -# -# .track_clonotypes <- function () { -# -# } -# -# .public_repertoire <- function () { -# -# } diff --git a/R/import-standalone-purrr.R b/R/import-standalone-purrr.R new file mode 100644 index 00000000..4ec36e12 --- /dev/null +++ b/R/import-standalone-purrr.R @@ -0,0 +1,244 @@ +# Standalone file: do not edit by hand +# Source: +# ---------------------------------------------------------------------- +# +# --- +# repo: r-lib/rlang +# file: standalone-purrr.R +# last-updated: 2023-02-23 +# license: https://unlicense.org +# imports: rlang +# --- +# +# This file provides a minimal shim to provide a purrr-like API on top of +# base R functions. They are not drop-in replacements but allow a similar style +# of programming. +# +# ## Changelog +# +# 2023-02-23: +# * Added `list_c()` +# +# 2022-06-07: +# * `transpose()` is now more consistent with purrr when inner names +# are not congruent (#1346). +# +# 2021-12-15: +# * `transpose()` now supports empty lists. +# +# 2021-05-21: +# * Fixed "object `x` not found" error in `imap()` (@mgirlich) +# +# 2020-04-14: +# * Removed `pluck*()` functions +# * Removed `*_cpl()` functions +# * Used `as_function()` to allow use of `~` +# * Used `.` prefix for helpers +# +# nocov start + +map <- function(.x, .f, ...) { + .f <- as_function(.f, env = global_env()) + lapply(.x, .f, ...) +} +walk <- function(.x, .f, ...) { + map(.x, .f, ...) + invisible(.x) +} + +map_lgl <- function(.x, .f, ...) { + .rlang_purrr_map_mold(.x, .f, logical(1), ...) +} +map_int <- function(.x, .f, ...) { + .rlang_purrr_map_mold(.x, .f, integer(1), ...) +} +map_dbl <- function(.x, .f, ...) { + .rlang_purrr_map_mold(.x, .f, double(1), ...) +} +map_chr <- function(.x, .f, ...) { + .rlang_purrr_map_mold(.x, .f, character(1), ...) +} +.rlang_purrr_map_mold <- function(.x, .f, .mold, ...) { + .f <- as_function(.f, env = global_env()) + out <- vapply(.x, .f, .mold, ..., USE.NAMES = FALSE) + names(out) <- names(.x) + out +} + +map2 <- function(.x, .y, .f, ...) { + .f <- as_function(.f, env = global_env()) + out <- mapply(.f, .x, .y, MoreArgs = list(...), SIMPLIFY = FALSE) + if (length(out) == length(.x)) { + set_names(out, names(.x)) + } else { + set_names(out, NULL) + } +} +map2_lgl <- function(.x, .y, .f, ...) { + as.vector(map2(.x, .y, .f, ...), "logical") +} +map2_int <- function(.x, .y, .f, ...) { + as.vector(map2(.x, .y, .f, ...), "integer") +} +map2_dbl <- function(.x, .y, .f, ...) { + as.vector(map2(.x, .y, .f, ...), "double") +} +map2_chr <- function(.x, .y, .f, ...) { + as.vector(map2(.x, .y, .f, ...), "character") +} +imap <- function(.x, .f, ...) { + map2(.x, names(.x) %||% seq_along(.x), .f, ...) +} + +pmap <- function(.l, .f, ...) { + .f <- as.function(.f) + args <- .rlang_purrr_args_recycle(.l) + do.call("mapply", c( + FUN = list(quote(.f)), + args, MoreArgs = quote(list(...)), + SIMPLIFY = FALSE, USE.NAMES = FALSE + )) +} +.rlang_purrr_args_recycle <- function(args) { + lengths <- map_int(args, length) + n <- max(lengths) + + stopifnot(all(lengths == 1L | lengths == n)) + to_recycle <- lengths == 1L + args[to_recycle] <- map(args[to_recycle], function(x) rep.int(x, n)) + + args +} + +keep <- function(.x, .f, ...) { + .x[.rlang_purrr_probe(.x, .f, ...)] +} +discard <- function(.x, .p, ...) { + sel <- .rlang_purrr_probe(.x, .p, ...) + .x[is.na(sel) | !sel] +} +map_if <- function(.x, .p, .f, ...) { + matches <- .rlang_purrr_probe(.x, .p) + .x[matches] <- map(.x[matches], .f, ...) + .x +} +.rlang_purrr_probe <- function(.x, .p, ...) { + if (is_logical(.p)) { + stopifnot(length(.p) == length(.x)) + .p + } else { + .p <- as_function(.p, env = global_env()) + map_lgl(.x, .p, ...) + } +} + +compact <- function(.x) { + Filter(length, .x) +} + +transpose <- function(.l) { + if (!length(.l)) { + return(.l) + } + + inner_names <- names(.l[[1]]) + + if (is.null(inner_names)) { + fields <- seq_along(.l[[1]]) + } else { + fields <- set_names(inner_names) + .l <- map(.l, function(x) { + if (is.null(names(x))) { + set_names(x, inner_names) + } else { + x + } + }) + } + + # This way missing fields are subsetted as `NULL` instead of causing + # an error + .l <- map(.l, as.list) + + map(fields, function(i) { + map(.l, .subset2, i) + }) +} + +every <- function(.x, .p, ...) { + .p <- as_function(.p, env = global_env()) + + for (i in seq_along(.x)) { + if (!rlang::is_true(.p(.x[[i]], ...))) { + return(FALSE) + } + } + TRUE +} +some <- function(.x, .p, ...) { + .p <- as_function(.p, env = global_env()) + + for (i in seq_along(.x)) { + if (rlang::is_true(.p(.x[[i]], ...))) { + return(TRUE) + } + } + FALSE +} +negate <- function(.p) { + .p <- as_function(.p, env = global_env()) + function(...) !.p(...) +} + +reduce <- function(.x, .f, ..., .init) { + f <- function(x, y) .f(x, y, ...) + Reduce(f, .x, init = .init) +} +reduce_right <- function(.x, .f, ..., .init) { + f <- function(x, y) .f(y, x, ...) + Reduce(f, .x, init = .init, right = TRUE) +} +accumulate <- function(.x, .f, ..., .init) { + f <- function(x, y) .f(x, y, ...) + Reduce(f, .x, init = .init, accumulate = TRUE) +} +accumulate_right <- function(.x, .f, ..., .init) { + f <- function(x, y) .f(y, x, ...) + Reduce(f, .x, init = .init, right = TRUE, accumulate = TRUE) +} + +detect <- function(.x, .f, ..., .right = FALSE, .p = is_true) { + .p <- as_function(.p, env = global_env()) + .f <- as_function(.f, env = global_env()) + + for (i in .rlang_purrr_index(.x, .right)) { + if (.p(.f(.x[[i]], ...))) { + return(.x[[i]]) + } + } + NULL +} +detect_index <- function(.x, .f, ..., .right = FALSE, .p = is_true) { + .p <- as_function(.p, env = global_env()) + .f <- as_function(.f, env = global_env()) + + for (i in .rlang_purrr_index(.x, .right)) { + if (.p(.f(.x[[i]], ...))) { + return(i) + } + } + 0L +} +.rlang_purrr_index <- function(x, right = FALSE) { + idx <- seq_along(x) + if (right) { + idx <- rev(idx) + } + idx +} + +list_c <- function(x) { + inject(c(!!!x)) +} + +# nocov end diff --git a/R/align_lineage.R b/R/v0_align_lineage.R similarity index 95% rename from R/align_lineage.R rename to R/v0_align_lineage.R index a38ecdee..27bd1293 100644 --- a/R/align_lineage.R +++ b/R/v0_align_lineage.R @@ -7,13 +7,16 @@ #' @importFrom magrittr %>% %<>% extract2 #' @importFrom stringr str_extract_all str_sub str_length boundary #' @importFrom plyr dlply . -#' @importFrom purrr map_dfr #' @importFrom rlist list.remove #' @importFrom ape as.DNAbin clustal #' @importFrom doParallel registerDoParallel stopImplicitCluster #' @importFrom parallel mclapply - -#' @description This function aligns all sequences (incliding germline) that belong to one clonal +#' +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' This function aligns all sequences (incliding germline) that belong to one clonal #' lineage and one cluster. After clustering and building the clonal lineage and germline, the next #' step is to analyze the degree of mutation and maturity of each clonal lineage. This allows for #' finding high mature cells and cells with a large number of offspring. The phylogenetic analysis @@ -24,7 +27,7 @@ #' #' repAlignLineage(.data, .min_lineage_sequences, .prepare_threads, .align_threads, .nofail) #' -#' @param .data The data to be processed. Can be \link{data.frame}, \link{data.table} +#' @param .data The data to be processed. Can be [data.frame], [data.table::data.table] #' or a list of these objects. #' #' @param .min_lineage_sequences If number of sequences in the same clonal lineage and the same @@ -36,7 +39,7 @@ #' #' @param .align_threads Number of threads for lineage alignment. #' -#' It must have columns in the immunarch compatible format \link{immunarch_data_format}, and also +#' It must have columns in the immunarch compatible format [immunarch_data_format], and also #' must contain 'Cluster' column, which is added by seqCluster() function, and 'Germline.sequence' #' column, which is added by repGermline() function. #' @@ -198,7 +201,7 @@ convert_results_to_df <- function(nested_results_list, alignments_list) { tibble(Sequences = .) df <- nested_results_list %>% lapply(rlist::list.remove, c("Alignment", "Sequences")) %>% - purrr::map_dfr(~.) %>% + map_dfr(~.) %>% cbind(alignments, sequences) return(df) } diff --git a/R/annotation.R b/R/v0_annotation.R similarity index 80% rename from R/annotation.R rename to R/v0_annotation.R index 2af67526..1c90d389 100644 --- a/R/annotation.R +++ b/R/v0_annotation.R @@ -5,22 +5,25 @@ if (getRversion() >= "2.15.1") { #' Load clonotype databases such as VDJDB and McPAS into the R workspace #' -#' @importFrom readxl read_xlsx #' @importFrom readr read_csv read_tsv #' #' @concept annotation #' -#' @description The function automatically detects the database format and loads it into R. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' The function automatically detects the database format and loads it into R. #' Additionally, the function provides a general query interface to databases that allows #' filtering by species, chain types (i.e., locus) and pathology (i.e., antigen species). #' #' Currently we support three popular databases: #' -#' VDJDB - \url{https://github.com/antigenomics/vdjdb-db} +#' VDJDB - #' -#' McPAS-TCR - \url{http://friedmanlab.weizmann.ac.il/McPAS-TCR/} +#' McPAS-TCR - #' -#' TBAdb from PIRD - \url{https://db.cngb.org/pird/} +#' TBAdb from PIRD - #' #' @param .path Character. A path to the database file, e.g., "/Users/researcher/Downloads/McPAS-TCR.csv". #' @@ -52,8 +55,8 @@ if (getRversion() >= "2.15.1") { #' @export dbLoad <- function(.path, .db, .species = NA, .chain = NA, .pathology = NA) { .db <- tolower(.db) - if (!(.db %in% c("vdjdb", "vdjdb-search", "mcpas", "mcpas-tcr", "pird", "tbadb"))) { - stop('Unknown .db argument. Please provide one of the following: "vdjdb", "vdjdb-search", "mcpas" or "tbadb"') + if (!(.db %in% c("vdjdb", "vdjdb-search", "mcpas", "mcpas-tcr", "pird"))) { + stop('Unknown .db argument. Please provide one of the following: "vdjdb", "vdjdb-search", "mcpas"') } if (.db == "vdjdb") { @@ -72,23 +75,6 @@ dbLoad <- function(.path, .db, .species = NA, .chain = NA, .pathology = NA) { db_file$Chain <- !is.na(db_file$CDR3.beta.aa) db_file$Chain <- "TRB" - } else if (.db == "tbadb") { - # ToDo: check for conflicting chains, such as TRB and BCR - sheet_index <- 1 - if (is.na(.chain)[1]) { - stop("TBAdb requires the .chain argument. Please specify it and try again.") - } - - chain_col <- paste0(.chain, collapse = "") - if (grepl("TRG", chain_col) || grepl("TRD", chain_col)) { - sheet_index <- 2 - } else if (grepl("IGH", chain_col) || grepl("IGL", chain_col) || grepl("IGK", chain_col)) { - sheet_index <- 3 - } - db_file <- read_xlsx(.path, sheet_index) - - db_file$Chain <- db_file$Locus - db_file$Pathology <- db_file$Disease.name } if (!is.na(.species)) { @@ -124,27 +110,31 @@ dbLoad <- function(.path, .db, .species = NA, .chain = NA, .pathology = NA) { } -#' Annotate clonotypes in immune repertoires using clonotype databases such as VDJDB and MCPAS +#' Annotate clonotypes in immune repertoires using clonotype databases (e.g., VDJDB, McPAS) #' #' @concept annotation #' -#' @description Annotate clonotypes using immune receptor databases with known condition-associated receptors. -#' Before using this function, you need to download database files first. -#' For more details see the tutorial \url{https://immunarch.com/articles/web_only/v11_db.html}. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Annotate clonotypes by matching them to known condition-associated immune receptors in a database. +#' Before using this function, you must download or load the relevant database files. +#' For more information, see the [online tutorial](https://immunarch.com/articles/web_only/v11_db.html). #' -#' @param .data The data to process. It can be a \link{data.frame}, a -#' \link{data.table}, or a list of these objects. +#' @param .data The data to process. It can be a [data.frame], a +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. #' -#' @param .db A data frame or a data table with an immune receptor database. See \link{dbLoad} on how to load databases into R. +#' @param .db A data frame or a data table with an immune receptor database. See [dbLoad] on how to load databases into R. #' #' @param .data.col Character vector. Vector of columns in the input repertoires to use for clonotype search. E.g., `"CDR3.aa"` or `c("CDR3.aa", "V.name")`. #' diff --git a/R/clonality.R b/R/v0_clonality.R similarity index 84% rename from R/clonality.R rename to R/v0_clonality.R index 9b104aa0..edd91bbb 100644 --- a/R/clonality.R +++ b/R/v0_clonality.R @@ -4,37 +4,41 @@ #' #' @aliases clonality clonal.prop clonal_proportion top_proportion rare_proportion clonal_space_homeostasis #' -#' @description \code{repClonality} function encompasses several methods to measure +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' `repClonality` function encompasses several methods to measure #' clonal proportions in a given repertoire. #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. #' -#' @param .method A String with one of the following options: \code{"clonal.prop"}, -#' \code{"homeo"}, \code{"top"} or \code{"rare"}. +#' @param .method A String with one of the following options: `"clonal.prop"`, +#' `"homeo"`, `"top"` or `"rare"`. #' -#' Set \code{"clonal.prop"} to compute clonal proportions or in other words -#' percentage of clonotypes required to occupy specified by \code{.perc} percent +#' Set `"clonal.prop"` to compute clonal proportions or in other words +#' percentage of clonotypes required to occupy specified by `.perc` percent #' of the total immune repertoire. #' -#' Set \code{"homeo"} to analyse relative abundance (also known as clonal space homeostasis), which is defined as the +#' Set `"homeo"` to analyse relative abundance (also known as clonal space homeostasis), which is defined as the #' proportion of repertoire occupied by clonal groups with specific abundances.. #' -#' Set \code{"top"} to estimate relative abundance for the groups of top clonotypes in -#' repertoire, e.g., ten most abundant clonotypes. Use \code{".head"} to define index intervals, +#' Set `"top"` to estimate relative abundance for the groups of top clonotypes in +#' repertoire, e.g., ten most abundant clonotypes. Use `".head"` to define index intervals, #' such as 10, 100 and so on. #' -#' Set \code{"rare"} to estimate relative abundance for the groups of rare clonotypes -#' with low counts. Use \code{".bound"} to define the threshold of clonotype groups. +#' Set `"rare"` to estimate relative abundance for the groups of rare clonotypes +#' with low counts. Use `".bound"` to define the threshold of clonotype groups. #' #' @param .perc A single numerical value ranging from 0 to 100. #' @param .clone.types A named numerical vector with the threshold of the half-closed @@ -60,7 +64,7 @@ #' #' Otherwise, it returns a numeric matrix with clonality statistics for all input repertoires. #' -#' @seealso \link{repDiversity} +#' @seealso [repDiversity] #' #' @examples #' # Load the data diff --git a/R/v0_clustering.R b/R/v0_clustering.R new file mode 100644 index 00000000..ba5476e2 --- /dev/null +++ b/R/v0_clustering.R @@ -0,0 +1,103 @@ +#' Clustering of objects or distance matrices +#' +#' @concept post_analysis +#' +#' @aliases immunr_hclust immunr_kmeans immunr_dbscan +#' +#' @importFrom stats kmeans as.dist cmdscale dist +#' +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Clusters the data with one of the following methods: +#' +#' - `immunr_hclust` clusters the data using the hierarchical clustering from [hcut][factoextra::hcut]; +#' +#' - `immunr_kmeans` clusters the data using the K-means algorithm from [kmeans]; +#' +#' - `immunr_dbscan` clusters the data using the DBSCAN algorithm from [dbscan][fpc::dbscan]. +#' +#' @usage +#' immunr_hclust(.data, .k = 2, .k.max = nrow(.data) - 1, .method = "complete", .dist = TRUE) +#' +#' immunr_kmeans(.data, .k = 2, .k.max = as.integer(sqrt(nrow(.data))) + 1, +#' .method = c("silhouette", "gap_stat")) +#' +#' immunr_dbscan(.data, .eps, .dist = TRUE) +#' +#' @param .data Matrix or data frame with features, distance matrix or output from [repOverlapAnalysis] or [geneUsageAnalysis] functions. +#' +#' @param .k The number of clusters to create, defined as `k` to [hcut][factoextra::hcut] or as `centers` to [kmeans]. +#' +#' @param .k.max Limits the maximum number of clusters. It is passed as `k.max` to [factoextra::fviz_nbclust] for `immunr_hclust` and `immunr_kmeans`. +#' +#' @param .eps Local radius for expanding clusters, minimal distance between points to expand clusters. Passed as `eps` to [dbscan][fpc::dbscan]. +#' +#' @param .method Passed to [factoextra::hcut] or as [factoextra::fviz_nbclust]. +#' +#' In case of [factoextra::hcut] the agglomeration method is going to be used (argument `hc_method`). +#' +#' In case of [factoextra::fviz_nbclust] it is the method to be used for estimating the optimal number of clusters (argument `method`). +#' +#' @param .dist If TRUE then ".data" is expected to be a distance matrix. If FALSE then the euclidean distance is computed for the input objects. +#' +#' @return +#' `immunr_hclust` - list with two elements. The first element is an output from [factoextra::hcut]. +#' The second element is an output from [factoextra::fviz_nbclust] +#' +#' `immunr_kmeans` - list with three elements. The first element is an output from [kmeans]. +#' The second element is an output from [factoextra::fviz_nbclust]. +#' The third element is the input dataset `.data`. +#' +#' `immunr_dbscan` - list with two elements. The first element is an output from [fpc::dbscan]. +#' The second element is the input dataset `.data`. +#' +#' @examples +#' data(immdata) +#' gu <- geneUsage(immdata$data, .norm = TRUE) +#' immunr_hclust(t(as.matrix(gu[, -1])), .dist = FALSE) +#' +#' gu[is.na(gu)] <- 0 +#' immunr_kmeans(t(as.matrix(gu[, -1]))) +#' @export immunr_hclust immunr_kmeans immunr_dbscan +immunr_hclust <- function(.data, .k = 2, .k.max = nrow(.data) - 1, .method = "complete", .dist = TRUE) { + + if (!requireNamespace("fpc", quietly = TRUE)) { + stop("Package 'fpc' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + if (!requireNamespace("factoextra", quietly = TRUE)) { + stop("Package 'factoextra' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + + if (.dist) { + dist_mat <- as.dist(.data) + } else { + dist_mat <- dist(.data) + } + res <- list( + hcut = add_class(factoextra::hcut(dist_mat, k = .k, hc_method = .method), "immunr_hcut"), + nbclust = add_class(factoextra::fviz_nbclust(.data, factoextra::hcut, k.max = .k.max), "immunr_nbclust") + ) + add_class(res, "immunr_hclust") +} + +immunr_kmeans <- function(.data, .k = 2, .k.max = as.integer(sqrt(nrow(.data))) + 1, .method = c("silhouette", "gap_stat")) { + res <- list( + kmeans = add_class(kmeans(.data, .k), "immunr_kmeans"), + nbclust = add_class(factoextra::fviz_nbclust(.data, kmeans, k.max = .k.max, .method[1]), "immunr_nbclust"), + data = .data + ) + add_class(res, "immunr_kmeans") +} + +immunr_dbscan <- function(.data, .eps, .dist = TRUE) { + if (.dist) { + .data <- as.dist(.data) + method <- "dist" + } else { + method <- "hybrid" + } + res <- list(dbscan = fpc::dbscan(.data, eps = .eps, method = method), data = .data) + add_class(res, "immunr_dbscan") +} diff --git a/R/data_docs.R b/R/v0_data_docs.R similarity index 100% rename from R/data_docs.R rename to R/v0_data_docs.R diff --git a/R/dimensions.R b/R/v0_dimensions.R similarity index 72% rename from R/dimensions.R rename to R/v0_dimensions.R index 881bcb95..817275cd 100644 --- a/R/dimensions.R +++ b/R/v0_dimensions.R @@ -17,16 +17,20 @@ default_scale_fun <- function(x) { #' #' @aliases immunr_pca immunr_mds immunr_tsne #' -#' @description Collects a set of principal variables, reducing the number of not important variables +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Collects a set of principal variables, reducing the number of not important variables #' to analyse. Dimensionality reduction makes data analysis algorithms work faster and #' sometimes more accurate, since it also reduces noise in the data. Currently available #' methods are: #' -#' - \code{immunr_pca} performs PCA (Principal Component Analysis) using \link{prcomp}; +#' - `immunr_pca` performs PCA (Principal Component Analysis) using [prcomp]; #' -#' - \code{immunr_mds} performs MDS (Multi-Dimensional Scaling) using \link[MASS]{isoMDS}; +#' - `immunr_mds` performs MDS (Multi-Dimensional Scaling) using isoMODS from MASS package. #' -#' - \code{immunr_tsne} performs tSNE (t-Distributed Stochastic Neighbour Embedding) using \link[Rtsne]{Rtsne}. +#' - `immunr_tsne` performs tSNE (t-Distributed Stochastic Neighbour Embedding) using Rtsne Rtsne package. #' #' @usage #' @@ -36,13 +40,13 @@ default_scale_fun <- function(x) { #' #' immunr_tsne(.data, .perp = 1, .dist = TRUE, ...) #' -#' @param .data A matrix or a data frame with features, distance matrix or output from \link{repOverlapAnalysis} or \link{geneUsageAnalysis} functions. +#' @param .data A matrix or a data frame with features, distance matrix or output from [repOverlapAnalysis] or [geneUsageAnalysis] functions. #' #' @param .scale A function to apply to your data before passing it to any of #' dimensionality reduction algorithms. There is no scaling by default. #' -#' @param .perp The perplexity parameter for \link[Rtsne]{Rtsne}. Sepcifies the number -#' of neighbours each data point must have in the resulting plot. +#' @param .perp The perplexity parameter for Rtsne. Specifies the number +#' of neighbors each data point must have in the resulting plot. #' #' @param .raw If TRUE then returns the non-processed output from dimensionality reduction #' algorithms. Pass FALSE if you want to visualise results. @@ -52,16 +56,16 @@ default_scale_fun <- function(x) { #' #' @param .dist If TRUE then assumes that ".data" is a distance matrix. #' -#' @param ... Other parameters passed to \link[Rtsne]{Rtsne}. +#' @param ... Other parameters passed to Rtsne. #' #' @return -#' \code{immunr_pca} - an output from \link{prcomp}. +#' `immunr_pca` - an output from [prcomp]. #' -#' \code{immunr_mds} - an output from \link{isoMDS}. +#' `immunr_mds` - an output from isoMDS. #' -#' \code{immunr_tsne} - an output from \link{Rtsne}. +#' `immunr_tsne` - an output from Rtsne. #' -#' @seealso \link{vis.immunr_pca} for visualisations. +#' @seealso [vis.immunr_pca] for visualisations. #' #' @examples #' data(immdata) @@ -99,6 +103,10 @@ immunr_pca <- function(.data, .scale = default_scale_fun, .raw = TRUE, .orig = F } immunr_mds <- function(.data, .scale = default_scale_fun, .raw = TRUE, .orig = FALSE, .dist = TRUE) { + if (!requireNamespace("MASS", quietly = TRUE)) { + stop("Package 'MASS' is required for this function. Please install it first via `pak::pkg_install('MASS')`", call. = FALSE) + } + if (.dist) { .data <- as.dist(.scale(.data)) } else { @@ -125,6 +133,10 @@ immunr_mds <- function(.data, .scale = default_scale_fun, .raw = TRUE, .orig = F } immunr_tsne <- function(.data, .perp = 1, .dist = TRUE, ...) { + if (!requireNamespace("Rtsne", quietly = TRUE)) { + stop("Package 'Rtsne' is required for this function. Please install it first via `pak::pkg_install('Rtsne')`", call. = FALSE) + } + if (.dist) { data_proc <- as.dist(.data) } else { diff --git a/R/distance.R b/R/v0_distance.R similarity index 82% rename from R/distance.R rename to R/v0_distance.R index 45eddac5..c6f8738f 100644 --- a/R/distance.R +++ b/R/v0_distance.R @@ -3,22 +3,25 @@ #' @concept distance #' #' @importFrom stringdist stringdistmatrix -#' @importFrom purrr map pmap map2 #' @importFrom magrittr %>% %<>% set_attr #' @importFrom tidyr unite #' @importFrom dplyr select_if group_keys group_map group_by group_by_at -#' @description Computing sequential distances between clonotypes from two repertoires: +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Computing sequential distances between clonotypes from two repertoires: #' #' @usage #' #' seqDist(.data, .col = 'CDR3.nt', .method = 'hamming', #' .group_by = c("V.name", "J.name"), .group_by_seqLength = TRUE, .trim_genes = TRUE, ...) #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' -#' Every object must have columns in the immunarch compatible format \link{immunarch_data_format} +#' Every object must have columns in the immunarch compatible format [immunarch_data_format] #' #' @param .col A string that specifies the column name to be processed. The default value is 'CDR3.nt'. #' @@ -32,27 +35,27 @@ #' #' @param ... Extra arguments for user-defined function. #' -#' The default value is \code{'hamming'} for Hamming distance which counts the number of character substitutions that turns b into a. +#' The default value is `'hamming'` for Hamming distance which counts the number of character substitutions that turns b into a. #' If a and b have different number of characters the distance is Inf. #' #' Other possible values are: #' -#' \code{'lv'} for Levenshtein distance which counts the number of deletions, insertions and substitutions necessary to turn b into a. +#' `'lv'` for Levenshtein distance which counts the number of deletions, insertions and substitutions necessary to turn b into a. #' -#' \code{'lcs'} for longest common substring is defined as the longest string can be obtained by pairing characters from a and b while keeping the order of characters intact. +#' `'lcs'` for longest common substring is defined as the longest string can be obtained by pairing characters from a and b while keeping the order of characters intact. #' -#' In case of user-defined function, it should take x and y parameters as input and return \link{dist} object. +#' In case of user-defined function, it should take x and y parameters as input and return [dist] object. #' #' @return #' -#' Named list of list with \link{dist} objects for given repertoires for each combination of .group_by variable(s) and/or sequence length of .col. +#' Named list of list with [dist] objects for given repertoires for each combination of .group_by variable(s) and/or sequence length of .col. #' #' @examples -#' +#' \dontrun{ #' data(immdata) #' # Reducing data to save time on examples -#' immdata$data <- purrr::map(immdata$data, ~ .x %>% head(10)) -#' # Computing hamming distance for the first two repertoires in \code{'immdata'} +#' immdata$data <- map(immdata$data, ~ .x %>% head(10)) +#' # Computing hamming distance for the first two repertoires in `'immdata'` #' seqDist(immdata$data[1:2]) #' #' # Here we define a custom distance function @@ -68,6 +71,8 @@ #' } #' #' seqDist(immdata$data[1:2], .method = f, .group_by_seqLength = FALSE) +#' } +#' #' @export seqDist seqDist <- function(.data, diff --git a/R/diversity.R b/R/v0_diversity.R similarity index 96% rename from R/diversity.R rename to R/v0_diversity.R index 0fd027b1..00b57c18 100644 --- a/R/diversity.R +++ b/R/v0_diversity.R @@ -17,20 +17,23 @@ if (getRversion() >= "2.15.1") { #' @importFrom tidyselect all_of #' #' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' This is a utility function to estimate the diversity of species or objects in the given distribution. #' #' Note: functions will check if .data is a distribution of a random variable (sum == 1) or not. #' To force normalisation and / or to prevent this, set .do.norm to TRUE (do normalisation) #' or FALSE (don't do normalisation), respectively. #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. @@ -65,7 +68,7 @@ if (getRversion() >= "2.15.1") { #' chao1 returns 4 values: estimated number of species, standart deviation of #' this number and two 95% confidence intervals for the species number. #' -#' hill returns a vector of specified length \code{.max.q - .min.q} +#' hill returns a vector of specified length `.max.q - .min.q` #' #' @details #' - True diversity, or the effective number of types, refers to the number @@ -111,13 +114,13 @@ if (getRversion() >= "2.15.1") { #' on different step of the simulaiton process or a list with such matrices. #' #' -#' @seealso \link{repOverlap}, \link{entropy}, \link{repClonality} +#' @seealso [repOverlap], [entropy], [repClonality] #' Rarefaction wiki -#' \url{https://en.wikipedia.org/wiki/Rarefaction_(ecology)} +#' #' Hill numbers paper -#' \url{https://www.uvm.edu/~ngotelli/manuscriptpdfs/ChaoHill.pdf} +#' #' Diversity wiki -#' \url{https://en.wikipedia.org/wiki/Measurement_of_biodiversity} +#' #' #' #' @examples diff --git a/R/dynamics.R b/R/v0_dynamics.R similarity index 93% rename from R/dynamics.R rename to R/v0_dynamics.R index 7c4e7370..6b8750ed 100644 --- a/R/dynamics.R +++ b/R/v0_dynamics.R @@ -8,25 +8,28 @@ #' @aliases trackClonotypes #' #' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' Tracks the temporal dynamics of clonotypes in repertoires. For example, tracking across multiple #' time points after vaccination. #' -#' @param .data The data to process. It can be a \link{data.frame}, a -#' \link{data.table}, or a list of these objects. +#' @param .data The data to process. It can be a [data.frame], a +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. #' #' @param .which An argument that regulates which clonotypes to choose for tracking. There are three options for this argument: #' -#' 1) passes a list with two elements \code{list(X, Y)}, where \code{X} is the name or the index of a target repertoire from ".data", and -#' \code{Y} is the number of the most abundant clonotypes to take from \code{X}. +#' 1) passes a list with two elements `list(X, Y)`, where `X` is the name or the index of a target repertoire from ".data", and +#' `Y` is the number of the most abundant clonotypes to take from `X`. #' #' 2) passes a character vector of sequences to take from all data frames; #' diff --git a/R/explore.R b/R/v0_explore.R similarity index 90% rename from R/explore.R rename to R/v0_explore.R index acec387f..aa63abf8 100644 --- a/R/explore.R +++ b/R/v0_explore.R @@ -6,18 +6,22 @@ #' #' @aliases repExplore #' -#' @description The \code{repExplore} function calculates the basic statistics of +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' The `repExplore` function calculates the basic statistics of #' repertoire: the number of unique immune receptor clonotypes, their relative abundances, #' and sequence length distribution across the input dataset. #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. @@ -40,7 +44,7 @@ #' @param .col A string that specifies the column to be processed. Pass "nt" for #' nucleotide sequence or "aa" for amino acid sequence. #' -#' @param .coding If \code{TRUE}, then only coding sequences will be analysed. +#' @param .coding If `TRUE`, then only coding sequences will be analysed. #' #' @return #' If input data is a single immune repertoire, then the function returns a numeric vector @@ -48,7 +52,7 @@ #' #' Otherwise, it returns a numeric matrix with exploratory analysis statistics for all input repertoires. #' -#' @seealso \link{vis.immunr_exp_vol} +#' @seealso [vis.immunr_exp_vol] #' #' @examples #' data(immdata) diff --git a/R/filters.R b/R/v0_filters.R similarity index 99% rename from R/filters.R rename to R/v0_filters.R index 81af95c5..9cae0759 100644 --- a/R/filters.R +++ b/R/v0_filters.R @@ -7,6 +7,10 @@ #' @importFrom magrittr "%>%" "%<>%" #' @importFrom tidyselect starts_with #' +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' @param .data The data to be processed. Must be the list of 2 elements: #' a data table and a metadata table. #' @param .method Method of filtering. Implemented methods: diff --git a/R/gene_usage.R b/R/v0_gene_usage.R similarity index 94% rename from R/gene_usage.R rename to R/v0_gene_usage.R index bf66f361..68857b16 100644 --- a/R/gene_usage.R +++ b/R/v0_gene_usage.R @@ -10,25 +10,28 @@ if (getRversion() >= "2.15.1") { #' @aliases geneUsage get_aliases get_genes #' #' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' An utility function to analyse the immune receptor gene usage #' (IGHD, IGHJ, IDHV, IGIJ, IGKJ, IGKV, IGLJ, IGLV, TRAJ, TRAV, TRBD, etc.) -#' and statistics. For gene details run \code{gene_stats()}. +#' and statistics. For gene details run `gene_stats()`. #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections,or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. #' @param .gene A character vector of length one with the name of the gene you want #' to analyse of the specific species. If you provide a vector of different length, only the first element #' will be used. The string should also contain the species of interest, for example, valid ".gene" arguments -#' are "hs.trbv", "HomoSapiens.TRBJ" or "macmul.IGHV". For details run \code{gene_stats()}. +#' are "hs.trbv", "HomoSapiens.TRBJ" or "macmul.IGHV". For details run `gene_stats()`. #' @param .quant Selects the column with data to evaluate. #' Pass NA if you want to compute gene statistics at the clonotype level without re-weighting. #' Pass "count" to use the "Clones" column to weight genes by abundance of their corresponding clonotypes. @@ -188,14 +191,12 @@ geneUsage <- function(.data, # df, list, MonetDB #' WIP #' -#' @concept gene_usage +#' @concept data #' #' @importFrom dplyr n #' -#' @aliases gene_stats -#' #' @return -#' \code{gene_stats} returns all segment gene statistics +#' `gene_stats` returns all segment gene statistics #' #' @examples #' gene_stats() diff --git a/R/gene_usage_analysis.R b/R/v0_gene_usage_analysis.R similarity index 88% rename from R/gene_usage_analysis.R rename to R/v0_gene_usage_analysis.R index 03e9eebf..bbe8c9e5 100644 --- a/R/gene_usage_analysis.R +++ b/R/v0_gene_usage_analysis.R @@ -6,17 +6,21 @@ #' #' @aliases geneUsageAnalysis #' -#' @description The \code{\link{geneUsageAnalysis}} function deploys several +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' The [geneUsageAnalysis()] function deploys several #' data analysis methods, including PCA, multidimensional scaling, #' Jensen-Shannon divergence, k-means, hierarchical clustering, DBscan, and different #' correlation coefficients. #' -#' @param .data The \code{\link{geneUsageAnalysis}} function runs on the output from -#' \code{\link{geneUsage}}. +#' @param .data The [geneUsageAnalysis()] function runs on the output from +#' [geneUsage()]. #' #' @param .method A string that defines the type of analysis to perform. Can be "pca", #' "mds", "js", "kmeans", "hclust", "dbscan" or "cor" if you want to calculate -#' correlation coefficient. In the latter case you have to provide \code{.cor} argument. +#' correlation coefficient. In the latter case you have to provide `.cor` argument. #' #' @param .base A numerical value that defines the logarithm base for Jensen-Shannon #' divergence. @@ -29,13 +33,13 @@ #' @param .laplace The numeric value, which is used as a pseudocount for Laplace #' smoothing. #' @param .verbose A logical value. -#' @param .k The number of clusters to create, passed as \code{k} to \link[factoextra]{hcut} or as \code{centers} to \link{kmeans}. +#' @param .k The number of clusters to create, passed as `k` to [hcut][factoextra::hcut] or as `centers` to [kmeans]. #' @param .eps A numerical value, DBscan epsylon parameter, see -#' \code{\link{immunr_dbscan}}. -#' @param .perp A numerical value, t-SNE perplexity, see \code{\link{immunr_tsne}}. -#' @param .theta A numerical value, t-SNE theta parameter, see \code{\link{immunr_tsne}}. +#' [immunr_dbscan()]. +#' @param .perp A numerical value, t-SNE perplexity, see [immunr_tsne()]. +#' @param .theta A numerical value, t-SNE theta parameter, see [immunr_tsne()]. #' -#' @return Depends on the last element in the \code{.method} string. See \link{immunr_tsne} for more info. +#' @return Depends on the last element in the `.method` string. See [immunr_tsne] for more info. #' #' @examples #' data(immdata) diff --git a/R/germline.R b/R/v0_germline.R similarity index 97% rename from R/germline.R rename to R/v0_germline.R index 8d21a700..9e4950bf 100644 --- a/R/germline.R +++ b/R/v0_germline.R @@ -5,14 +5,17 @@ #' @aliases repGermline #' #' @importFrom stringr str_sub str_length str_replace fixed str_extract_all str_extract boundary str_c -#' @importFrom purrr imap map_dfr #' @importFrom magrittr %>% %<>% extract2 #' @importFrom dplyr filter rowwise #' @importFrom tidyselect any_of #' @importFrom parallel parApply detectCores makeCluster clusterExport stopCluster #' @importFrom ape as.DNAbin clustal #' -#' @description This function creates germlines for clonal lineages. B cell clonal lineage +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' This function creates germlines for clonal lineages. B cell clonal lineage #' represents a set of B cells that presumably have a common origin (arising from the same VDJ #' rearrangement event) and a common ancestor. Each clonal lineage has its own germline sequence #' that represents the ancestral sequence for each BCR in clonal lineage. In other words, @@ -24,10 +27,10 @@ #' #' repGermline(.data, .species, .min_nuc_outside_cdr3, .threads) #' -#' @param .data The data to be processed. Can be \link{data.frame}, \link{data.table} +#' @param .data The data to be processed. Can be [data.frame], [data.table::data.table] #' or a list of these objects. #' -#' It must have columns in the immunarch compatible format \link{immunarch_data_format}. +#' It must have columns in the immunarch compatible format [immunarch_data_format]. #' #' @param .species Species from which the data was acquired. Available options: #' "HomoSapiens" (default), "MusMusculus", "BosTaurus", "CamelusDromedarius", diff --git a/R/immunr_data_format.R b/R/v0_immunr_data_format.R similarity index 100% rename from R/immunr_data_format.R rename to R/v0_immunr_data_format.R diff --git a/R/info_theory.R b/R/v0_info_theory.R similarity index 95% rename from R/info_theory.R rename to R/v0_info_theory.R index c8fbfd31..9f52e946 100644 --- a/R/info_theory.R +++ b/R/v0_info_theory.R @@ -4,7 +4,11 @@ #' #' @aliases entropy kl_div js_div cross_entropy #' -#' @description Compute information-based estimates and distances. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Compute information-based estimates and distances. #' #' @usage #' entropy(.data, .base = 2, .norm = FALSE, .do.norm = NA, .laplace = 1e-12) diff --git a/R/io.R b/R/v0_io.R similarity index 94% rename from R/io.R rename to R/v0_io.R index 975eca74..4e6db265 100644 --- a/R/io.R +++ b/R/v0_io.R @@ -17,16 +17,19 @@ if (getRversion() >= "2.15.1") { #' @concept io #' #' @importFrom readr read_delim read_tsv read_csv col_integer col_character col_double col_logical col_guess cols write_lines -#' @importFrom jsonlite read_json #' @importFrom stringr str_split str_detect str_replace_all str_trim #' @importFrom methods as #' @importFrom dplyr contains first select_ group_by_at one_of row_number #' @importFrom utils read.table #' @importFrom data.table setDF #' -#' @description The \code{repLoad} function loads repertoire files +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' The `repLoad` function loads repertoire files #' into R workspace in the immunarch format where you can immediately use them for -#' the analysis. \code{repLoad} automatically detects the right format for +#' the analysis. `repLoad` automatically detects the right format for #' your files, so all you need is simply provide the path to your files. #' #' See "Details" for more information on supported formats. See "Examples" for @@ -36,15 +39,15 @@ if (getRversion() >= "2.15.1") { #' Input data can be one of the following: #' #' - a single repertoire file. -#' In this case \code{repLoad} returns an R \link{data.frame}; +#' In this case `repLoad` returns an R [data.frame]; #' #' - a vector of paths to repertoire files. #' Same as in the case with no metadata file presented in the next section below; #' #' - a path to the folder with repertoire files and, if available, metadata file "metadata.txt". -#' If the metadata file if presented, then the \code{repLoad} returns a list with two elements "data" and "meta". -#' "data" is an another list with repertoire R \link{data.frame}s. "meta" is a data frame with the metadata. -#' If the metadata file "metadata.txt" is not presented, then the \code{repLoad} creates a dummy metadata file with +#' If the metadata file if presented, then the `repLoad` returns a list with two elements "data" and "meta". +#' "data" is an another list with repertoire R [data.frame]s. "meta" is a data frame with the metadata. +#' If the metadata file "metadata.txt" is not presented, then the `repLoad` creates a dummy metadata file with #' sample names and returns a list with two elements "data" and "meta". #' If input data has multiple chains or cell types stored in the same file #' (for example, like in 10xGenomics repertoire files), such repertoire files will be splitted to different @@ -104,8 +107,8 @@ if (getRversion() >= "2.15.1") { #' #' - "meta" is a data frame with sample metadata. #' -#' @seealso \link{immunr_data_format} for immunarch data format; \link{repSave} for file saving; -#' \link{repOverlap}, \link{geneUsage} and \link{repDiversity} for starting with immune repertoires basic statistics. +#' @seealso [immunr_data_format] for immunarch data format; [repSave] for file saving; +#' [repOverlap], [geneUsage] and [repDiversity] for starting with immune repertoires basic statistics. #' #' @examples #' # To load the data from a single file (note that you don't need to specify the data format): @@ -171,7 +174,6 @@ repLoad <- function(.path, .mode = "paired", .coding = TRUE, ...) { catt = parse_catt, rtcr = parse_rtcr, imseq = parse_imseq, - vidjil = parse_vidjil, NA ) @@ -430,13 +432,16 @@ repLoad <- function(.path, .mode = "paired", .coding = TRUE, ...) { #' #' @importFrom utils packageVersion #' @importFrom plyr mapvalues -#' @importFrom purrr map #' -#' @description The \code{repSave} function is deigned to save your data to the disk +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' The `repSave` function is deigned to save your data to the disk #' in desirable format. Currently supports "immunarch" and "vdjtools" file formats. #' -#' @param .data An R dataframe, a list of R dataframes or a list with \code{data} and -#' \code{meta} where first element is a list of dataframes and the latter is a dataframe +#' @param .data An R dataframe, a list of R dataframes or a list with `data` and +#' `meta` where first element is a list of dataframes and the latter is a dataframe #' with metadata. #' @param .path A string with the path to the output directory. It should include file #' name if a single dataframe is provided to .data argument. @@ -450,9 +455,10 @@ repLoad <- function(.path, .mode = "paired", .coding = TRUE, ...) { #' @return No return value. #' #' @examples +#' \dontrun{ #' data(immdata) #' # Reduce data to save time on examples -#' immdata$data <- purrr::map(immdata$data, ~ .x %>% head(10)) +#' immdata$data <- map(immdata$data, ~ .x %>% head(10)) #' dirpath <- tempdir() #' # Save the list of repertoires #' repSave(immdata, dirpath) @@ -461,6 +467,7 @@ repLoad <- function(.path, .mode = "paired", .coding = TRUE, ...) { #' # sum(immdata$data[[1]] != new_immdata$data[[1]], na.rm = TRUE) #' # sum(immdata$data[[2]] != new_immdata$data[[2]], na.rm = TRUE) #' # sum(immdata$meta != new_immdata$meta, na.rm = TRUE) +#' } #' @export repSave repSave <- function(.data, .path, .format = c("immunarch", "vdjtools"), .compress = TRUE) { diff --git a/R/io-parsers.R b/R/v0_io_parsers.R similarity index 97% rename from R/io-parsers.R rename to R/v0_io_parsers.R index fd0601cd..3adb1a5c 100644 --- a/R/io-parsers.R +++ b/R/v0_io_parsers.R @@ -1275,46 +1275,3 @@ parse_imseq <- function(.filename, .mode) { .total.insertions = total.insertions, .skip = .skip, .sep = .sep ) } - -parse_vidjil <- function(.filename, .mode) { - json_data <- read_json(.filename, simplifyVector = TRUE) - clones <- json_data[["clones"]] - - count <- as.vector(clones[["reads"]], mode = "numeric") - proportion <- count / sum(count) - cdr3nt <- NA - cdr3aa <- as.vector(clones[["seg"]][["cdr3"]][["aa"]]) - vgenes <- as.vector(clones[["seg"]][["5"]]) - dgenes <- NA - jgenes <- as.vector(clones[["seg"]][["3"]]) - vend <- as.vector(clones[["seg"]][["5end"]], mode = "numeric") - dstart <- NA - dend <- NA - jstart <- as.vector(clones[["seg"]][["3start"]], mode = "numeric") - vj.insertions <- NA - vd.insertions <- NA - dj.insertions <- NA - - df <- data.frame( - count, proportion, cdr3nt, cdr3aa, vgenes, dgenes, jgenes, - vend, dstart, dend, jstart, vj.insertions, vd.insertions, dj.insertions - ) - - colnames(df)[1] <- IMMCOL$count - colnames(df)[2] <- IMMCOL$prop - colnames(df)[3] <- IMMCOL$cdr3nt - colnames(df)[4] <- IMMCOL$cdr3aa - colnames(df)[5] <- IMMCOL$v - colnames(df)[6] <- IMMCOL$d - colnames(df)[7] <- IMMCOL$j - colnames(df)[8] <- IMMCOL$ve - colnames(df)[9] <- IMMCOL$ds - colnames(df)[10] <- IMMCOL$de - colnames(df)[11] <- IMMCOL$js - colnames(df)[12] <- IMMCOL$vnj - colnames(df)[13] <- IMMCOL$vnd - colnames(df)[14] <- IMMCOL$dnj - - df <- .postprocess(df) - df -} diff --git a/R/io-savers.R b/R/v0_io_savers.R similarity index 100% rename from R/io-savers.R rename to R/v0_io_savers.R diff --git a/R/io-utility.R b/R/v0_io_utility.R similarity index 100% rename from R/io-utility.R rename to R/v0_io_utility.R diff --git a/R/kmers.R b/R/v0_kmers.R similarity index 70% rename from R/kmers.R rename to R/v0_kmers.R index 6560565b..b76e6e6c 100644 --- a/R/kmers.R +++ b/R/v0_kmers.R @@ -7,14 +7,19 @@ #' #' @aliases getKmers get.kmers makeKmerTable #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections,or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. @@ -89,12 +94,18 @@ getKmers <- function(.data, .k, .col = c("aa", "nt"), .coding = TRUE) { #' #' @aliases split_to_kmers kmer_profile #' +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' #' @usage #' split_to_kmers(.data, .k) #' #' kmer_profile(.data, .method = c("freq", "prob", "wei", "self"), .remove.stop = TRUE) #' -#' @param .data Character vector or the output from \code{getKmers}. +#' @param .data Character vector or the output from `getKmers`. #' @param .k Integer. Size of k-mers. #' @param .method Character vector of length one. If "freq" then returns a position frequency matrix (PFM) - #' a matrix with occurences of each amino acid in each position. @@ -110,9 +121,9 @@ getKmers <- function(.data, .k, .col = c("aa", "nt"), .coding = TRUE) { #' @param .remove.stop Logical. If TRUE (by default) remove stop codons. #' #' @return -#' \code{split_to_kmers} - Data frame with two columns (k-mers and their counts). +#' `split_to_kmers` - Data frame with two columns (k-mers and their counts). #' -#' \code{kmer_profile} - a matrix with per-position amino acid statistics. +#' `kmer_profile` - a matrix with per-position amino acid statistics. #' #' @examples #' data(immdata) @@ -201,59 +212,3 @@ kmer_profile <- function(.data, .method = c("freq", "prob", "wei", "self"), .rem add_class(res, "immunr_kmer_profile_self") } } - - -####### -# WIP # -####### -# gibbs_sampling <- function (.data, .motif.len = 5, .niter = 500) { -# .score <- function (.seq, .i, .prof, .background) { -# kmer_aa = strsplit(substr(.seq, seq_i, seq_i + .motif.len - 1), "")[[1]] -# prod(sapply(1:.motif.len, function (kmer_pos) { -# sc = .prof[kmer_aa[kmer_pos], kmer_pos] / .background[kmer_aa[kmer_pos]] -# if (is.nan(sc)) { sc = 0 } -# sc -# })) -# } -# -# cat("Removed", sum(nchar(.data) < .motif.len), "sequences with the length less than the length of motifs.\n") -# seq_vec = .data[nchar(.data) >= .motif.len] -# background = table(unlist(strsplit(seq_vec, ""))) -# background = background / sum(background) -# -# # Vector of scores for each position in the each input sequence -# score_vec = lapply(seq_vec, function (seq_x) rep(1, nchar(seq_x) - .motif.len + 1) ) -# start_pos = sapply(nchar(seq_vec), function (max_pos) sample(1:(max_pos - .motif.len + 1), 1)) -# -# # In the loop: -# pb = set_pb(.niter) -# for (iter in 1:.niter) { -# # Get random kmers -# prev_start_pos = start_pos -# start_pos = sapply(nchar(seq_vec), function (max_pos) sample(1:(max_pos - .motif.len + 1), 1)) -# -# for (out_kmer_i in sample(1:length(seq_vec), length(seq_vec))) { -# max_pos = nchar(seq_vec[out_kmer_i]) - .motif.len + 1 -# kmers <- substr(seq_vec[-out_kmer_i], start_pos[-out_kmer_i], start_pos[-out_kmer_i] + .motif.len - 1) -# prof = kmer_profile(kmers[-out_kmer_i]) -# for (seq_i in 1:max_pos) { -# score_vec[[out_kmer_i]][seq_i] = .score(seq_vec[out_kmer_i], seq_i, prof, background) -# } -# if (sum(score_vec[[out_kmer_i]]) != 0) { -# poses = c(1:max_pos)[!is.na(score_vec[[out_kmer_i]])] -# start_pos[out_kmer_i] = sample(c(1:max_pos), 1, prob = score_vec[[out_kmer_i]][poses] / sum(score_vec[[out_kmer_i]][poses])) -# } -# } -# -# add_pb(pb) -# -# if (sum(prev_start_pos != start_pos) == 0) { -# break -# } -# } -# close(pb) -# -# data.frame(Motif = substr(seq_vec, start_pos, start_pos + .motif.len - 1), -# Start = start_pos, -# Score = sapply(1:length(score_vec), function (i) { score_vec[[i]][start_pos[i]] }), stringsAsFactors = FALSE) -# } diff --git a/R/overlap.R b/R/v0_overlap.R similarity index 93% rename from R/overlap.R rename to R/v0_overlap.R index 5bc97436..4c33389c 100644 --- a/R/overlap.R +++ b/R/v0_overlap.R @@ -6,24 +6,28 @@ #' @importFrom magrittr "%>%" #' @importFrom dtplyr lazy_dt #' -#' @description The \code{repOverlap} function is designed to analyse the overlap between +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' The `repOverlap` function is designed to analyse the overlap between #' two or more repertoires. It contains a number of methods to compare immune receptor #' sequences that are shared between individuals. #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. #' #' @param .method A string that specifies the method of analysis or a combination of -#' methods. The \code{repOverlap} function supports following basic methods: +#' methods. The `repOverlap` function supports following basic methods: #' "public", "overlap", "jaccard", "tversky", "cosine", "morisita". #' If vector of multiple methods is given for this parameter, the first method will be used. #' @@ -83,7 +87,7 @@ #' #' If one of the incremental method is chosen, return list of overlap matrix. #' -#' @seealso \link{inc_overlap}, \link{vis} +#' @seealso [inc_overlap], [vis] #' #' @examples #' data(immdata) @@ -332,21 +336,25 @@ horn_index <- function(.x, .y) { #' #' @concept overlap #' -#' @description For reference please look up https://www.pnas.org/content/111/16/5980 (Fig. 4). +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' For reference please look up https://www.pnas.org/content/111/16/5980 (Fig. 4). #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. #' -#' @param .fun Function to compute overlaps. e.g., \code{morisita_index}. +#' @param .fun Function to compute overlaps. e.g., `morisita_index`. #' #' @param .step Either an integer or a numeric vector. #' @@ -354,7 +362,7 @@ horn_index <- function(.x, .y) { #' #' In the second case, the vector encodes all repertoire sampling depths. #' -#' @param .n.steps Integer. Number of steps if \code{.step} is a single integer. +#' @param .n.steps Integer. Number of steps if `.step` is a single integer. #' Skipped if ".step" is a numeric vector. #' #' @param .downsample If TRUE then performs downsampling to N clonotypes at each step instead of choosing the @@ -364,7 +372,7 @@ horn_index <- function(.x, .y) { #' #' @param .verbose.inc Logical. If TRUE then shows the output from the computation process. #' -#' @param ... Other arguments passed to \code{.fun}. +#' @param ... Other arguments passed to `.fun`. #' #' @return #' List with overlap matrices. diff --git a/R/overlap_analysis.R b/R/v0_overlap_analysis.R similarity index 79% rename from R/overlap_analysis.R rename to R/v0_overlap_analysis.R index 90deea4b..51993f2a 100644 --- a/R/overlap_analysis.R +++ b/R/v0_overlap_analysis.R @@ -2,12 +2,16 @@ #' #' @concept overlap #' -#' @description The \code{\link{repOverlapAnalysis}} function contains advanced data +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' The [repOverlapAnalysis()] function contains advanced data #' analysis methods. You can use several clustering and dimensionality reduction #' techniques in order to investigate further the difference between repertoires #' provided. #' -#' To cluster a subset of similar data with \code{\link{repOverlapAnalysis}} you can +#' To cluster a subset of similar data with [repOverlapAnalysis()] you can #' perform hierarchical clustering, k-means or dbscan ('hclust', 'kmeans', 'dbscan' #' respectively). #' @@ -16,21 +20,21 @@ #' respectively). #' #' @param .data Any distance matrix between pairs of repertoires. You can also pass your -#' output from \code{\link{repOverlap}}. +#' output from [repOverlap()]. #' @param .method A string that defines the type of analysis to perform. #' @param .scale A function to scale the data before passing it to the MDS algorithm. #' @param .raw A logical value. Set TRUE if you want to receive raw output of clustering #' or dimensionality reduction function of choice. Set FALSE if you want to receive -#' processed output that can be subjected to visualisation with \code{\link{vis}} function. +#' processed output that can be subjected to visualisation with [vis()] function. #' -#' @param .perp A numerical value, t-SNE parameter, see \code{\link{immunr_tsne}}. -#' @param .theta A numerical value, t-SNE parameter, see \code{\link{immunr_tsne}}. +#' @param .perp A numerical value, t-SNE parameter, see [immunr_tsne()]. +#' @param .theta A numerical value, t-SNE parameter, see [immunr_tsne()]. #' -#' @param .eps A numerical value, DBscan epsylon parameter, see \code{\link{immunr_dbscan}}. +#' @param .eps A numerical value, DBscan epsylon parameter, see [immunr_dbscan()]. #' -#' @param .k The number of clusters to create, passed as \code{k} to \link[factoextra]{hcut} or as \code{centers} to \link{kmeans}. +#' @param .k The number of clusters to create, passed as `k` to [hcut][factoextra::hcut] or as `centers` to [kmeans]. #' -#' @return Depends on the last element in the \code{.method} string. See \link{immunr_tsne} for more info. +#' @return Depends on the last element in the `.method` string. See [immunr_tsne] for more info. #' #' @examples #' data(immdata) diff --git a/R/phylip.R b/R/v0_phylip.R similarity index 97% rename from R/phylip.R rename to R/v0_phylip.R index b96bba88..155ab695 100644 --- a/R/phylip.R +++ b/R/v0_phylip.R @@ -5,18 +5,18 @@ #' @aliases repClonalFamily #' #' @importFrom magrittr %>% %<>% extract2 -#' @importFrom purrr map_dfr #' @importFrom rlist list.remove #' @importFrom stringr str_match str_count fixed str_extract_all str_length str_sub -#' @importFrom stringi stri_replace_all_fixed #' @importFrom utils capture.output #' @importFrom parallel mclapply detectCores -#' @importFrom phangorn write.phyDat #' @importFrom ape read.tree -#' @importFrom uuid UUIDgenerate #' @importFrom data.table fread -#' @description This function uses the PHYLIP package to make phylogenetic analysis. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' This function uses the PHYLIP package to make phylogenetic analysis. #' For making trees it uses maximum parsimony methods. #' #' @usage @@ -143,6 +143,10 @@ process_dataframe <- function(df, vis_groups, .threads, sample_name = NA) { } process_cluster <- function(cluster_row, vis_groups) { + if (!requireNamespace("phangorn", quietly = TRUE)) { + stop("Package 'phangorn' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + # alignment, sequences and aa_frame_starts should be extracted from 1-element lists # because of these columns format alignment <- cluster_row[["Alignment"]][[1]] @@ -151,12 +155,15 @@ process_cluster <- function(cluster_row, vis_groups) { fsep <- if (.Platform$OS.type == "windows") "\\" else "/" shell <- if (.Platform$OS.type == "windows") "powershell /c " else "sh -c " - temp_dir <- file.path(tempdir(check = TRUE), uuid::UUIDgenerate(use.time = FALSE), fsep = fsep) + + temp_dir <- tempfile(pattern = "tempdir_") dir.create(temp_dir) + # workaround for phylip: it shows "Unexpected end-of-file" for too short sequence labels; # these \t are also used to read outfile as table rownames(alignment) %<>% paste0("\t") phangorn::write.phyDat(alignment, file.path(temp_dir, "infile", fsep = fsep)) + dnapars <- if (Sys.which("phylip") == "") "dnapars" else "phylip dnapars" system( paste0(shell, "\"cd ", temp_dir, "; ", dnapars, " infile\""), @@ -366,7 +373,7 @@ convert_nested_to_df <- function(nested_results_list) { tibble(Sequences = .) df <- nested_results_list %>% lapply(rlist::list.remove, c("Tree", "TreeStats", "Sequences")) %>% - purrr::map_dfr(~.) %>% + map_dfr(~.) %>% cbind(tree, tree_stats, sequences) # fix column types after dataframe rebuilding df[["Trunk.Length"]] %<>% as.integer() diff --git a/R/preprocessing.R b/R/v0_preprocessing.R similarity index 88% rename from R/preprocessing.R rename to R/v0_preprocessing.R index 0a52eac4..e1218b23 100644 --- a/R/preprocessing.R +++ b/R/v0_preprocessing.R @@ -4,21 +4,21 @@ #' #' @importFrom dplyr top_n collect #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. #' @param .n Numeric. Number of the most abundant clonotypes to return. #' #' @return -#' Data frame with the \code{.n} most abundant clonotypes only. +#' Data frame with the `.n` most abundant clonotypes only. #' #' @examples #' data(immdata) @@ -62,14 +62,14 @@ top <- function(.data, .n = 10) { #' #' outofframes(.data) #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, Apache Spark DataFrame from "copy_to" or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. diff --git a/R/public.R b/R/v0_public.R similarity index 92% rename from R/public.R rename to R/v0_public.R index 344c10d3..ab5cff59 100644 --- a/R/public.R +++ b/R/v0_public.R @@ -9,14 +9,19 @@ #' @importFrom data.table setcolorder ":=" as.data.table #' @importFrom dplyr full_join ungroup #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. @@ -123,7 +128,12 @@ publicRepertoire <- pubRep #' #' @concept pubrep #' -#' @param .data Public repertoire, an output from \link{pubRep}. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data Public repertoire, an output from [pubRep]. #' #' @return #' Matrix with per-sample clonotype counts / proportions only. @@ -168,9 +178,13 @@ get_public_repertoire_names <- function(.pr) { #' #' @aliases pubRepFilter publicRepertoireFilter #' -#' @description Filter our clonotypes with low incidence in a specific group. +#' @description #' -#' @param .pr Public repertoires, an output from \link{pubRep}. +#' `r lifecycle::badge('deprecated')` +#' +#' Filter our clonotypes with low incidence in a specific group. +#' +#' @param .pr Public repertoires, an output from [pubRep]. #' @param .meta Metadata file. #' @param .by Named character vector. Names of the group to filter by. #' @param .min.samples Integer. Filters out clonotypes with the number of samples below than this number. @@ -236,12 +250,14 @@ publicRepertoireFilter <- pubRepFilter #' #' @aliases pubRepApply publicRepertoireApply #' -#' @description Work In Progress +#' @description +#' +#' `r lifecycle::badge('deprecated')` #' #' @param .pr1 First public repertoire. #' @param .pr2 Second public repertoire. #' @param .fun A function to apply to pairs of frequencies of same clonotypes from "pr1" and "pr2". -#' By default - \code{log(X) / log(Y)} where \code{X,Y} - frequencies of the same clonotype, +#' By default - `log(X) / log(Y)` where `X,Y` - frequencies of the same clonotype, #' found in both public repertoires. #' #' @return @@ -288,7 +304,12 @@ publicRepertoireApply <- pubRepApply #' @importFrom dplyr group_by mutate filter #' @importFrom stats na.omit #' -#' @param .data Public repertoire, an output from the \link{pubRep} function. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data Public repertoire, an output from the [pubRep] function. #' @param .by Work in Progress. #' @param .meta Work in Progress. #' diff --git a/R/sampling.R b/R/v0_sampling.R similarity index 85% rename from R/sampling.R rename to R/v0_sampling.R index ee5b7790..701c0614 100644 --- a/R/sampling.R +++ b/R/v0_sampling.R @@ -22,16 +22,19 @@ #' @aliases repSample #' #' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' Sample (downsample) repertoires using different approches. #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. @@ -49,19 +52,19 @@ #' @return Subsampled immune repertoire or a list of subsampled immune repertoires. #' #' @details -#' If \code{.method} is "downsample" then \code{repSample} chooses \code{.n} clones (not clonotypes!) from the input repertoires without any probabilistic simulation, +#' If `.method` is "downsample" then `repSample` chooses `.n` clones (not clonotypes!) from the input repertoires without any probabilistic simulation, #' but exactly computing each choosed clones. Such approach is is more consistent and biologically pleasant than -#' an output from the function if \code{.method} is "resample". +#' an output from the function if `.method` is "resample". #' -#' If \code{.method} is "resample" then \code{repSample} uses multinomial distribution to compute the number of occurences for each cloneset. -#' then it removes zero-number clonotypes and return the resulting data frame. Probabilities for \code{rmultinom} for each cloneset +#' If `.method` is "resample" then `repSample` uses multinomial distribution to compute the number of occurences for each cloneset. +#' then it removes zero-number clonotypes and return the resulting data frame. Probabilities for `rmultinom` for each cloneset #' is a percentage of this cloneset in the "Proportion" column. It's a some sort of simulation of how clonotypes are chosen from the organisms. #' -#' if \code{.method} is "sample" then \code{repSample} chooses \code{.n} clonotypes (not clones!) randomly. Depending on the -#' \code{.prob} argument, the function chooses clonotypes either according to their size (if \code{.prob} is TRUE, by default), -#' or each clonotype has an equal chance to be choosed (if \code{.prob} is FALSE). Note that sampling is done without replacing. +#' if `.method` is "sample" then `repSample` chooses `.n` clonotypes (not clones!) randomly. Depending on the +#' `.prob` argument, the function chooses clonotypes either according to their size (if `.prob` is TRUE, by default), +#' or each clonotype has an equal chance to be choosed (if `.prob` is FALSE). Note that sampling is done without replacing. #' -#' @seealso \link{rmultinom}, \link{clonal_proportion} +#' @seealso [rmultinom], [clonal_proportion] #' #' @examples #' data(immdata) diff --git a/R/seqCluster.R b/R/v0_seqCluster.R similarity index 90% rename from R/seqCluster.R rename to R/v0_seqCluster.R index 8bbb37db..2f234240 100644 --- a/R/seqCluster.R +++ b/R/v0_seqCluster.R @@ -2,27 +2,30 @@ #' #' @concept seq_cluster #' -#' @importFrom purrr map map_lgl map_chr map2 map2_chr map_df map2_lgl pmap map2_df #' @importFrom magrittr %>% %<>% #' @importFrom reshape2 melt #' @importFrom dplyr group_by mutate ungroup select cur_group_id left_join -#' @importFrom igraph graph_from_data_frame clusters #' @importFrom reshape2 melt #' @importFrom tibble rownames_to_column #' @importFrom glue glue +#' @importFrom purrr map_chr #' -#' @description Graph clustering based on distances between sequences +#' @description +#' +#' `r lifecycle::badge("deprecated")` +#' +#' Graph clustering based on distances between sequences #' #' @usage #' #' seqCluster(.data, .dist, .perc_similarity, .nt_similarity, .fixed_threshold) #' -#' @param .data The data which was used to caluculate .dist object. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data which was used to caluculate .dist object. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' -#' Every object must have columns in the immunarch compatible format \link{immunarch_data_format} +#' Every object must have columns in the immunarch compatible format [immunarch_data_format] #' -#' @param .dist List of distance objects produced with \link{seqDist} function. +#' @param .dist List of distance objects produced with [seqDist] function. #' #' @param .perc_similarity Numeric value between 0 and 1 specifying the maximum acceptable weight of an edge in a graph. #' This threshold depends on the length of sequences. @@ -35,15 +38,20 @@ #' Immdata data format object. Same as .data, but with extra 'Cluster' column with clusters assigned. #' #' @examples -#' +#' \dontrun{ #' data(immdata) #' # In this example, we will use only 2 samples with 500 clonotypes in each for time saving #' input_data <- lapply(immdata$data[1:2], head, 500) #' dist_result <- seqDist(input_data) #' cluster_result <- seqCluster(input_data, dist_result, .fixed_threshold = 1) +#' } #' @export seqCluster seqCluster <- function(.data, .dist, .perc_similarity, .nt_similarity, .fixed_threshold = 10) { + if (!requireNamespace("igraph", quietly = TRUE)) { + stop("Package 'igraph' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + grouping_cols <- attr(.dist, "group_by") matching_col <- attr(.dist, "col") trimmed <- attr(.dist, "trimmed") @@ -92,7 +100,7 @@ seqCluster <- function(.data, .dist, .perc_similarity, .nt_similarity, .fixed_th threshold <- map(seq_length, ~ .x %>% threshold_fun()) group_values <- map_dfr(dist_list, ~ attr(.x, "group_values")) if (all(is.na(grouping_cols))) { - protocluster_names <- map_chr(seq_labels, 1) + protocluster_names <- purrr::map_chr(seq_labels, 1) result_single <- data.frame( Sequence = unlist(seq_labels[singleseq_flag]), Cluster = paste0( @@ -122,8 +130,8 @@ seqCluster <- function(.data, .dist, .perc_similarity, .nt_similarity, .fixed_th ifelse(x > t, NA, x) }, .y)) seq_clusters <- map(mat_dist, ~ melt(.x, na.rm = TRUE) %>% - graph_from_data_frame() %>% - clusters() %>% + igraph::graph_from_data_frame() %>% + igraph::clusters() %>% .$membership %>% melt() %>% suppressWarnings()) diff --git a/R/shiny.R b/R/v0_shiny.R similarity index 61% rename from R/shiny.R rename to R/v0_shiny.R index dd5d0f88..79d63672 100644 --- a/R/shiny.R +++ b/R/v0_shiny.R @@ -10,13 +10,12 @@ if (getRversion() >= "2.15.1") { #' @aliases fixVis #' #' @importFrom graphics plot -#' @importFrom shiny fluidPage titlePanel sidebarLayout sidebarPanel downloadButton actionButton br -#' @importFrom shiny tabsetPanel tabPanel textOutput sliderInput checkboxInput selectInput textInput textAreaInput -#' @importFrom shiny mainPanel uiOutput renderText renderUI renderPlot plotOutput observe updateSliderInput -#' @importFrom shiny observeEvent downloadHandler splitLayout -#' @importFrom shinythemes shinytheme #' -#' @description The \code{fixVis} is a built-in software tool for the manipulation +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' The `fixVis` is a built-in software tool for the manipulation #' of plots, such as adjusting title text font and size, axes, and more. It is a powerful #' tool designed to produce publication-ready plots with minimal amount of coding. #' @@ -41,43 +40,50 @@ fixVis <- function(.plot = NA) { objs <- list(title = .name) - objs <- c(objs, list(br())) + objs <- c(objs, list(shiny::br())) if (.is.title) { objs <- c(objs, list( - splitLayout( + shiny::splitLayout( cellWidths = c("60%", "40%"), - checkboxInput(.full("remove"), "Remove the legend"), - checkboxInput(.full("contin"), "Continuous?") + shiny::checkboxInput(.full("remove"), "Remove the legend"), + shiny::checkboxInput(.full("contin"), "Continuous?") ), - sliderInput(.full("ncol"), "Number of columns:", + shiny::sliderInput(.full("ncol"), "Number of columns:", min = 1, max = 40, value = 1, step = 1 ), - br(), - textInput(.full("text"), "Title text:", .name, placeholder = "Samples") + shiny::br(), + shiny::textInput(.full("text"), "Title text:", .name, placeholder = "Samples") )) } objs <- c(objs, list( - sliderInput(.full("size"), "Text size:", + shiny::sliderInput(.full("size"), "Text size:", min = 1, max = 40, value = ifelse(.is.title, 16, 11), step = .5 ), - sliderInput(.full("hjust"), "Text horizontal adjustment:", + shiny::sliderInput(.full("hjust"), "Text horizontal adjustment:", min = 0, max = 1, value = 0, step = .05 ), - sliderInput(.full("vjust"), "Text vertical adjustment:", + shiny::sliderInput(.full("vjust"), "Text vertical adjustment:", min = -4, max = 4, value = .5, step = .25 ), - sliderInput(.full("angle"), "Text angle:", + shiny::sliderInput(.full("angle"), "Text angle:", min = 0, max = 90, value = 0, step = 1 ), - selectInput( + shiny::selectInput( .full("face"), "Face:", list(Plain = "plain", Bold = "bold", Italic = "italic", "Bold Italic" = "bold.italic") ) )) - do.call(tabPanel, objs) + do.call(shiny::tabPanel, objs) + } + + if (!requireNamespace("shinythemes", quietly = TRUE)) { + stop("Package 'shinythemes' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + if (!requireNamespace("shiny", quietly = TRUE)) { + stop("Package 'shiny' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) } if (has_no_data(.plot)) { @@ -88,28 +94,28 @@ fixVis <- function(.plot = NA) { # #### UI #### # - ui <- fluidPage( - theme = shinytheme("cosmo"), - titlePanel("FixVis: make your plots publication-ready already!"), - sidebarLayout( - sidebarPanel( - downloadButton("save_plot", "Save"), - actionButton("console_plot", "Plot to R console"), - br(), - br(), - tabsetPanel( - tabPanel( + ui <- shiny::fluidPage( + theme = shinythemes::shinytheme("cosmo"), + shiny::titlePanel("FixVis: make your plots publication-ready already!"), + shiny::sidebarLayout( + shiny::sidebarPanel( + shiny::downloadButton("save_plot", "Save"), + shiny::actionButton("console_plot", "Plot to R console"), + shiny::br(), + shiny::br(), + shiny::tabsetPanel( + shiny::tabPanel( "General", - br(), - textOutput("save_text"), - br(), - # textOutput("save_text2"), - # br(), - sliderInput("plot_width", "Plot width (in):", min = 2, max = 24, value = 8), - sliderInput("plot_height", "Plot height (in):", min = 2, max = 20, value = 5), - checkboxInput("coord_flip", "Flip coordinates"), - # checkboxInput("do_interactive", "Interactive plot"), - selectInput("ggplot_theme", "Theme", + shiny::br(), + shiny::textOutput("save_text"), + shiny::br(), + # shiny::textOutput("save_text2"), + # shiny::br(), + shiny::sliderInput("plot_width", "Plot width (in):", min = 2, max = 24, value = 8), + shiny::sliderInput("plot_height", "Plot height (in):", min = 2, max = 20, value = 5), + shiny::checkboxInput("coord_flip", "Flip coordinates"), + # shiny::checkboxInput("do_interactive", "Interactive plot"), + shiny::selectInput("ggplot_theme", "Theme", selected = "Pubr", list( "Linedraw", @@ -124,60 +130,60 @@ fixVis <- function(.plot = NA) { ) ) ), - tabPanel( + shiny::tabPanel( "Title & subtitle", - br(), - tabsetPanel( - tabPanel( + shiny::br(), + shiny::tabsetPanel( + shiny::tabPanel( "Title", - br(), - textInput("title_text", "Title text:", "nice title text", placeholder = "Gene usage"), - sliderInput("title_text_size", "Title text size:", + shiny::br(), + shiny::textInput("title_text", "Title text:", "nice title text", placeholder = "Gene usage"), + shiny::sliderInput("title_text_size", "Title text size:", min = 1, max = 40, value = 25, step = .5 ), - sliderInput("title_text_hjust", "Title text horizontal adjustment:", + shiny::sliderInput("title_text_hjust", "Title text horizontal adjustment:", min = 0, max = 1, value = 0, step = .05 ), - sliderInput("title_text_vjust", "Title text vertical adjustment:", + shiny::sliderInput("title_text_vjust", "Title text vertical adjustment:", min = -4, max = 4, value = .5, step = .25 ), - sliderInput("title_text_angle", "Title text angle:", + shiny::sliderInput("title_text_angle", "Title text angle:", min = 0, max = 90, value = 0, step = 1 ), - selectInput( + shiny::selectInput( "title_face", "Face:", list(Plain = "plain", Bold = "bold", Italic = "italic", "Bold Italic" = "bold.italic") ) ), - tabPanel( + shiny::tabPanel( "Subtitle", - br(), - textAreaInput("subtitle_text", "Subtitle text:", "nice subtitle text", + shiny::br(), + shiny::textAreaInput("subtitle_text", "Subtitle text:", "nice subtitle text", placeholder = "Frequency of Variable gene segments presented in the input samples" ), - sliderInput("subtitle_text_size", "Subtitle text size:", + shiny::sliderInput("subtitle_text_size", "Subtitle text size:", min = 1, max = 40, value = 16, step = .5 ), - sliderInput("subtitle_text_hjust", "Subtitle text horizontal adjustment:", + shiny::sliderInput("subtitle_text_hjust", "Subtitle text horizontal adjustment:", min = 0, max = 1, value = 0, step = .05 ), - sliderInput("subtitle_text_vjust", "Subtitle text vertical adjustment:", + shiny::sliderInput("subtitle_text_vjust", "Subtitle text vertical adjustment:", min = -4, max = 4, value = .5, step = .25 ), - sliderInput("subtitle_text_angle", "Subtitle text angle:", + shiny::sliderInput("subtitle_text_angle", "Subtitle text angle:", min = 0, max = 90, value = 0, step = 1 ), - selectInput( + shiny::selectInput( "subtitle_face", "Face:", list(Plain = "plain", Bold = "bold", Italic = "italic", "Bold Italic" = "bold.italic") ) ) ) ), - tabPanel( + shiny::tabPanel( "Legends", - br(), - selectInput( + shiny::br(), + shiny::selectInput( "legend_position", "Legend position", list( "right", @@ -186,143 +192,143 @@ fixVis <- function(.plot = NA) { "left" ) ), - selectInput( + shiny::selectInput( "legend_box", "Legend arrangement", list( "vertical", "horizontal" ) ), - tabsetPanel( - tabPanel( + shiny::tabsetPanel( + shiny::tabPanel( "Color", - tabsetPanel( + shiny::tabsetPanel( make_legend_tab("col_title", "Title (color)", TRUE), make_legend_tab("col_text", "Labels (color)", FALSE) ) ), - tabPanel( + shiny::tabPanel( "Fill", - tabsetPanel( + shiny::tabsetPanel( make_legend_tab("fill_title", "Title (fill)", TRUE), make_legend_tab("fill_text", "Labels (fill)", FALSE) ) ), - tabPanel( + shiny::tabPanel( "Size", - tabsetPanel( + shiny::tabsetPanel( make_legend_tab("size_title", "Title (size)", TRUE), make_legend_tab("size_text", "Labels (size)", FALSE) ) ), - tabPanel( + shiny::tabPanel( "Shape", - tabsetPanel( + shiny::tabsetPanel( make_legend_tab("shape_title", "Title (shape)", TRUE), make_legend_tab("shape_text", "Labels (shape)", FALSE) ) ), - tabPanel( + shiny::tabPanel( "Linetype", - tabsetPanel( + shiny::tabsetPanel( make_legend_tab("linetype_title", "Title (linetype)", TRUE), make_legend_tab("linetype_text", "Labels (linetype)", FALSE) ) ) ) ), - tabPanel( + shiny::tabPanel( "X axis", - br(), - tabsetPanel( - tabPanel( + shiny::br(), + shiny::tabsetPanel( + shiny::tabPanel( "X title", - br(), - textInput("x_text", "X axis label:", "x axis text", placeholder = "V genes"), - checkboxInput("apply_x2y", "Apply X axis settings to Y axis"), - br(), - sliderInput("x_title_size", "X axis title text size:", + shiny::br(), + shiny::textInput("x_text", "X axis label:", "x axis text", placeholder = "V genes"), + shiny::checkboxInput("apply_x2y", "Apply X axis settings to Y axis"), + shiny::br(), + shiny::sliderInput("x_title_size", "X axis title text size:", min = 1, max = 40, value = 16, step = .5 ), - sliderInput("x_title_hjust", "X axis title text horizontal adjustment:", + shiny::sliderInput("x_title_hjust", "X axis title text horizontal adjustment:", min = 0, max = 1, value = 0.5, step = .05 ), - sliderInput("x_title_vjust", "X axis title text vertical adjustment:", + shiny::sliderInput("x_title_vjust", "X axis title text vertical adjustment:", min = -4, max = 4, value = .5, step = .25 ), - sliderInput("x_title_angle", "X axis title text angle:", + shiny::sliderInput("x_title_angle", "X axis title text angle:", min = 0, max = 90, value = 0, step = 1 ), - selectInput( + shiny::selectInput( "x_title_face", "Face:", list(Plain = "plain", Bold = "bold", Italic = "italic", "Bold Italic" = "bold.italic") ) ), - tabPanel( + shiny::tabPanel( "X ticks", - br(), - sliderInput("x_text_size", "X axis text size:", + shiny::br(), + shiny::sliderInput("x_text_size", "X axis text size:", min = 1, max = 40, value = 11, step = .5 ), - sliderInput("x_text_hjust", "X axis text horizontal adjustment:", + shiny::sliderInput("x_text_hjust", "X axis text horizontal adjustment:", min = -2, max = 2, value = .5, step = .1 ), - sliderInput("x_text_vjust", "X axis text vertical adjustment:", + shiny::sliderInput("x_text_vjust", "X axis text vertical adjustment:", min = -4, max = 4, value = .5, step = .25 ), - sliderInput("x_text_angle", "X axis text angle:", + shiny::sliderInput("x_text_angle", "X axis text angle:", min = 0, max = 90, value = 90, step = 1 ), - selectInput( + shiny::selectInput( "x_text_face", "Face:", list(Plain = "plain", Bold = "bold", Italic = "italic", "Bold Italic" = "bold.italic") ) ) ) ), - tabPanel( + shiny::tabPanel( "Y axis", - br(), - tabsetPanel( - tabPanel( + shiny::br(), + shiny::tabsetPanel( + shiny::tabPanel( "Y title", - br(), - textInput("y_text", "Y axis label:", "y axis text", placeholder = "Gene frequency"), - checkboxInput("apply_y2x", "Apply Y axis settings to X axis"), - br(), - sliderInput("y_title_size", "Y axis title text size:", + shiny::br(), + shiny::textInput("y_text", "Y axis label:", "y axis text", placeholder = "Gene frequency"), + shiny::checkboxInput("apply_y2x", "Apply Y axis settings to X axis"), + shiny::br(), + shiny::sliderInput("y_title_size", "Y axis title text size:", min = 1, max = 40, value = 16, step = .5 ), - sliderInput("y_title_hjust", "Y axis title text horizontal adjustment:", + shiny::sliderInput("y_title_hjust", "Y axis title text horizontal adjustment:", min = 0, max = 1, value = 0.5, step = .05 ), - sliderInput("y_title_vjust", "Y axis title text vertical adjustment:", + shiny::sliderInput("y_title_vjust", "Y axis title text vertical adjustment:", min = -4, max = 4, value = .5, step = .25 ), - sliderInput("y_title_angle", "Y axis title text angle:", + shiny::sliderInput("y_title_angle", "Y axis title text angle:", min = 0, max = 90, value = 90, step = 1 ), - selectInput( + shiny::selectInput( "y_title_face", "Face:", list(Plain = "plain", Bold = "bold", Italic = "italic", "Bold Italic" = "bold.italic") ) ), - tabPanel( + shiny::tabPanel( "Y ticks", - br(), - sliderInput("y_text_size", "Y axis text size:", + shiny::br(), + shiny::sliderInput("y_text_size", "Y axis text size:", min = 1, max = 40, value = 11, step = .5 ), - sliderInput("y_text_hjust", "Y axis text horizontal adjustment:", + shiny::sliderInput("y_text_hjust", "Y axis text horizontal adjustment:", min = -2, max = 2, value = .5, step = .1 ), - sliderInput("y_text_vjust", "Y axis text vertical adjustment:", + shiny::sliderInput("y_text_vjust", "Y axis text vertical adjustment:", min = -4, max = 4, value = .5, step = .25 ), - sliderInput("y_text_angle", "Y axis text angle:", + shiny::sliderInput("y_text_angle", "Y axis text angle:", min = 0, max = 90, value = 0, step = 1 ), - selectInput( + shiny::selectInput( "y_text_face", "Face:", list(Plain = "plain", Bold = "bold", Italic = "italic", "Bold Italic" = "bold.italic") ) @@ -331,8 +337,8 @@ fixVis <- function(.plot = NA) { ) ) ), - mainPanel( - uiOutput("main_plot", style = "position:fixed;") + shiny::mainPanel( + shiny::uiOutput("main_plot", style = "position:fixed;") ) ) ) @@ -476,40 +482,40 @@ fixVis <- function(.plot = NA) { .plot } - output$save_text <- renderText({ + output$save_text <- shiny::renderText({ 'To save the plot, press the "Save" button above or drag-n-drop the plot to your Desktop or into any file manager (Finder, File Explorer, etc.)' }) - output$save_text2 <- renderText({ + output$save_text2 <- shiny::renderText({ 'Note: saving via the "Save" button will be different from the drag-n-drop method due to R\'s peculiar properties.' }) - output$main_plot <- renderUI({ + output$main_plot <- shiny::renderUI({ # if (input$do_interactive) { # output$main_plot_helper = renderPlotly(ggplotly(create_plot(input))) # plotlyOutput("main_plot_helper") # } else { - output$main_plot_helper <- renderPlot(create_plot(input)) - plotOutput("main_plot_helper", width = input$plot_width * 72, height = input$plot_height * 72) + output$main_plot_helper <- shiny::renderPlot(create_plot(input)) + shiny::plotOutput("main_plot_helper", width = input$plot_width * 72, height = input$plot_height * 72) # } }) # # Assign X settings to Y # - observe({ + shiny::observe({ if (!is.null(input$apply_x2y)) { if (input$apply_x2y) { - updateSliderInput(session, "y_title_size", value = input$x_title_size) - updateSliderInput(session, "y_title_hjust", value = input$x_title_size) - updateSliderInput(session, "y_title_vjust", value = input$x_title_size) - updateSliderInput(session, "y_title_angle", value = input$x_title_size) + shiny::updateSliderInput(session, "y_title_size", value = input$x_title_size) + shiny::updateSliderInput(session, "y_title_hjust", value = input$x_title_size) + shiny::updateSliderInput(session, "y_title_vjust", value = input$x_title_size) + shiny::updateSliderInput(session, "y_title_angle", value = input$x_title_size) - updateSliderInput(session, "y_text_size", value = input$x_text_size) - updateSliderInput(session, "y_text_hjust", value = input$x_text_size) - updateSliderInput(session, "y_text_vjust", value = input$x_text_size) - updateSliderInput(session, "y_text_angle", value = input$x_text_size) + shiny::updateSliderInput(session, "y_text_size", value = input$x_text_size) + shiny::updateSliderInput(session, "y_text_hjust", value = input$x_text_size) + shiny::updateSliderInput(session, "y_text_vjust", value = input$x_text_size) + shiny::updateSliderInput(session, "y_text_angle", value = input$x_text_size) } } }) @@ -517,30 +523,30 @@ fixVis <- function(.plot = NA) { # # Vice versa: assign Y settings to X # - observe({ + shiny::observe({ if (!is.null(input$apply_y2x)) { if (input$apply_y2x) { - updateSliderInput(session, "x_title_size", value = input$y_title_size) - updateSliderInput(session, "x_title_hjust", value = input$y_title_hjust) - updateSliderInput(session, "x_title_vjust", value = input$y_title_vjust) - updateSliderInput(session, "x_title_angle", value = input$y_title_angle) + shiny::updateSliderInput(session, "x_title_size", value = input$y_title_size) + shiny::updateSliderInput(session, "x_title_hjust", value = input$y_title_hjust) + shiny::updateSliderInput(session, "x_title_vjust", value = input$y_title_vjust) + shiny::updateSliderInput(session, "x_title_angle", value = input$y_title_angle) - updateSliderInput(session, "x_text_size", value = input$y_text_size) - updateSliderInput(session, "x_text_hjust", value = input$y_text_hjust) - updateSliderInput(session, "x_text_vjust", value = input$y_text_vjust) - updateSliderInput(session, "x_text_angle", value = input$y_text_angle) + shiny::updateSliderInput(session, "x_text_size", value = input$y_text_size) + shiny::updateSliderInput(session, "x_text_hjust", value = input$y_text_hjust) + shiny::updateSliderInput(session, "x_text_vjust", value = input$y_text_vjust) + shiny::updateSliderInput(session, "x_text_angle", value = input$y_text_angle) } } }) - observeEvent(input$console_plot, { + shiny::observeEvent(input$console_plot, { plot(create_plot(input)) }) # # Save plots # - output$save_plot <- downloadHandler( + output$save_plot <- shiny::downloadHandler( filename = paste0("plot shiny ", Sys.time(), ".png"), content = function(file) { ggsave(file, plot = create_plot(input), width = input$plot_width, height = input$plot_height, device = "png") diff --git a/R/singlecell.R b/R/v0_singlecell.R similarity index 90% rename from R/singlecell.R rename to R/v0_singlecell.R index b2074882..1bd14853 100644 --- a/R/singlecell.R +++ b/R/v0_singlecell.R @@ -9,26 +9,30 @@ if (getRversion() >= "2.15.1") { #' #' @concept single_cell #' -#' @description Subsets the input immune repertoire by barcodes. Creates a vector of +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Subsets the input immune repertoire by barcodes. Creates a vector of #' barcodes to subset or a vector cluster IDs and corresponding barcodes to #' get a list of immune repertoires corresponding to cluster IDs. #' Columns with clonotype counts #' and proportions are changed accordingly to the filtered barcodes. #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. #' #' @param .barcodes Either a character vector with barcodes or a named character/factor vector with -#' barcodes as names and cluster IDs a vector elements. The output of Seurat's \code{Idents} function works. +#' barcodes as names and cluster IDs a vector elements. The output of Seurat's `Idents` function works. #' #' @param .force.list Logical. If TRUE then always returns a list, even if the result is one data frame. #' @@ -37,7 +41,7 @@ if (getRversion() >= "2.15.1") { #' with clonotype barcodes corresponding to the input barcodes. The output list names are cluster names #' in the ".barcode" argument (Seurat::Idents() case only). #' -#' @seealso \link{select_clusters} +#' @seealso [select_clusters] #' #' @examples #' \dontrun{ @@ -120,7 +124,11 @@ select_barcodes <- function(.data, .barcodes, .force.list = FALSE) { #' #' @concept single_cell #' -#' @description Given the vector of barcodes from Seurat, splits the input repertoires +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Given the vector of barcodes from Seurat, splits the input repertoires #' to separate subsets following the barcodes' assigned IDs. Useful in case you want to #' split immune repertoires by patients or clusters. #' @@ -128,7 +136,7 @@ select_barcodes <- function(.data, .barcodes, .force.list = FALSE) { #' immune repertoires, and "meta" being a metadata table. #' #' @param .clusters Factor vector with barcodes as vector names and cluster IDs as vector elements. -#' The output of the Seurat \code{Idents} function works. +#' The output of the Seurat `Idents` function works. #' #' @param .field A string specifying the name of the field in the input metadata. New immune #' repertoire subsets will have cluster IDs in this field. @@ -136,7 +144,7 @@ select_barcodes <- function(.data, .barcodes, .force.list = FALSE) { #' @return A list with two elements "data" and "meta" with updated immune repertoire tables and #' metadata. #' -#' @seealso \link{select_barcodes} +#' @seealso [select_barcodes] #' #' @examples #' \dontrun{ diff --git a/R/somatic_hypermutation.R b/R/v0_somatic_hypermutation.R similarity index 97% rename from R/somatic_hypermutation.R rename to R/v0_somatic_hypermutation.R index 8d6bed7b..bb220256 100644 --- a/R/somatic_hypermutation.R +++ b/R/v0_somatic_hypermutation.R @@ -11,7 +11,11 @@ #' @importFrom doParallel registerDoParallel stopImplicitCluster #' @importFrom ape as.DNAbin clustal #' -#' @description This function aligns V and J genes from the germline in each cluster +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' This function aligns V and J genes from the germline in each cluster #' with corresponding genes in each clonotype, saves the alignments for purpose of visualization, #' and calculates number of mutations for each clonotype. #' diff --git a/R/spectratyping.R b/R/v0_spectratyping.R similarity index 94% rename from R/spectratyping.R rename to R/v0_spectratyping.R index b1670076..d387fe20 100644 --- a/R/spectratyping.R +++ b/R/v0_spectratyping.R @@ -4,14 +4,19 @@ #' #' @importFrom dplyr summarise group_by #' -#' @param .data The data to be processed. Can be \link{data.frame}, -#' \link{data.table}, or a list of these objects. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data The data to be processed. Can be [data.frame], +#' [data.table::data.table], or a list of these objects. #' #' Every object must have columns in the immunarch compatible format. -#' \link{immunarch_data_format} +#' [immunarch_data_format] #' #' Competent users may provide advanced data representations: -#' DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +#' DBI database connections, or a list #' of these objects. They are supported with the same limitations as basic objects. #' #' Note: each connection must represent a separate repertoire. diff --git a/R/tools.R b/R/v0_tools.R similarity index 98% rename from R/tools.R rename to R/v0_tools.R index 383d0818..8d4408d6 100644 --- a/R/tools.R +++ b/R/v0_tools.R @@ -73,7 +73,7 @@ check_distribution <- function(.data, .do.norm = NA, .laplace = 1, .na.val = 0, #' @param .class String with the desired class name. #' #' @return -#' Input object with additional class \code{.class}. +#' Input object with additional class `.class`. #' #' @section Developer Examples: #' tmp <- "abc" @@ -125,7 +125,7 @@ get_empty_object_with_class <- function(.class) { #' add_pb(.pb, .value = 1) #' #' @param .max Integer. Maximal value of the progress bar. -#' @param .pb Progress bar object from \code{set_pb}. +#' @param .pb Progress bar object from `set_pb`. #' @param .value Numeric. Value to add to the progress bar at each step. #' #' @return @@ -189,7 +189,7 @@ add_pb <- function(.pb, .value = 1) { #' @section Developer Examples: #' mat <- matrix(0, 3, 3) #' mat -#' mat[1, 3] <- 1 +#' mat(1, 3) <- 1 #' mat <- immunarch:::matrixdiagcopy(mat) #' mat matrixdiagcopy <- function(.mat) { @@ -276,7 +276,7 @@ check_group_names <- function(.meta, .by) { #' #' @param .by Character vector. Specify a column or columns in the input metadata to group by. #' @param .metadata Metadata object. -#' @param .sep Character vector. Defines a separator between groups if more than one group passed in \code{.by}. +#' @param .sep Character vector. Defines a separator between groups if more than one group passed in `.by`. #' #' @return #' Character vector with group names. @@ -362,7 +362,7 @@ rename_column <- function(.data, .old, .new) { #' @param .diag Either NA for NA or something else != NULL for .fun(x,x). #' @param .verbose if TRUE then output a progress bar. #' -#' @return Matrix with values M[i,j] = fun(datalist[i], datalist[j]) +#' @return Matrix with values M(i,j) = fun(datalist(i), datalist(j)) #' #' @examples #' data(immdata) @@ -510,7 +510,7 @@ apply_to_sample_or_list <- function(.data, .function, .with_names = FALSE, .vali } if (.with_names) { .data %<>% - purrr::imap(function(sample_data, sample_name) { + imap(function(sample_data, sample_name) { sample_data %>% as_tibble() %>% .function(..., sample_name = sample_name) @@ -624,7 +624,7 @@ require_system_package <- function(executable_names, if (.nofail & .prev_failed) { return(FALSE) } - package_not_exist <- all(unlist(purrr::map(Sys.which(executable_names), identical, ""))) + package_not_exist <- all(unlist(map(Sys.which(executable_names), identical, ""))) if (package_not_exist) { if (.nofail) { cat(error_message) diff --git a/R/vis.R b/R/v0_vis.R similarity index 85% rename from R/vis.R rename to R/v0_vis.R index 164cdf87..bf52c686 100644 --- a/R/vis.R +++ b/R/v0_vis.R @@ -12,6 +12,69 @@ if (getRversion() >= "2.15.1") { )) } +theme_pubr <- function(base_size = 12, base_family = "", border = FALSE, margin = TRUE, + legend = c("top", "bottom", "left", "right", "none"), x.text.angle = 0) { + half_line <- base_size / 2 + if (!is.numeric(legend)) { + legend <- match.arg(legend) + } + if (x.text.angle > 5) { + xhjust <- 1 + } else { + xhjust <- NULL + } + if (border) { + panel.border <- element_rect( + fill = NA, colour = "black", + size = 0.7 + ) + axis.line <- element_blank() + } else { + panel.border <- element_blank() + axis.line <- element_line(colour = "black", size = 0.5) + } + if (margin) { + plot.margin <- margin( + half_line, half_line, half_line, + half_line + ) + } else { + plot.margin <- unit(c(0.5, 0.3, 0.3, 0.3), "mm") + } + .theme <- theme_bw(base_size = base_size, base_family = base_family) %+replace% + theme( + panel.border = panel.border, panel.grid.major = element_blank(), + panel.grid.minor = element_blank(), axis.line = axis.line, + axis.text = element_text(color = "black"), legend.key = element_blank(), + strip.background = element_rect( + fill = "#F2F2F2", + colour = "black", size = 0.7 + ), plot.margin = plot.margin, + legend.position = legend, complete = TRUE + ) + if (x.text.angle != 0) { + .theme <- .theme + theme(axis.text.x = element_text( + angle = x.text.angle, + hjust = xhjust + )) + } + .theme +} + + +rotate_x_text <- function(angle = 90, hjust = NULL, vjust = NULL, ...) { + if (missing(hjust) & angle > 5) { + hjust <- 1 + } + if (missing(vjust) & angle == 90) { + vjust <- 0.5 + } + theme(axis.text.x = element_text( + angle = angle, hjust = hjust, + vjust = vjust, ... + )) +} + ##### Utility functions ##### @@ -105,20 +168,21 @@ theme_cleveland2 <- function(rotate = TRUE) { #' @name vis #' #' @import ggplot2 -#' @importFrom factoextra fviz_cluster fviz_dend fviz_pca_ind #' @importFrom grDevices colorRampPalette #' @importFrom tidyr drop_na -#' @importFrom igraph graph_from_data_frame -#' @importFrom ggraph ggraph geom_edge_diagonal geom_node_point theme_graph #' -#' @description Output from every function in immunarch can be visualised with a -#' single function - \code{vis}. The \code{vis} automatically detects +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Output from every function in immunarch can be visualised with a +#' single function - `vis`. The `vis` automatically detects #' the type of the data and draws a proper visualisation. For example, output -#' from the \code{repOverlap} function will be identified as repertoire overlap values +#' from the `repOverlap` function will be identified as repertoire overlap values #' and respective visualisation will be chosen without any additional arguments. #' See "Details" for the list of available visualisations. #' -#' @param .data Pass the output from any immunarch analysis tool to \code{vis()}. +#' @param .data Pass the output from any immunarch analysis tool to `vis()`. #' @param ... Any other arguments, see the "Details" section for specific visualisation functions. #' #' @details @@ -126,43 +190,43 @@ theme_cleveland2 <- function(rotate = TRUE) { #' #' Basic analysis: #' -#' - Exploratory analysis results (from \link{repExplore}) - see \link{vis.immunr_exp_vol}; +#' - Exploratory analysis results (from [repExplore]) - see [vis.immunr_exp_vol]; #' -#' - Clonality statistics (from \link{repClonality}) - see \link{vis.immunr_homeo}. +#' - Clonality statistics (from [repClonality]) - see [vis.immunr_homeo]. #' #' Overlaps and public clonotypes: #' -#' - Overlaps (from \link{repOverlap}) using heatmaps, circos plots, polar area plots - see \link{vis.immunr_ov_matrix}; +#' - Overlaps (from [repOverlap]) using heatmaps, circos plots, polar area plots - see [vis.immunr_ov_matrix]; #' -#' - Overlap clustering (from \link{repOverlapAnalysis}) - see \link{vis.immunr_hclust}; +#' - Overlap clustering (from [repOverlapAnalysis]) - see [vis.immunr_hclust]; #' -#' - Repertoire incremental overlaps (from \link{repOverlap}) - see \link{vis.immunr_inc_overlap}; +#' - Repertoire incremental overlaps (from [repOverlap]) - see [vis.immunr_inc_overlap]; #' -#' - Public repertoire abundance (from \link{pubRep}) - vis \link{vis.immunr_public_repertoire}. +#' - Public repertoire abundance (from [pubRep]) - vis [vis.immunr_public_repertoire]. #' #' Gene usage: #' -#' - Gene usage statistics (from \link{geneUsage}) using bar plots, box plots - see \link{vis.immunr_gene_usage}; +#' - Gene usage statistics (from [geneUsage]) using bar plots, box plots - see [vis.immunr_gene_usage]; #' -#' - Gene usage distances (from \link{geneUsageAnalysis}) using heatmaps, circos plots, polar area plots - see \link{vis.immunr_ov_matrix}; +#' - Gene usage distances (from [geneUsageAnalysis]) using heatmaps, circos plots, polar area plots - see [vis.immunr_ov_matrix]; #' -#' - Gene usage clustering (from \link{geneUsageAnalysis}) - see \link{vis.immunr_hclust}. +#' - Gene usage clustering (from [geneUsageAnalysis]) - see [vis.immunr_hclust]. #' #' Diversity estimation: #' -#' - Diversity estimations (from \link{repDiversity}) - see \link{vis.immunr_chao1}. +#' - Diversity estimations (from [repDiversity]) - see [vis.immunr_chao1]. #' #' BCR analysis: #' -#' - Clonal tree (from \link{repClonalFamily}) - see \link{vis.clonal_family} and \link{vis.clonal_family_tree}. +#' - Clonal tree (from [repClonalFamily]) - see [vis.clonal_family] and [vis.clonal_family_tree]. #' #' Advanced analysis: #' -#' - Repertoire dynamics (from \link{trackClonotypes}) - see \link{vis.immunr_dynamics}; +#' - Repertoire dynamics (from [trackClonotypes]) - see [vis.immunr_dynamics]; #' -#' - Sequence logo plots of amino acid distributions (from \link{kmer_profile}) - see \link{vis_seqlogo}; +#' - Sequence logo plots of amino acid distributions (from [kmer_profile]) - see [vis_seqlogo]; #' -#' - Kmers distributions (from \link{getKmers}) - see \link{vis.immunr_kmer_table}; +#' - Kmers distributions (from [getKmers]) - see [vis.immunr_kmer_table]; #' #' - Mutation networks (from mutationNetwork) - Work In Progress on vis.immunr_mutation_network; #' @@ -170,14 +234,14 @@ theme_cleveland2 <- function(rotate = TRUE) { #' #' Additionaly, we provide a wrapper functions for visualisations of common data types: #' -#' - Any data frames or matrices using heatmaps - see \link{vis_heatmap} and \link{vis_heatmap2}; +#' - Any data frames or matrices using heatmaps - see [vis_heatmap] and [vis_heatmap2]; #' -#' - Any data frames or matrices using circos plots - see \link{vis_circos}. +#' - Any data frames or matrices using circos plots - see [vis_circos]. #' #' @return #' A ggplot2, pheatmap or circlize object. #' -#' @seealso \link{fixVis} for precise manipulation of plots. +#' @seealso [fixVis] for precise manipulation of plots. #' #' @examples #' # Load the test data @@ -209,26 +273,30 @@ vis <- function(.data, ...) { #' #' @aliases vis.immunr_ov_matrix vis.immunr_gu_matrix #' -#' @description Visualises matrices with overlap values or gene usage distances among samples. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Visualises matrices with overlap values or gene usage distances among samples. #' For details see the links below. #' -#' @param .data Output from \link{repOverlap} or \link{geneUsageAnalysis}. +#' @param .data Output from [repOverlap] or [geneUsageAnalysis]. #' #' @param .plot A string specifying the plot type: #' -#' - "heatmap" for heatmaps using \link{vis_heatmap}; +#' - "heatmap" for heatmaps using [vis_heatmap]; #' -#' - "heatmap2" for heatmaps using \link{vis_heatmap2}; +#' - "heatmap2" for heatmaps using [vis_heatmap2]; #' -#' - "circos" for circos plots using \link{vis_circos}; +#' - "circos" for circos plots using [vis_circos]; #' #' @param ... Other arguments are passed through to the underlying plotting function: #' -#' - "heatmap" - passes arguments to \link{vis_heatmap}; +#' - "heatmap" - passes arguments to [vis_heatmap]; #' -#' - "heatmap2" - passes arguments to \link{vis_heatmap2} and \link{heatmap} from the "pheatmap" package; +#' - "heatmap2" - passes arguments to [vis_heatmap2] and [heatmap] from the "pheatmap" package; #' -#' - "circos" - passes arguments to \link{vis_circos} and \link{chordDiagram} from the "circlize" package; +#' - "circos" - passes arguments to [vis_circos] and [circlize::chordDiagram] from the "circlize" package; #' #' @return #' A ggplot2, pheatmap or circlize object. @@ -283,7 +351,11 @@ vis.immunr_gu_matrix <- function(.data, .plot = c("heatmap", "heatmap2", "circos #' #' @aliases vis_heatmap #' -#' @description Fast and easy visualisations of matrices or data frames +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Fast and easy visualisations of matrices or data frames #' with functions based on the ggplot2 package. #' #' @param .data Input object: a matrix or a data frame. @@ -321,7 +393,7 @@ vis.immunr_gu_matrix <- function(.data, .plot = c("heatmap", "heatmap2", "circos #' @return #' A ggplot2 object. #' -#' @seealso \link{vis}, \link{repOverlap}. +#' @seealso [vis], [repOverlap]. #' #' @examples #' data(immdata) @@ -411,7 +483,11 @@ vis_heatmap <- function(.data, .text = TRUE, .scientific = FALSE, .signif.digits #' #' @name vis_heatmap2 #' -#' @description Visualise matrices with the functions based on the \link[pheatmap]{pheatmap} +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Visualise matrices with the functions based on the [pheatmap][pheatmap::pheatmap] #' package with minimum amount of arguments. #' #' @param .data Input matrix. Column names and row names (if presented) will be used as names for labs. @@ -421,17 +497,17 @@ vis_heatmap <- function(.data, .text = TRUE, .scientific = FALSE, .signif.digits #' #' @param .by Set NA if you want to plot samples without grouping. #' -#' @param .title The text for the plot's title (same as the "main" argument in \link[pheatmap]{pheatmap}). +#' @param .title The text for the plot's title (same as the "main" argument in [pheatmap][pheatmap::pheatmap]). #' -#' @param .color A vector specifying the colors (same as the "color" argument in \link[pheatmap]{pheatmap}). +#' @param .color A vector specifying the colors (same as the "color" argument in [pheatmap][pheatmap::pheatmap]). #' Pass NA to use the default pheatmap colors. #' -#' @param ... Other arguments for the \link[pheatmap]{pheatmap} function. +#' @param ... Other arguments for the [pheatmap][pheatmap::pheatmap] function. #' #' @return #' A pheatmap object. #' -#' @seealso \link{vis}, \link{repOverlap} +#' @seealso [vis], [repOverlap] #' #' @examples #' data(immdata) @@ -465,19 +541,23 @@ vis_heatmap2 <- function(.data, .meta = NA, .by = NA, .title = NA, .color = colo #' #' @name vis_circos #' -#' @description Visualise matrices with the \link{chordDiagram} function +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Visualise matrices with the [circlize::chordDiagram] function #' from the circlize package. #' #' @param .data Input matrix. #' #' @param .title The The text for the title of the plot. #' -#' @param ... Other arguments passed to \link{chordDiagram} from the 'circlize' package. +#' @param ... Other arguments passed to [circlize::chordDiagram] from the 'circlize' package. #' #' @return #' A circlize object. #' -#' @seealso \link{vis}, \link{repOverlap}. +#' @seealso [vis], [repOverlap]. #' #' @examples #' data(immdata) @@ -583,9 +663,14 @@ vis_circos <- function(.data, .title = NULL, ...) { #' #' @importFrom dplyr rename #' +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' #' @name vis.immunr_inc_overlap #' -#' @param .data Output from the \link{repOverlap} function that uses "top" methods. +#' @param .data Output from the [repOverlap] function that uses "top" methods. #' #' @param .target Index of a repertoire to plot. Omitted if .grid is TRUE. #' @@ -598,7 +683,7 @@ vis_circos <- function(.data, .title = NULL, ...) { #' @return #' A ggplot2 object. #' -#' @seealso \link{repOverlap} +#' @seealso [repOverlap] #' #' @examples #' data(immdata) @@ -681,15 +766,20 @@ vis.immunr_inc_overlap <- function(.data, .target = 1, .grid = FALSE, .ncol = 2, #' #' @name vis.immunr_public_repertoire #' -#' @param .data Public repertoire, an output from \link{pubRep}. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data Public repertoire, an output from [pubRep]. #' @param .plot A string specifying the plot type: #' #' - "freq" for visualisation of the distribution of occurrences of clonotypes -#' and their frequencies using \link{vis_public_frequencies}. +#' and their frequencies using [vis_public_frequencies]. #' #' - "clonotypes" for visualisation of public clonotype frequenciy correlations between pairs of -#' samples using \link{vis_public_clonotypes} -#' @param ... Further arguments passed \link{vis_public_frequencies} or \link{vis_public_clonotypes}, +#' samples using [vis_public_clonotypes] +#' @param ... Further arguments passed [vis_public_frequencies] or [vis_public_clonotypes], #' depending on the ".plot" argument. #' #' @return @@ -720,15 +810,17 @@ vis.immunr_public_repertoire <- function(.data, .plot = c("freq", "clonotypes"), #' #' @concept pubrep #' -#' @importFrom UpSetR upset fromExpression -#' #' @name vis.immunr_public_statistics #' -#' @description Visualise public clonotype frequencies. +#' @description +#' +#' `r lifecycle::badge('deprecated')` #' -#' @param .data Public repertoire - an output from the \link{pubRep} function. +#' Visualise public clonotype frequencies. #' -#' @param ... Other arguments passsed directly to \link{upset}. +#' @param .data Public repertoire - an output from the [pubRep] function. +#' +#' @param ... Other arguments passsed directly to [UpSetR::upset]. #' #' @return #' A ggplot2 object. @@ -740,9 +832,13 @@ vis.immunr_public_repertoire <- function(.data, .plot = c("freq", "clonotypes"), #' pubRepStatistics(pr) %>% vis() #' @export vis.immunr_public_statistics <- function(.data, ...) { + if (!requireNamespace("UpSetR", quietly = TRUE)) { + stop("Package 'UpSetR' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + upsetr_data <- as.list(.data$Count) names(upsetr_data) <- .data$Group - upset(fromExpression(upsetr_data), ...) + UpSetR::upset(UpSetR::fromExpression(upsetr_data), ...) } @@ -752,9 +848,13 @@ vis.immunr_public_statistics <- function(.data, ...) { #' #' @name vis_public_frequencies #' -#' @description Visualise public clonotype frequencies. +#' @description +#' +#' `r lifecycle::badge('deprecated')` #' -#' @param .data Public repertoire - an output from the \link{pubRep} function. +#' Visualise public clonotype frequencies. +#' +#' @param .data Public repertoire - an output from the [pubRep] function. #' @param .by Pass NA if you want to plot samples without grouping. #' #' You can pass a character vector with one or several column names from ".meta" @@ -848,9 +948,13 @@ vis_public_frequencies <- function(.data, .by = NA, .meta = NA, #' @importFrom stats lm #' @importFrom patchwork wrap_plots plot_annotation #' -#' @description Visualise correlation of public clonotype frequencies in pairs of repertoires. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Visualise correlation of public clonotype frequencies in pairs of repertoires. #' -#' @param .data Public repertoire data - an output from the \link{pubRep} function. +#' @param .data Public repertoire data - an output from the [pubRep] function. #' #' @param .x.rep Either indices of samples or character vector of sample names #' for the x-axis. Must be of the same length as ".y.rep". @@ -879,7 +983,7 @@ vis_public_frequencies <- function(.data, .by = NA, .meta = NA, #' @return #' A ggplot2 object. #' -#' @seealso \link{pubRep}, \link{vis.immunr_public_repertoire} +#' @seealso [pubRep], [vis.immunr_public_repertoire] #' #' @examples #' data(immdata) @@ -1051,31 +1155,35 @@ vis_public_clonotypes <- function(.data, .x.rep = NA, .y.rep = NA, #' #' @name vis.immunr_gene_usage #' -#' @description Visualise distributions of genes using heatmaps or other plots. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Visualise distributions of genes using heatmaps or other plots. #' -#' @param .data Output from the \link{geneUsage} function. +#' @param .data Output from the [geneUsage] function. #' #' @param .plot String specifying the plot type: #' -#' - "hist" for histograms using \link{vis_hist}; +#' - "hist" for histograms using [vis_hist]; #' -#' - "heatmap" for heatmaps using \link{vis_heatmap}; +#' - "heatmap" for heatmaps using [vis_heatmap]; #' -#' - "heatmap2" for heatmaps using \link{vis_heatmap2}; +#' - "heatmap2" for heatmaps using [vis_heatmap2]; #' -#' - "circos" for circos plots using \link{vis_circos}. +#' - "circos" for circos plots using [vis_circos]. #' #' @param ... Other arguments passed to corresponding functions depending on the plot type: #' -#' - "hist" - passes arguments to \link{vis_hist}; +#' - "hist" - passes arguments to [vis_hist]; #' -#' - "box" - passes arguments to \link{vis_box}; +#' - "box" - passes arguments to [vis_box]; #' -#' - "heatmap" - passes arguments to \link{vis_heatmap}; +#' - "heatmap" - passes arguments to [vis_heatmap]; #' -#' - "heatmap2" - passes arguments to \link{vis_heatmap2} and \link{heatmap} from the "pheatmap" package; +#' - "heatmap2" - passes arguments to [vis_heatmap2] and [heatmap] from the "pheatmap" package; #' -#' - "circos" - passes arguments to \link{vis_circos} and \link{chordDiagram} from the "circlize" package. +#' - "circos" - passes arguments to [vis_circos] and [circlize::chordDiagram] from the "circlize" package. #' #' @return #' A ggplot2 object, pheatmap or circlize object. @@ -1089,7 +1197,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 \link{geneUsage} +#' @seealso [geneUsage] #' #' @export vis.immunr_gene_usage <- function(.data, .plot = c("hist", "box", "heatmap", "heatmap2", "circos"), ...) { @@ -1126,7 +1234,11 @@ vis.immunr_gene_usage <- function(.data, .plot = c("hist", "box", "heatmap", "he #' #' @name vis_hist #' -#' @description Visualisation of distributions using ggplot2-based histograms. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Visualisation of distributions using ggplot2-based histograms. #' #' @param .data Input matrix or data frame. #' @@ -1158,7 +1270,7 @@ vis.immunr_gene_usage <- function(.data, .plot = c("hist", "box", "heatmap", "he #' #' @param .labs A character vector of length two with names for x-axis and y-axis, respectively. #' -#' @param .melt If TRUE then apply \link{melt} to the ".data" before plotting. +#' @param .melt If TRUE then apply [reshape2::melt] to the ".data" before plotting. #' In this case ".data" is supposed to be a data frame with the first character column reserved #' for names of genes and other numeric columns reserved to counts or frequencies of genes. #' Each numeric column should be associated with a specific repertoire sample. @@ -1171,19 +1283,19 @@ vis.immunr_gene_usage <- function(.data, .plot = c("hist", "box", "heatmap", "he #' @param ... Is not used here. #' #' @details -#' If data is grouped, then statistical tests for comparing means of groups will be performed, unless \code{.test = FALSE} is supplied. +#' If data is grouped, then statistical tests for comparing means of groups will be performed, unless `.test = FALSE` is supplied. #' In case there are only two groups, the Wilcoxon rank sum test (https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test) is performed -#' (R function \code{\link{wilcox.test}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. -#' In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link{kruskal.test}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. +#' (R function [wilcox.test()] with an argument `exact = FALSE`) for testing if there is a difference in mean rank values between two groups. +#' In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function [kruskal.test()]), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. #' A significant Kruskal-Wallis test indicates that at least one sample stochastically dominates one other sample. #' Adjusted for multiple comparisons P-values are plotted on the top of groups. #' P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm%E2%80%93Bonferroni_method) (also known as Holm-Bonferroni correction). -#' You can execute the command \code{?p.adjust} in the R console to see more. +#' You can execute the command `?p.adjust` in the R console to see more. #' #' @return #' A ggplot2 object. #' -#' @seealso \link{vis.immunr_gene_usage}, \link{geneUsage} +#' @seealso [vis.immunr_gene_usage], [geneUsage] #' #' @examples #' data(immdata) @@ -1320,7 +1432,11 @@ vis_hist <- function(.data, .by = NA, .meta = NA, .title = "Gene usage", .ncol = #' #' @name vis_box #' -#' @description Visualisation of distributions using ggplot2-based boxplots. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' Visualisation of distributions using ggplot2-based boxplots. #' #' @param .data Input matrix or data frame. #' @@ -1338,7 +1454,7 @@ vis_hist <- function(.data, .by = NA, .meta = NA, .title = "Gene usage", .ncol = #' such as age, serostatus or hla. #' @param .title The text for the title of the plot. #' @param .labs Character vector of length two with names for x-axis and y-axis, respectively. -#' @param .melt If TRUE then apply \link{melt} to the ".data" before plotting. +#' @param .melt If TRUE then apply [reshape2::melt] to the ".data" before plotting. #' In this case ".data" is supposed to be a data frame with the first character column reserved #' for names of genes and other numeric columns reserved to counts or frequencies of genes. #' Each numeric column should be associated with a specific repertoire sample. @@ -1356,7 +1472,7 @@ vis_hist <- function(.data, .by = NA, .meta = NA, .title = "Gene usage", .ncol = #' @return #' A ggplot2 object. #' -#' @seealso \link{vis.immunr_gene_usage}, \link{geneUsage} +#' @seealso [vis.immunr_gene_usage], [geneUsage] #' #' @examples #' vis_box(data.frame(Sample = sample(c("A", "B", "C"), 100, TRUE), Value = rnorm(100)), .melt = FALSE) @@ -1366,6 +1482,10 @@ vis_box <- function(.data, .by = NA, .meta = NA, .melt = TRUE, .labs = c("X", "Y"), .title = "Boxplot (.title argument)", .subtitle = "Subtitle (.subtitle argument)", .legend = NA, .leg.title = "Legend (.leg.title argument)", .legend.pos = "right") { + if (!requireNamespace("ggpubr", quietly = TRUE)) { + stop("Package 'ggpubr' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + if (.melt) { res <- reshape2::melt(.data) res <- res[1:nrow(res), ] @@ -1437,7 +1557,7 @@ vis_box <- function(.data, .by = NA, .meta = NA, .melt = TRUE, } } - p_df <- compare_means(Value ~ Group, .data, comparisons = comparisons, p.adjust.method = "holm") + p_df <- ggpubr::compare_means(Value ~ Group, .data, comparisons = comparisons, p.adjust.method = "holm") y_max <- max(.data$Value) p.value.y.coord <- rep(y_max, nrow(p_df)) @@ -1450,18 +1570,18 @@ vis_box <- function(.data, .by = NA, .meta = NA, .melt = TRUE, p.adj = format.pval(p.adj, digits = 1) ) - p <- p + geom_signif( + p <- p + ggpubr::geom_signif( data = p_df, aes(xmin = group1, xmax = group2, annotations = p.adj, y_position = y.coord), manual = TRUE, tip_length = 0.03, size = .5, inherit.aes = FALSE ) } else { # Seems fine... - # p_df = compare_means(Value ~ Group, group.by = "Grouping.var", method = "kruskal.test", .data, p.adjust.method = "holm") + # p_df = ggpubr::compare_means(Value ~ Group, group.by = "Grouping.var", method = "kruskal.test", .data, p.adjust.method = "holm") # print(p_df) p <- p + - stat_compare_means(aes(label = after_stat(p.adj)), + ggpubr::stat_compare_means(aes(label = after_stat(p.adj)), bracket.size = .5, size = .signif.label.size, label.y = max(.data$Value, na.rm = TRUE) * 1.07 ) @@ -1495,13 +1615,16 @@ vis_box <- function(.data, .by = NA, .meta = NA, .melt = TRUE, #' @concept post_analysis #' #' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' Visualisation of the results of hierarchical clustering. -#' For other clustering visualisations see \link{vis.immunr_kmeans}. +#' For other clustering visualisations see [vis.immunr_kmeans]. #' #' @aliases vis.immunr_hclust #' -#' @param .data Clustering results from \link{repOverlapAnalysis} or \link{geneUsageAnalysis}. -#' @param .rect Passed to \link{fviz_dend} - whether to add a rectangle around groups. +#' @param .data Clustering results from [repOverlapAnalysis] or [geneUsageAnalysis]. +#' @param .rect Passed to [factoextra::fviz_dend] - whether to add a rectangle around groups. #' @param .plot A character vector of length one or two specifying which plots to visualise. #' If "clust" then plot only the clustering. If "best" then plot the number of optimal clusters. #' If both then plot both. @@ -1510,7 +1633,7 @@ vis_box <- function(.data, .by = NA, .meta = NA, .melt = TRUE, #' @return #' Ggplot2 objects inside the patchwork container. #' -#' @seealso \link{vis}, \link{repOverlapAnalysis}, \link{geneUsageAnalysis} +#' @seealso [vis], [repOverlapAnalysis], [geneUsageAnalysis] #' #' @examples #' data(immdata) @@ -1518,9 +1641,13 @@ vis_box <- function(.data, .by = NA, .meta = NA, .melt = TRUE, #' repOverlapAnalysis(ov, "mds+hclust") %>% vis() #' @export vis.immunr_hclust <- function(.data, .rect = FALSE, .plot = c("clust", "best"), ...) { + if (!requireNamespace("factoextra", quietly = TRUE)) { + stop("Package 'factoextra' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + p1 <- NULL if ("clust" %in% .plot) { - p1 <- fviz_dend(.data[[1]], main = "Hierarchical clustering", rect = .rect) + p1 <- factoextra::fviz_dend(.data[[1]], main = "Hierarchical clustering", rect = .rect) } p2 <- NULL @@ -1546,17 +1673,20 @@ vis.immunr_hclust <- function(.data, .rect = FALSE, .plot = c("clust", "best"), #' @concept post_analysis #' #' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' Visualisation of the results of K-means and DBSCAN clustering. -#' For hierarhical clustering visualisations see \link{vis.immunr_hclust}. +#' For hierarhical clustering visualisations see [vis.immunr_hclust]. #' #' @aliases vis.immunr_kmeans vis.immunr_dbscan #' -#' @param .data Clustering results from \link{repOverlapAnalysis} or \link{geneUsageAnalysis}. -#' @param .point If TRUE then plot sample points. Passed to \link{fviz_cluster}. -#' @param .text If TRUE then plot text labels. Passed to \link{fviz_cluster}. -#' @param .ellipse If TRUE then plot ellipses around all samples. Passed to "ellipse" from \link{fviz_cluster}. -#' @param .point.size Size of points, passed to "pointsize" from \link{fviz_cluster}. -#' @param .text.size Size of text labels, passed to labelsize from \link{fviz_cluster}. +#' @param .data Clustering results from [repOverlapAnalysis] or [geneUsageAnalysis]. +#' @param .point If TRUE then plot sample points. Passed to [factoextra::fviz_cluster]. +#' @param .text If TRUE then plot text labels. Passed to [factoextra::fviz_cluster]. +#' @param .ellipse If TRUE then plot ellipses around all samples. Passed to "ellipse" from [factoextra::fviz_cluster]. +#' @param .point.size Size of points, passed to "pointsize" from [factoextra::fviz_cluster]. +#' @param .text.size Size of text labels, passed to labelsize from [factoextra::fviz_cluster]. #' @param .plot A character vector of length one or two specifying which plots to visualise. #' If "clust" then plot only the clustering. If "best" then plot the number of optimal clusters. #' If both then plot both. @@ -1565,7 +1695,7 @@ vis.immunr_hclust <- function(.data, .rect = FALSE, .plot = c("clust", "best"), #' @return #' Ggplot2 objects inside the pathwork container. #' -#' @seealso \link{vis}, \link{repOverlapAnalysis}, \link{geneUsageAnalysis} +#' @seealso [vis], [repOverlapAnalysis], [geneUsageAnalysis] #' #' @examples #' data(immdata) @@ -1575,9 +1705,13 @@ vis.immunr_hclust <- function(.data, .rect = FALSE, .plot = c("clust", "best"), vis.immunr_kmeans <- function(.data, .point = TRUE, .text = TRUE, .ellipse = TRUE, .point.size = 2, .text.size = 10, .plot = c("clust", "best"), ...) { + if (!requireNamespace("factoextra", quietly = TRUE)) { + stop("Package 'factoextra' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + p1 <- NULL if ("clust" %in% .plot) { - p1 <- fviz_cluster(.data[[1]], + p1 <- factoextra::fviz_cluster(.data[[1]], data = .data[[3]], main = "K-means clustering", geom = c("point", "text")[c(.point, .text)], show.legend.text = FALSE, show.clust.cent = FALSE, repel = TRUE, ellipse = .ellipse, shape = 16, pointsize = .point.size, labelsize = .text.size, label.rectangle = TRUE @@ -1606,7 +1740,11 @@ vis.immunr_kmeans <- function(.data, .point = TRUE, .text = TRUE, .ellipse = TRU #' @export vis.immunr_dbscan <- function(.data, .point = TRUE, .text = TRUE, .ellipse = TRUE, .point.size = 2, .text.size = 10, .plot = c("clust", "best"), ...) { - fviz_cluster(.data[[1]], + if (!requireNamespace("factoextra", quietly = TRUE)) { + stop("Package 'factoextra' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + + factoextra::fviz_cluster(.data[[1]], data = .data[[2]], main = "DBSCAN clustering", geom = c("point", "text")[c(.point, .text)], show.legend.text = FALSE, show.clust.cent = FALSE, repel = TRUE, ellipse = .ellipse, shape = 16, pointsize = .point.size, labelsize = .text.size, label.rectangle = TRUE @@ -1623,12 +1761,15 @@ vis.immunr_dbscan <- function(.data, .point = TRUE, .text = TRUE, .ellipse = TRU #' #' @concept post_analysis #' -#' @importFrom ggpubr ggscatter -#' #' @aliases vis.immunr_mds vis.immunr_pca vis.immunr_tsne #' -#' @param .data Output from analysis functions such as \link{geneUsageAnalysis} or -#' \link{immunr_pca}, \link{immunr_mds} or \link{immunr_tsne}. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data Output from analysis functions such as [geneUsageAnalysis] or +#' [immunr_pca], [immunr_mds] or [immunr_tsne]. #' @param .by Pass NA if you want to plot samples without grouping. #' #' You can pass a character vector with one or several column names from ".meta" @@ -1654,11 +1795,11 @@ vis.immunr_dbscan <- function(.data, .point = TRUE, .text = TRUE, .ellipse = TRU #' @details #' Other visualisation methods: #' -#' - PCA - \link{vis.immunr_pca} +#' - PCA - [vis.immunr_pca] #' -#' - MDS - \link{vis.immunr_mds} +#' - MDS - [vis.immunr_mds] #' -#' - tSNE - \link{vis.immunr_tsne} +#' - tSNE - [vis.immunr_tsne] #' #' @examples #' data(immdata) @@ -1668,6 +1809,10 @@ vis.immunr_dbscan <- function(.data, .point = TRUE, .text = TRUE, .ellipse = TRU vis.immunr_mds <- function(.data, .by = NA, .meta = NA, .point = TRUE, .text = TRUE, .ellipse = TRUE, .point.size = 2, .text.size = 4, ...) { + if (!requireNamespace("factoextra", quietly = TRUE)) { + stop("Package 'factoextra' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + if (!.point & !.text) { stop("Error: Please provide at least one of the arguments: .point and .text") } @@ -1677,7 +1822,7 @@ vis.immunr_mds <- function(.data, .by = NA, .meta = NA, .ellipse <- FALSE } - fviz_pca_ind(.data, + factoextra::fviz_pca_ind(.data, habillage = group_res$group_column, geom = c("point", "text")[c(.point, .text)], repel = TRUE, addEllipses = .ellipse, mean.point = FALSE, pointshape = 16, pointsize = .point.size, labelsize = .text.size, label.rectangle = TRUE, show.legend.text = FALSE @@ -1691,6 +1836,10 @@ vis.immunr_mds <- function(.data, .by = NA, .meta = NA, vis.immunr_pca <- function(.data, .by = NA, .meta = NA, .point = TRUE, .text = TRUE, .ellipse = TRUE, .point.size = 2, .text.size = 4, ...) { + if (!requireNamespace("factoextra", quietly = TRUE)) { + stop("Package 'factoextra' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + if (!.point & !.text) { stop("Error: Please provide at least one of the arguments: .point and .text") } @@ -1700,7 +1849,7 @@ vis.immunr_pca <- function(.data, .by = NA, .meta = NA, .ellipse <- FALSE } - fviz_pca_ind(.data, + factoextra::fviz_pca_ind(.data, habillage = group_res$group_column, geom = c("point", "text")[c(.point, .text)], repel = TRUE, addEllipses = .ellipse, mean.point = FALSE, pointshape = 16, pointsize = .point.size, labelsize = .text.size, label.rectangle = TRUE, show.legend.text = FALSE @@ -1714,6 +1863,14 @@ vis.immunr_pca <- function(.data, .by = NA, .meta = NA, vis.immunr_tsne <- function(.data, .by = NA, .meta = NA, .point = TRUE, .text = TRUE, .ellipse = TRUE, .point.size = 2, .text.size = 4, ...) { + if (!requireNamespace("factoextra", quietly = TRUE)) { + stop("Package 'factoextra' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + + if (!requireNamespace("ggpubr", quietly = TRUE)) { + stop("Package 'ggpubr' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + .data <- data.frame(.data) colnames(.data) <- c("Dim1", "Dim2") .data$Sample <- row.names(.data) @@ -1725,7 +1882,7 @@ vis.immunr_tsne <- function(.data, .by = NA, .meta = NA, .ellipse <- FALSE } - ggscatter( + ggpubr::ggscatter( data = .data, x = "Dim1", y = "Dim2", color = "Group", ellipse = .ellipse, size = .point.size, point = .point, label = ifelse(.text, "Sample", NULL), repel = TRUE, label.rectangle = TRUE, show.legend.text = FALSE ) + @@ -1824,12 +1981,16 @@ vis_bar_stacked <- function(.data, .by = NA, .meta = NA, #' #' @aliases vis.immunr_clonal_prop vis.immunr_homeo vis.immunr_top_prop vis.immunr_tail_prop #' -#' @description An utility function to visualise the output from \code{\link{repClonality}}. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' An utility function to visualise the output from [repClonality()]. #' #' @importFrom reshape2 melt #' @importFrom scales percent #' -#' @param .data Output from \code{\link{repClonality}}. +#' @param .data Output from [repClonality()]. #' @param .by Pass NA if you want to plot samples without grouping. #' #' You can pass a character vector with one or several column names from ".meta" @@ -1854,19 +2015,19 @@ vis_bar_stacked <- function(.data, .by = NA, .meta = NA, #' @param ... Not used here. #' #' @details -#' If data is grouped, then statistical tests for comparing means of groups will be performed, unless \code{.test = FALSE} is supplied. +#' If data is grouped, then statistical tests for comparing means of groups will be performed, unless `.test = FALSE` is supplied. #' In case there are only two groups, the Wilcoxon rank sum test (https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test) is performed -#' (R function \code{\link{wilcox.test}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. -#' In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link{kruskal.test}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. +#' (R function [wilcox.test()] with an argument `exact = FALSE`) for testing if there is a difference in mean rank values between two groups. +#' In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function [kruskal.test()]), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. #' A significant Kruskal-Wallis test indicates that at least one sample stochastically dominates one other sample. #' Adjusted for multiple comparisons P-values are plotted on the top of groups. #' P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm%E2%80%93Bonferroni_method) (also known as Holm-Bonferroni correction). -#' You can execute the command \code{?p.adjust} in the R console to see more. +#' You can execute the command `?p.adjust` in the R console to see more. #' #' @return #' A ggplot2 object. #' -#' @seealso \link{repClonality} \link{vis} +#' @seealso [repClonality] [vis] #' #' @examples #' data(immdata) @@ -2011,10 +2172,13 @@ vis.immunr_rare_prop <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.0 #' #' @concept vis #' -#' @importFrom ggpubr compare_means geom_signif stat_compare_means theme_pubr rotate_x_text -#' #' @name vis_bar #' +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' #' @param .data Data to visualise. #' @param .by Pass NA if you want to plot samples without grouping. #' @@ -2058,6 +2222,10 @@ vis_bar <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), . .subtitle = "Subtitle (.subtitle argument)", .legend = NA, .leg.title = "Legend (.leg.title argument)", .legend.pos = "right", .rotate_x = 90) { + if (!requireNamespace("ggpubr", quietly = TRUE)) { + stop("Package 'ggpubr' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + group_res <- process_metadata_arguments(.data, .by, .meta, .defgroupby) group_column <- group_res$name .data$Group <- group_res$group_column @@ -2156,7 +2324,7 @@ vis_bar <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), . } } - p_df <- compare_means(Value ~ Group, .data, comparisons = comparisons, p.adjust.method = "holm") + p_df <- ggpubr::compare_means(Value ~ Group, .data, comparisons = comparisons, p.adjust.method = "holm") y_max <- max(.data$Value) p.value.y.coord <- rep(y_max, nrow(p_df)) @@ -2169,18 +2337,18 @@ vis_bar <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), . p.adj = format.pval(p.adj, digits = 1) ) - p <- p + geom_signif( + p <- p + ggpubr::geom_signif( data = p_df, aes(xmin = group1, xmax = group2, annotations = p.adj, y_position = y.coord), manual = TRUE, tip_length = 0.03, size = .5, inherit.aes = FALSE ) } else { # Seems fine... - # p_df = compare_means(Value ~ Group, group.by = "Grouping.var", method = "kruskal.test", .data, p.adjust.method = "holm") + # p_df = ggpubr::compare_means(Value ~ Group, group.by = "Grouping.var", method = "kruskal.test", .data, p.adjust.method = "holm") # print(p_df) p <- p + - stat_compare_means(aes(label = after_stat(p.adj)), + ggpubr::stat_compare_means(aes(label = after_stat(p.adj)), bracket.size = .5, size = .signif.label.size, label.y = max(.data$Value, na.rm = TRUE) * 1.07 ) @@ -2227,11 +2395,16 @@ vis_bar <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), . #' @concept diversity #' #' @aliases vis.immunr_chao1 vis.immunr_dxx vis.immunr_rarefaction vis.immunr_div vis.immunr_ginisimp vis.immunr_invsimp vis.immunr_hill -#' @description An utility function to visualise the output from \code{\link{repDiversity}}. +#' +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' An utility function to visualise the output from [repDiversity()]. #' #' @importFrom reshape2 melt #' -#' @param .data Output from \code{\link{repDiversity}}. +#' @param .data Output from [repDiversity()]. #' @param .by Pass NA if you want to plot samples without grouping. #' #' You can pass a character vector with one or several column names from ".meta" @@ -2253,19 +2426,19 @@ vis_bar <- function(.data, .by = NA, .meta = NA, .errorbars = c(0.025, 0.975), . #' @param ... Not used here. #' #' @details -#' If data is grouped, then statistical tests for comparing means of groups will be performed, unless \code{.test = FALSE} is supplied. +#' If data is grouped, then statistical tests for comparing means of groups will be performed, unless `.test = FALSE` is supplied. #' In case there are only two groups, the Wilcoxon rank sum test (https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test) is performed -#' (R function \code{\link{wilcox.test}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. -#' In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link{kruskal.test}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. +#' (R function [wilcox.test()] with an argument `exact = FALSE`) for testing if there is a difference in mean rank values between two groups. +#' In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function [kruskal.test()]), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. #' A significant Kruskal-Wallis test indicates that at least one sample stochastically dominates one other sample. #' Adjusted for multiple comparisons P-values are plotted on the top of groups. #' P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm%E2%80%93Bonferroni_method) (also known as Holm-Bonferroni correction). -#' You can execute the command \code{?p.adjust} in the R console to see more. +#' You can execute the command `?p.adjust` in the R console to see more. #' #' @return #' A ggplot2 object. #' -#' @seealso \link{repDiversity} \link{vis} +#' @seealso [repDiversity] [vis] #' #' @examples #' data(immdata) @@ -2414,6 +2587,10 @@ vis.immunr_dxx <- function(.data, .by = NA, .meta = NA, vis.immunr_rarefaction <- function(.data, .by = NA, .meta = NA, .mean = TRUE, .errors = TRUE, .log = FALSE, .labels = TRUE, ...) { + if (!requireNamespace("ggrepel", quietly = TRUE)) { + stop("Package 'ggrepel' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + .muc.res <- .data group_res <- process_metadata_arguments(.data, .by, .meta) @@ -2486,11 +2663,15 @@ vis.immunr_rarefaction <- function(.data, .by = NA, .meta = NA, #' @concept explore #' #' @aliases vis.immunr_exp_vol vis.immunr_exp_count vis.immunr_exp_len vis.immunr_exp_clones -#' @description An utility function to visualise the output from \code{\link{repExplore}}. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' An utility function to visualise the output from [repExplore()]. #' #' @importFrom reshape2 melt #' -#' @param .data Output from \code{\link{repExplore}}. +#' @param .data Output from [repExplore()]. #' @param .by Pass NA if you want to plot samples without grouping. #' #' You can pass a character vector with one or several column names from ".meta" @@ -2515,19 +2696,19 @@ vis.immunr_rarefaction <- function(.data, .by = NA, .meta = NA, #' @param ... Not used here. #' #' @details -#' If data is grouped, then statistical tests for comparing means of groups will be performed, unless \code{.test = FALSE} is supplied. +#' If data is grouped, then statistical tests for comparing means of groups will be performed, unless `.test = FALSE` is supplied. #' In case there are only two groups, the Wilcoxon rank sum test (https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test) is performed -#' (R function \code{\link{wilcox.test}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. -#' In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link{kruskal.test}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. +#' (R function [wilcox.test()] with an argument `exact = FALSE`) for testing if there is a difference in mean rank values between two groups. +#' In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function [kruskal.test()]), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. #' A significant Kruskal-Wallis test indicates that at least one sample stochastically dominates one other sample. #' Adjusted for multiple comparisons P-values are plotted on the top of groups. #' P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm%E2%80%93Bonferroni_method) (also known as Holm-Bonferroni correction). -#' You can execute the command \code{?p.adjust} in the R console to see more. +#' You can execute the command `?p.adjust` in the R console to see more. #' #' @return #' A ggplot2 object. #' -#' @seealso \link{repExplore} \link{vis} +#' @seealso [repExplore] [vis] #' #' @examples #' data(immdata) @@ -2631,18 +2812,21 @@ vis.immunr_exp_clones <- function(.data, .by = NA, .meta = NA, #' @name vis.immunr_kmer_table #' #' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' Plot a distribution (bar plot) of the most frequent kmers in a data. #' #' @param .data Data frame with two columns "Kmers" and "Count" or a list with such data frames. See Examples. #' @param .head Number of the most frequent kmers to choose for plotting from each data frame. -#' @param .position Character vector of length 1. Position of bars for each kmers. Value for the \code{ggplot2} argument \code{position}. +#' @param .position Character vector of length 1. Position of bars for each kmers. Value for the `ggplot2` argument `position`. #' @param .log Logical. If TRUE then plot log-scaled plots. #' @param ... Not used here. #' #' @return #' A ggplot2 object. #' -#' @seealso \code{get.kmers} +#' @seealso `get.kmers` #' #' @examples #' # Load necessary data and package. @@ -2696,8 +2880,6 @@ vis.immunr_kmer_table <- function(.data, .head = 100, .position = c("stack", "do #' #' @concept kmers #' -#' @importFrom ggseqlogo geom_logo theme_logo -#' #' @aliases vis_seqlogo vis_textlogo #' #' @name vis_textlogo @@ -2708,6 +2890,9 @@ vis.immunr_kmer_table <- function(.data, .head = 100, .position = c("stack", "do #' vis_seqlogo(.data, .scheme = "chemistry", ...) #' #' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' Plot sequence logo plots for visualising of amino acid motif sequences / profiles. #' #' `vis_textlogo` plots sequences in a text format - each letter has the same height. Useful when there @@ -2716,10 +2901,10 @@ vis.immunr_kmer_table <- function(.data, .head = 100, .position = c("stack", "do #' `vis_seqlogo` is a traditional sequence logo plots. Useful when there are one or two amino acids #' with clear differences in their occurrences. #' -#' @param .data Output from the \code{kmer.profile} function. +#' @param .data Output from the `kmer.profile` function. #' @param .replace.zero.with.na if TRUE then replace all zeros with NAs, therefore letters with #' zero frequency wont appear at the plot. -#' @param .scheme Character. An argumentt passed to \link{geom_logo} specifying how to colour symbols. +#' @param .scheme Character. An argument passed to geom_logo from ggseqlogo package specifying how to colour symbols. #' @param .width Width for jitter, i.e., how much points will scatter around the verical line. Pass 0 (zero) #' to plot points on the straight vertical line for each position. #' @param ... Not used here. @@ -2727,7 +2912,7 @@ vis.immunr_kmer_table <- function(.data, .head = 100, .position = c("stack", "do #' @return #' A ggplot2 object. #' -#' @seealso \link{getKmers}, \link{kmer_profile} +#' @seealso [getKmers], [kmer_profile] #' #' @examples #' data(immdata) @@ -2743,6 +2928,10 @@ vis.immunr_kmer_table <- function(.data, .head = 100, .position = c("stack", "do vis_textlogo <- function(.data, .replace.zero.with.na = TRUE, .width = 0.1, ...) { # ToDo: make different color schemas, for type of aminoacids (polarity, etc), etc + if (!requireNamespace("ggrepel", quietly = TRUE)) { + stop("Package 'ggrepel' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + .data <- reshape2::melt(.data) if (.replace.zero.with.na) { .data$value[.data$value == 0] <- NA @@ -2758,6 +2947,10 @@ vis_textlogo <- function(.data, .replace.zero.with.na = TRUE, .width = 0.1, ...) #' @export vis_seqlogo <- function(.data, .scheme = "chemistry", ...) { + if (!requireNamespace("ggseqlogo", quietly = TRUE)) { + stop("Package 'ggseqlogo' is required for this function. Please install it first via `pak::pkg_install('ggseqlogo')`", call. = FALSE) + } + ggplot() + ggseqlogo::geom_logo(.data, method = "custom", col_scheme = .scheme) + ggseqlogo::theme_logo() @@ -2768,13 +2961,18 @@ vis_seqlogo <- function(.data, .scheme = "chemistry", ...) { #' #' @concept kmers #' -#' @param .data Kmer data, an output from \link{kmer_profile}. +#' @description +#' +#' #' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data Kmer data, an output from [kmer_profile]. #' @param .plot String specifying the plot type: #' -#' - "seqlogo" for traditional sequence logo plots using \link{vis_seqlogo}; +#' - "seqlogo" for traditional sequence logo plots using [vis_seqlogo]; #' -#' - "textlogo" for modified approach to sequence logo plots via text labels using \link{vis_textlogo}; -#' @param ... Other arguments passed to \link{vis_textlogo} or \link{vis_seqlogo}, depending +#' - "textlogo" for modified approach to sequence logo plots via text labels using [vis_textlogo]; +#' @param ... Other arguments passed to [vis_textlogo] or [vis_seqlogo], depending #' on the ".plot" argument. #' #' @return @@ -2833,11 +3031,15 @@ vis.immunr_kmer_profile_self <- function(.data, .plot = c("textlogo", "seqlogo") #' @concept dynamics #' #' @importFrom data.table setnames melt.data.table -#' @importFrom ggalluvial geom_flow geom_stratum #' #' @name vis.immunr_dynamics #' -#' @param .data Output from the \link{trackClonotypes} function. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data Output from the [trackClonotypes] function. #' @param .plot Character. Either "smooth", "area" or "line". Each specifies a type of plot for visualisation of clonotype dynamics. #' @param .order Numeric or character vector. Specifies the order to samples, e.g., it used for ordering samples #' by timepoints. Either See "Examples" below for more details. @@ -2896,6 +3098,10 @@ vis.immunr_kmer_profile_self <- function(.data, .plot = c("textlogo", "seqlogo") #' 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)) { + stop("Package 'ggalluvial' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + .plot <- .plot[1] if (!(.plot %in% c("smooth", "area", "line"))) { stop("Error: unknown plot identifier \"", .plot, "\". Please provide one of the following: \"smooth\", \"area\" or \"line\".") @@ -2934,8 +3140,8 @@ vis.immunr_dynamics <- function(.data, .plot = c("smooth", "area", "line"), .ord if (.plot == "smooth") { p <- p + - geom_flow() + - geom_stratum() + ggalluvial::geom_flow() + + ggalluvial::geom_stratum() } else if (.plot == "area") { p <- p + geom_area(aes(group = Clonotype), color = "black") @@ -2958,9 +3164,15 @@ vis.immunr_dynamics <- function(.data, .plot = c("smooth", "area", "line"), .ord #' #' @concept phylip #' -#' @param .data Clonal families from 1 or multiple samples: \code{\link{repClonalFamily}} output. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data Clonal families from 1 or multiple samples: [repClonalFamily()] output. #' @param ... Not used here. #' +#' #' @return #' A ggraph object. #' @@ -3004,7 +3216,12 @@ vis.clonal_family <- function(.data, ...) { #' #' @concept phylip #' -#' @param .data Single clonal family tree data from 1 cluster: 1 element from TreeStats column from \code{\link{repClonalFamily}} output. +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' +#' +#' @param .data Single clonal family tree data from 1 cluster: 1 element from TreeStats column from [repClonalFamily()] output. #' @param ... Not used here. #' #' @return @@ -3027,17 +3244,24 @@ vis.clonal_family <- function(.data, ...) { #' } #' @export vis.clonal_family_tree <- function(.data, ...) { + if (!requireNamespace("ggraph", quietly = TRUE)) { + stop("Package 'ggraph' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + if (!requireNamespace("igraph", quietly = TRUE)) { + stop("Package 'igraph' is required for this function. Please install it first via install.packages() or devtools::install_github().", call. = FALSE) + } + links_df <- .data[c("Ancestor", "Name")] %>% drop_na("Ancestor") names(links_df) <- c("from", "to") vertices_df <- .data[c("Name", "Type", "Clones")] names(vertices_df)[1] <- "name" - tree_graph <- graph_from_data_frame(links_df, vertices = vertices_df) %>% - ggraph("tree") + - geom_edge_diagonal() + - geom_node_point(aes(color = Type, size = Clones)) + - theme_graph(base_family = "sans") + tree_graph <- igraph::graph_from_data_frame(links_df, vertices = vertices_df) %>% + ggraph::ggraph("tree") + + ggraph::geom_edge_diagonal() + + ggraph::geom_node_point(aes(color = Type, size = Clones)) + + ggraph::theme_graph(base_family = "sans") return(tree_graph) } @@ -3045,6 +3269,10 @@ vis.clonal_family_tree <- function(.data, ...) { #' Handler for .nofail argument of pipeline steps that prevents examples from crashing #' on computers where certain dependencies are not installed #' +#' @description +#' +#' `r lifecycle::badge('deprecated')` +#' #' @param .data Not used here. #' @param ... Not used here. #' diff --git a/R/v1_aaa_registry_utils.R b/R/v1_aaa_registry_utils.R new file mode 100644 index 00000000..7c8e3051 --- /dev/null +++ b/R/v1_aaa_registry_utils.R @@ -0,0 +1,77 @@ +make_immunarch_method_record <- function(fn, method_name, ...) { + list( + fn = fn, + method_name = method_name + ) +} + +register_airr_family <- function(family_name) { + fam_env <- IMMUNARCH_METHOD_REGISTRY[[family_name]] + + if (is.null(fam_env)) { + fam_env <- new.env(parent = emptyenv()) + IMMUNARCH_METHOD_REGISTRY[[family_name]] <- fam_env + } +} + +register_airr_method <- function(family_name, method_name, fn) { + # checkmate checks + + fam_env <- IMMUNARCH_METHOD_REGISTRY[[family_name]] + + assign(method_name, + make_immunarch_method_record( + fn = fn, + method_name = method_name + ), + envir = fam_env + ) +} + +get_airr_method <- function(family_name, method_name, verbose = TRUE) { + # checkmate checks + + fam_env <- IMMUNARCH_METHOD_REGISTRY[[family_name]] + + if (is.null(method_name)) { + if (verbose) { + cli::cli_text("Available methods in {.code {family_name}}:") + cli::cli_ol(ls(fam_env)) + return(invisible(ls(fam_env))) + } else { + return(ls(fam_env)) + } + } else { + # check and throw an error if no such object + record <- get0(method_name, envir = fam_env, ifnotfound = NULL) + + if (is.null(record)) { + cli::cli_abort("No such method: {.code {method_name}}. Available methods: {ls(fam_env)}") + } + + record + } +} + +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) + + if (is.null(idata)) { + # list available methods for this family + get_airr_method(family_name, NULL) + } else if (is.null(method)) { + cli::cli_abort("{.code idata} provided, but {.code method} is null, aborting the execution; please provide either both {.code idata} and {.code method}, or leave them as nulls to show the list of available methods") + } else { + checkmate::assert_data_frame(idata$repertoires, null.ok = FALSE) + + record <- get_airr_method(family_name, method) + fn <- record$fn + res <- fn(idata, ...) + res + } + } +} diff --git a/R/v1_airr_clonality.R b/R/v1_airr_clonality.R new file mode 100644 index 00000000..7b011f30 --- /dev/null +++ b/R/v1_airr_clonality.R @@ -0,0 +1,201 @@ +#' @title Clonality - receptor overabundance statistics for immune repertoires +#' +#' @description +#' `r lifecycle::badge("experimental")` +#' +#' A family of functions to quantify **receptor overabundance** per repertoire. Helps in deciphering the structure and partition the repertoire. +#' +#' ## Available functions +#' +#' Supported methods are the following. +#' +#' @param idata An `ImmunData` object. +#' @inheritParams airr_clonality_line +#' @inheritParams airr_clonality_rank +#' @inheritParams airr_clonality_prop +#' @inheritParams im_common_args +#' +#' @seealso +#' * Per-repertoire summaries: [annotate_clonality] +#' * Data container: [immundata::ImmunData] +#' +#' @examples +#' # Load data +#' immdata <- get_test_idata() |> agg_repertoires("Therapy") +#' +#' @name airr_clonality +#' @concept Clonality +NULL + + +#' @keywords internal +airr_clonality_line_impl <- function(idata, limit = 100000) { + checkmate::check_numeric(limit, lower = 10, len = 1) + + n_repertoires <- idata$repertoires |> + distinct(!!immundata::imd_schema_sym("repertoire")) |> + pull() |> + length() + + idata$annotations |> + select(all_of(c( + immundata::imd_schema("repertoire"), + immundata::imd_schema("receptor"), + immundata::imd_schema("count") + ))) |> + distinct(!!immundata::imd_schema_sym("repertoire"), + !!immundata::imd_schema_sym("receptor"), + .keep_all = TRUE + ) |> + arrange(desc(!!immundata::imd_schema_sym("count"))) |> + collect() |> # TODO: .by doesn't work in slice_head in duckplyr. What to do instead then? + slice_head(n = limit * n_repertoires, by = !!immundata::imd_schema_sym("repertoire")) |> + mutate( + index = row_number(), + .by = immundata::imd_schema("repertoire") + ) |> + select(-!!immundata::imd_schema_sym("receptor")) |> + arrange(index) +} + + +#' @description `airr_clonality_line` - build ranked abundance lines: for each +#' repertoire, take the top `limit` receptors by `count` and attach repertoire +#' metadata. Useful for per-repertoire rank-abundance plots. +#' +#' @param limit Positive integer >= 10: maximum number of top receptors to keep +#' **per repertoire** (default `100000`). +#' +#' @return +#' +#' ## `airr_clonality_line` +#' A tibble with columns: +#' * `repertoire_id` - repertoire identifier +#' * `index` - rank within repertoire (1 = most abundant) +#' * `count` - receptor count used for ranking +#' * plus any repertoire metadata columns carried from `idata$repertoires` +#' +#' @examples +#' # +#' # airr_clonality_line +#' # +#' top_line <- airr_clonality_line(immdata, limit = 1000) +#' +#' @rdname airr_clonality +#' @concept Clonality +#' @export +airr_clonality_line <- register_immunarch_method( + core = airr_clonality_line_impl, + family = "airr_clonality", + name = "line", + need_repertoires = TRUE +) + + +#' @keywords internal +airr_clonality_rank_impl <- function(idata, + bins = c(10, 30, 100, 300, 1000, 10000, 100000)) { + checkmate::check_numeric(bins, lower = 1) + + bins <- sort(bins, decreasing = FALSE) + + clonality_df <- core_clonality_rank(idata = idata, bins = bins) + + clonality_df |> + summarise( + .by = c(immundata::imd_schema("repertoire"), "clonal_rank_bin"), + occupied_prop = sum(!!immundata::imd_schema_sym("proportion"), na.rm = TRUE) + ) +} + + +#' @description `airr_clonality_rank` - aggregate clonal space by **rank bins**. +#' Receptors are ordered by `proportion` within each repertoire; each receptor +#' is assigned to the smallest threshold in `bins` that contains its rank. +#' +#' @param bins Integer vector of rank thresholds (e.g., `c(10, 100, 1000)`). +#' For each repertoire, receptors with ranks `<= bins[i]` contribute to bin +#' `bins[i]`. Bins are sorted ascending internally. +#' +#' @return +#' +#' ## `airr_clonality_rank` +#' A tibble with +#' * `repertoire_id` +#' * `clonal_rank_bin` - the rank threshold (e.g., `10`, `100`, ...) +#' * `occupied_prop` - sum of `proportion` within the bin +#' * plus repertoire metadata columns from `idata$repertoires` +#' +#' @examples +#' # +#' # airr_clonality_rank +#' # +#' rank_stat <- airr_clonality_rank(immdata, bins = c(10, 100)) +#' +#' @rdname airr_clonality +#' @concept Clonality +#' @export +airr_clonality_rank <- register_immunarch_method( + core = airr_clonality_rank_impl, + family = "airr_clonality", + name = "rank", + need_repertoires = TRUE +) + + +#' @keywords internal +airr_clonality_prop_impl <- function( + idata, bins = c( + Hyperexpanded = 1e-2, + Large = 1e-3, + Medium = 1e-4, + Small = 1e-5, + Rare = 1e-6 + )) { + checkmate::check_numeric(bins, lower = 0, min.len = 1) + + bins <- sort(bins, decreasing = TRUE) + + clonality_df <- core_clonality_prop(idata = idata, bins = bins) + + clonality_df |> + summarise( + .by = c(immundata::imd_schema("repertoire"), "clonal_prop_bin"), + occupied_prop = sum(!!immundata::imd_schema_sym("proportion"), na.rm = TRUE) + ) +} + + +#' @description `airr_clonality_prop` - aggregate clonal space by **proportion bins**. +#' Each receptor is assigned to a named bin according to its `proportion` +#' (e.g., `Hyperexpanded >= 1e-2`, `Large >= 1e-3`, ...). Thresholds are matched in +#' descending order; unmatched receptors fall into `"Ultra-rare"`. +#' +#' @param bins A **named** numeric vector of thresholds (e.g., +#' `c(Hyperexpanded = 1e-2, Large = 1e-3, ...)`). Names become bin labels and +#' must be non-empty. Internally sorted in descending order. +#' +#' @return +#' +#' ## `airr_clonality_prop` +#' A tibble with +#' * `repertoire_id` +#' * `clonal_prop_bin` - factor-like label from `names(bins)` or `"Ultra-rare"` +#' * `occupied_prop` - sum of `proportion` within the bin +#' * plus repertoire metadata columns from `idata$repertoires` +#' +#' @examples +#' # +#' # airr_clonality_prop +#' # +#' prop_stat <- airr_clonality_prop(immdata) +#' +#' @rdname airr_clonality +#' @concept Clonality +#' @export +airr_clonality_prop <- register_immunarch_method( + core = airr_clonality_prop_impl, + family = "airr_clonality", + name = "prop", + need_repertoires = TRUE +) diff --git a/R/v1_airr_diversity.R b/R/v1_airr_diversity.R new file mode 100644 index 00000000..02a7d52b --- /dev/null +++ b/R/v1_airr_diversity.R @@ -0,0 +1,356 @@ +#' @title Diversity - estimating the heterogeneity of immune repertoires +#' +#' @description +#' `r lifecycle::badge("experimental")` +#' +#' A family of functions to quantify **receptor diversity** per repertoire. A characteristic of a whole repertoire. +#' +#' ## Available functions +#' +#' Supported methods are the following. +#' +#' @param idata An `ImmunData` object. +#' @inheritParams airr_diversity_dxx +#' @inheritParams airr_diversity_chao1 +#' @inheritParams airr_diversity_shannon +#' @inheritParams airr_diversity_pielou +#' @inheritParams airr_diversity_hill +#' @inheritParams airr_diversity_index +#' @inheritParams im_common_args +#' +#' @seealso [immundata::ImmunData] +#' +#' @examples +#' # Load data +#' immdata <- get_test_idata() |> agg_repertoires("Therapy") +#' +#' @name airr_diversity +#' @concept Diversity +NULL + + +#' @keywords internal +airr_diversity_dxx_impl <- function(idata, perc = 50) { + checkmate::assert_numeric(perc, any.missing = FALSE) + if (!all(perc > 0 & perc <= 100)) { + cli::cli_abort("{.code perc} must be in (0, 100].") + } + + rep_str <- immundata::imd_schema("repertoire") + rep_sym <- immundata::imd_schema_sym("repertoire") + rec_sym <- immundata::imd_schema_sym("receptor") + prop_str <- immundata::imd_schema("proportion") + prop_sym <- immundata::imd_schema_sym("proportion") + + base_tbl <- idata$annotations |> + dplyr::select(!!rec_sym, !!rep_sym, !!prop_sym) |> + dplyr::distinct(!!rec_sym, !!rep_sym, .keep_all = TRUE) |> + dplyr::arrange() + + k_sql <- sprintf( + "ROW_NUMBER() OVER (PARTITION BY %s ORDER BY %s DESC)", + rep_str, prop_str + ) + cum_sql <- sprintf( + "SUM(%s) OVER (PARTITION BY %s ORDER BY %s DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)", + prop_str, rep_str, prop_str + ) + + ranked <- base_tbl |> + duckplyr::as_tbl() |> + dplyr::mutate( + k = dbplyr::sql(k_sql), + cum = dbplyr::sql(cum_sql) + ) |> + duckplyr::as_duckdb_tibble() + + res <- purrr::map_dfr(perc, function(p) { + ranked |> + dplyr::filter(.data$cum >= p / 100) |> + dplyr::group_by(!!rep_sym) |> + dplyr::summarise(dxx = min(.data$k), .groups = "drop") |> + dplyr::mutate(perc = p) + }) |> + dplyr::select(!!rep_sym, .data$perc, .data$dxx) |> + dplyr::arrange(!!rep_sym, .data$perc) |> + collect() + + res +} + + +#' @description `airr_diversity_dxx` - **coverage diversity**: minimal number of +#' top receptors needed to reach `perc%` of clonal space (by `proportion`). +#' Great for spotting dominance/overexpansion and for quick, interpretable dashboards +#' (e.g., D50 = receptors to cover half of the repertoire). +#' +#' @param perc A number or numeric vector in `(0, 100]` (default `50`), e.g. +#' `50` for D50, `20` for D20. +#' +#' @return +#' +#' ## `airr_diversity_dxx` +#' A tibble with: +#' * `imd_repertoire_id` +#' * `perc` +#' * `dxx` - minimal count of top receptors to reach `perc%` +#' * plus repertoire metadata from `idata$repertoires` +#' +#' @examples +#' # +#' # airr_diversity_dxx +#' # +#' d50 <- airr_diversity_dxx(immdata, perc = 50) +#' d_multi <- airr_diversity_dxx(immdata, perc = c(20, 50, 80)) +#' +#' @rdname airr_diversity +#' @concept Diversity +#' @export +airr_diversity_dxx <- register_immunarch_method(airr_diversity_dxx_impl, "airr_diversity", "dxx") + + +#' @keywords internal +airr_diversity_chao1_impl <- function(idata) { + rep_col <- immundata::imd_schema("repertoire") + rep_sym <- immundata::imd_schema_sym("repertoire") + cnt_sym <- immundata::imd_schema_sym("count") + + # TODO: optimize this please, loading all the data in R is not good. + # TODO: check if no integer overflow + idata$annotations |> + select(!!rep_sym, !!cnt_sym) |> + collect() |> + summarise(counts = list(!!cnt_sym), .by = !!rep_sym) |> + mutate(ch = lapply(counts, chao1)) |> + transmute( + !!rep_col := !!rep_sym, + Estimator = vapply(ch, function(x) unname(x["Estimator.1"]), numeric(1)), + SD = vapply(ch, function(x) unname(x["SD.2"]), numeric(1)), + `Conf.95.lo` = vapply(ch, function(x) unname(x["Conf.95.lo.1"]), numeric(1)), + `Conf.95.hi` = vapply(ch, function(x) unname(x["Conf.95.hi.1"]), numeric(1)) + ) |> + collect() +} + +#' @description `airr_diversity_chao1` - Chao1 estimator is a nonparameteric +#' asymptotic estimator of species richness (number of species in a population). +#' One of the most used methods for estimating immune repertoire diversity. +#' +#' @return +#' +#' ## `airr_diversity_chao1` +#' A tibble with: +#' * `imd_repertoire_id` +#' * `Estimator` - number of species +#' * `SD` - standard deviation for the estimator value +#' * `Conf.95.lo` - CI 0.025 +#' * `Conf.95.hi` - CI 0.975 +#' * plus repertoire metadata from `idata$repertoires` +#' +#' @examples +#' # +#' # airr_diversity_chao1 +#' # +#' chao <- airr_diversity_chao1(immdata) +#' +#' @rdname airr_diversity +#' @concept Diversity +#' @export +airr_diversity_chao1 <- register_immunarch_method(airr_diversity_chao1_impl, "airr_diversity", "chao1") + + +#' @keywords internal +airr_diversity_shannon_impl <- function(idata) { + idata$annotations |> + select( + !!immundata::imd_schema_sym("receptor"), + !!immundata::imd_schema_sym("repertoire"), + !!immundata::imd_schema_sym("proportion") + ) |> + distinct(!!immundata::imd_schema_sym("receptor"), + !!immundata::imd_schema_sym("repertoire"), + .keep_all = TRUE + ) |> + summarise( + .by = !!immundata::imd_schema_sym("repertoire"), + shannon = -sum(!!immundata::imd_schema_sym("proportion") * dd$log2(!!immundata::imd_schema_sym("proportion"))) + ) |> + collect() +} + + +#' @description `airr_diversity_shannon` - Shannon entropy (base 2) per repertoire +#' computed from `proportion`. Ideal when you want a single evenness-aware +#' diversity score; pair with Pielou/Hill for samples with very different richness. +#' +#' @return +#' +#' ## `airr_diversity_shannon` +#' A tibble with: +#' * `imd_repertoire_id` +#' * `shannon` - entropy in bits +#' +#' @examples +#' # +#' # airr_diversity_shannon +#' # +#' sh <- airr_diversity_shannon(immdata) +#' +#' @rdname airr_diversity +#' @concept Diversity +#' @export +airr_diversity_shannon <- register_immunarch_method(airr_diversity_shannon_impl, "airr_diversity", "shannon") + + +#' @keywords internal +airr_diversity_pielou_impl <- function(idata) { + shannon_values <- airr_diversity_shannon(idata, autojoin = FALSE) + + idata$repertoires |> + select(c(immundata::imd_schema("repertoire"), immundata::imd_schema("n_receptors"))) |> + left_join(shannon_values, + by = imd_schema("repertoire") + ) |> + mutate(richness = dd$log2(!!immundata::imd_schema_sym("n_receptors")), pielou = shannon / richness) |> + collect() +} + + +#' @description `airr_diversity_pielou` - Pielou's evenness `H / log2(S)` with +#' richness `S`. Best when you need a **size-normalized** evenness score that's +#' comparable across repertoires with different receptor counts. +#' +#' @return +#' +#' ## `airr_diversity_pielou` +#' A tibble with: +#' * `imd_repertoire_id` +#' * `shannon` +#' * `n_receptors` +#' * `pielou` - evenness in `[0, 1]` (NA if `S <= 1`) +#' +#' @examples +#' # +#' # airr_diversity_pielou +#' # +#' pj <- airr_diversity_pielou(immdata) +#' +#' @rdname airr_diversity +#' @concept Diversity +#' @export +airr_diversity_pielou <- register_immunarch_method(airr_diversity_pielou_impl, "airr_diversity", "pielou") + + +#' @keywords internal +airr_diversity_index_impl <- function(idata) { + airr_diversity_hill(idata, q = 1) +} + + +#' @description `airr_diversity_index` - convenience alias for Hill number with +#' `q = 1` (`exp(Shannon)` using natural log). A solid **default single metric** +#' that's relatively robust to rare-count noise and easy to compare across samples. +#' +#' @return +#' +#' ## `airr_diversity_index` +#' A tibble with: +#' * `imd_repertoire_id` +#' * `q = 1` +#' * `hill_number` +#' * plus repertoire metadata from `idata$repertoires` +#' +#' @examples +#' # +#' # airr_diversity_index +#' # +#' idx <- airr_diversity_index(immdata) +#' +#' @rdname airr_diversity +#' @concept Diversity +#' @export +airr_diversity_index <- register_immunarch_method(airr_diversity_index_impl, "airr_diversity", "index") + + +#' @keywords internal +airr_diversity_hill_impl <- function(idata, q = 0:5) { + checkmate::check_numeric(q, lower = 0, sorted = TRUE) + + receptors <- idata$annotations |> + select( + !!immundata::imd_schema_sym("receptor"), + !!immundata::imd_schema_sym("repertoire"), + !!immundata::imd_schema_sym("proportion") + ) |> + distinct(!!immundata::imd_schema_sym("receptor"), + !!immundata::imd_schema_sym("repertoire"), + .keep_all = TRUE + ) + + result <- NULL + + # TODO: Join by value of q-s and run? if_else in case of different q-s + for (q_val in q) { + if (q_val == 0) { + q_val_tbl <- idata$repertoires |> + summarise( + .by = !!immundata::imd_schema_sym("repertoire"), + q = 0, + hill_number = as.numeric(!!immundata::imd_schema_sym("n_receptors")) + ) + } else if (q_val == 1) { + q_val_tbl <- receptors |> + summarise( + .by = !!immundata::imd_schema_sym("repertoire"), + q = q_val, + hill_number = dd$exp(-sum(!!immundata::imd_schema_sym("proportion") * dd$ln(!!immundata::imd_schema_sym("proportion")))) + ) + } else { + q_val_tbl <- receptors |> + summarise( + .by = !!immundata::imd_schema_sym("repertoire"), + q = q_val, + hill_number = dd$pow(sum(dd$pow(!!immundata::imd_schema_sym("proportion"), q_val)), 1 / (1 - q_val)) + ) + } + + if (is.null(result)) { + result <- q_val_tbl + } else { + result <- result |> union_all(q_val_tbl) + } + } + + idata$metadata |> + left_join(result, by = imd_schema("repertoire")) |> + collect() +} + + +#' @description `airr_diversity_hill` - Hill numbers ("true diversity") for +#' orders `q \eqn{\in}{in} {0, 1, 2, ...}`: `q=0` richness, `q=1` exp(Shannon), `q>1` +#' emphasizes abundant receptors. Perfect when you want a **diversity profile** +#' that tunes sensitivity to rare vs. abundant clonotypes. +#' +#' @inheritParams im_common_args +#' @param q A scalar or vector of non-negative orders. Defaults to `0:5`. +#' +#' @return +#' +#' ## `airr_diversity_hill` +#' A tibble with: +#' * `imd_repertoire_id` +#' * `q` - Hill order +#' * `hill_number` - true diversity of order `q` +#' * plus repertoire metadata from `idata$repertoires` +#' +#' @examples +#' # +#' # airr_diversity_hill +#' # +#' hill <- airr_diversity_hill(immdata, q = c(0, 1, 2)) +#' +#' @rdname airr_diversity +#' @concept Diversity +#' @export +airr_diversity_hill <- register_immunarch_method(airr_diversity_hill_impl, "airr_diversity", "hill") diff --git a/R/v1_airr_public.R b/R/v1_airr_public.R new file mode 100644 index 00000000..1eb65992 --- /dev/null +++ b/R/v1_airr_public.R @@ -0,0 +1,144 @@ +#' @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_stats.R b/R/v1_airr_stats.R new file mode 100644 index 00000000..feac3bee --- /dev/null +++ b/R/v1_airr_stats.R @@ -0,0 +1,233 @@ +#' @title Compute key immune repertoire statistics +#' +#' @description +#' `r lifecycle::badge("experimental")` +#' +#' A family of functions that extract **core descriptive statistics** from an `ImmunData` object. +#' +#' ## Available functions +#' +#' Supported methods are the following. +#' +#' @param idata An `ImmunData` object. +#' @inheritParams airr_stats_chains +#' @inheritParams airr_stats_lengths +#' @inheritParams airr_stats_genes +#' @inheritParams im_common_args +#' +#' @seealso [immundata::ImmunData] +#' +#' @examples +#' # Load data +#' immdata <- get_test_idata() |> agg_repertoires("Therapy") +#' +#' @name airr_stats +#' @concept Key AIRR statistics +NULL + + +#' @keywords internal +airr_stats_chains_impl <- function(idata, locus_col = NA) { + checkmate::assert_character(locus_col, null.ok = TRUE) + + if (is.null(idata$repertoires)) { + cli::cli_abort("No repertoires in the input ImmunData. Run {.code agg_repertoires} first.") + } + + if (is.na(locus_col)) { + locus_col <- immundata::imd_schema("locus") + + if (!locus_col %in% colnames(idata$annotations)) { + locus_col <- NULL + } + } else if (!is.null(locus_col)) { + if (!locus_col %in% colnames(idata$annotations)) { + cli::cli_alert_warning("No locus column {.code locus_col} found.") + } + } + + repertoire_id_col <- immundata::imd_schema("repertoire") + + by_cols <- c(repertoire_id_col, locus_col) + + chain_stats <- idata$annotations |> + summarise( + .by = all_of(by_cols), + n_chains = n() + ) |> + collect() + + chain_stats <- idata$repertoires |> + select(-idata$schema_repertoire) |> + left_join(chain_stats, by = repertoire_id_col) |> + collect() + + if (is.null(locus_col)) { + chain_stats |> mutate(locus = NA) + } else { + chain_stats |> rename(locus = locus_col) + } +} + + +#' @description `airr_stats_chains` --- count V(D)J *chains* per repertoire +#' (optionally split by locus). Quickly gauges capture depth per repertoire +#' and, when split by locus, reveals TRA/TRB/IGH balance. Use it for QC, +#' library-size checks, and to spot locus-specific dropouts or +#' over-representation. +#' +#' @param locus_col Column in `idata$annotations` that stores the locus (e.g. +#' `"locus"`). If `NULL` or missing, the result is not split by locus. +#' +#' @return +#' +#' ## `airr_stats_chains` Returns a tibble with columns: +#' * `repertoire_id` -- repertoire identifier +#' * `locus` -- TRA, TRB, IGH, ... (present only if `locus_col` is supplied) +#' * `n_chains` -- number of chains +#' +#' @examples +#' # +#' # airr_stats_chains +#' # +#' airr_stats_chains(immdata) +#' +#' @rdname airr_stats +#' @concept Key AIRR statistics +#' @export +airr_stats_chains <- register_immunarch_method( + core = airr_stats_chains_impl, + family = "airr_stats", + name = "chains" +) + + +#' @keywords internal +airr_stats_lengths_impl <- function(idata, seq_col = "cdr3_aa") { + idata$annotations |> + dplyr::select(dplyr::all_of(c(immundata::imd_schema("repertoire"), seq_col))) |> + dplyr::mutate(seq_len = dd$length(!!rlang::sym(seq_col))) |> + dplyr::summarise( + n = dplyr::n(), + .by = dplyr::all_of(c(immundata::imd_schema("repertoire"), "seq_len")) + ) |> + collect() |> + dplyr::mutate( + prop = n / sum(n, na.rm = TRUE), # proportion within repertoire + pct = 100 * prop, + .by = immundata::imd_schema("repertoire") + ) +} + + +#' @description `airr_stats_lengths` --- count the number of sequence lengths +#' per repertoire. Summarizes the CDR3 length distribution, a sensitive QC +#' fingerprint of repertoire prep and selection. Helpful for detecting +#' primer/UMI biases, comparing cohorts, and deriving length-based features for +#' models. +#' +#' @param seq_col Character vector with names of the columns containing +#' sequences. +#' +#' @return +#' +#' ## `airr_stats_lengths` Returns a tibble with columns: +#' * `repertoire_id` -- repertoire identifier +#' * `seq_len` -- lengths of sequences +#' * `n` -- number of receptors +#' +#' @examples +#' # +#' # airr_stats_lengths +#' # +#' airr_stats_lengths(immdata) +#' +#' @rdname airr_stats +#' @concept Key AIRR statistics +#' @export +airr_stats_lengths <- register_immunarch_method( + core = airr_stats_lengths_impl, + family = "airr_stats", + name = "lengths", + required = "seq_col" +) + + +#' @keywords internal +airr_stats_genes_impl <- function(idata, gene_col = "v_call", level = c("receptor", "barcode"), by = c(NA, "locus")) { + checkmate::assert_logical(gene_col %in% colnames(idata$annotations)) + level <- match.arg(level) + by <- match.arg(by) + if (!is.na(by)) { + checkmate::assert_logical(by %in% colnames(idata$annotations)) + } + + receptors <- idata$annotations |> + distinct(!!rlang::sym(immundata::imd_schema("receptor")), !!rlang::sym(immundata::imd_schema("repertoire")), .keep_all = TRUE) + + if (level == "receptor") { + genes <- receptors |> + summarise(.by = all_of(c(gene_col, immundata::imd_schema("repertoire"))), n = n()) + } else { + genes <- receptors |> + summarise(.by = all_of(c(gene_col, immundata::imd_schema("repertoire"))), n = sum(!!rlang::sym(immundata::imd_schema("count")))) + } + + genes |> + arrange(!!rlang::sym(immundata::imd_schema("repertoire")), desc(n)) |> + collect() +} + +#' @description `airr_stats_genes` - count V(D)J gene segments per repertoire, +#' optionally split by locus and using either receptor counts or barcode/UMI +#' counts as the measure. Profiles V/D/J gene usage to characterize repertoire +#' composition and germline biases, with optional locus split. Useful for +#' cohort comparisons, flagging clonal expansions, and producing ML-ready +#' features for repertoire-level ML tasks. +#' +#' @param gene_col A single column name in `idata$annotations` with gene segment +#' calls (e.g., `"v_call"`, `"d_call"`, `"j_call"`, `"c_call"`). Default is +#' `"v_call"`. +#' @param level One of `"receptor"` or `"barcode"`. If `"receptor"` (default), +#' the function counts **unique receptors** (one per receptor ID) that carry a +#' given gene segment. If `"barcode"`, the function **sums counts** (e.g., +#' cells/UMIs) per gene segment using the column defined by +#' `immundata::imd_schema("count")`. +#' @param by Either `NULL` (no split) or `"locus"`. When `"locus"`, the result +#' is further split by the locus column if present (as given by +#' `immundata::imd_schema("locus")`); otherwise a warning is emitted and the +#' split is ignored. +#' +#' @return +#' +#' ## `airr_stats_genes` A tibble with columns: +#' * `repertoire_id` - repertoire identifier +#' * *(optional)* `locus` - TRA, TRB, IGH, ... (present only when `by = "locus"` +#' and the locus column exists) +#' * `` - the gene segment value (e.g., V gene) +#' * `n` - the measure: +#' - if `level = "receptor"`: number of receptors carrying the gene segment +#' - if `level = "barcode"`: sum of counts across receptors for the segment +#' +#' @examples +#' # +#' # airr_stats_genes +#' # +#' # V gene usage by receptor count +#' airr_stats_genes(immdata, gene_col = "v_call", level = "receptor") +#' +#' # V gene usage by summed cell/UMI counts (if a count column is present) +#' 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") +#' +#' @rdname airr_stats +#' @concept Key AIRR statistics +#' @export +airr_stats_genes <- register_immunarch_method( + core = airr_stats_genes_impl, + family = "airr_stats", + name = "genes", + required = "gene_col" +) diff --git a/R/v1_annotate_clonality.R b/R/v1_annotate_clonality.R new file mode 100644 index 00000000..73a0452b --- /dev/null +++ b/R/v1_annotate_clonality.R @@ -0,0 +1,124 @@ +#' @title Annotate clonality - per-receptor labels for overabundance +#' +#' @description +#' `r lifecycle::badge("experimental")` +#' +#' A small family of helpers that **add clonality labels to each receptor** in +#' an [immundata::ImmunData] object. +#' +#' ## Available functions +#' * `annotate_clonality_rank()` - label by **rank bins** within each repertoire. +#' * `annotate_clonality_prop()` - label by **proportion bins** (named thresholds). +#' +#' @param idata An [immundata::ImmunData] object. +#' @inheritParams im_common_args +#' +#' @seealso +#' * Per-repertoire summaries: [airr_clonality] +#' * Data container: [immundata::ImmunData] +#' +#' @examples +#' \dontrun{ +#' idata <- get_test_idata() |> agg_repertoires("Therapy") +#' idata_rank <- annotate_clonality_rank(idata) +#' idata_prop <- annotate_clonality_prop(idata) +#' } +#' +#' @name annotate_clonality +#' @concept Clonality +NULL + + +#' @keywords internal +annotate_clonality_rank_impl <- function(idata, + bins = c(10, 30, 100, 300, 1000, 10000, 100000)) { + checkmate::check_numeric(bins, lower = 1) + + bins <- sort(bins, decreasing = FALSE) + + clonality_df <- core_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")) + annotate_immundata(idata, + clonality_df |> + select( + immundata::imd_schema("receptor"), + immundata::imd_schema("repertoire"), + clonal_rank_bin + ), + by = by_cols + ) +} + + +#' @description +#' `annotate_clonality_rank()` - for each repertoire, receptors are ordered by +#' within-repertoire abundance (proportion) and assigned a **rank bin** label. +#' +#' @inheritParams airr_clonality_rank +#' +#' @return +#' An [immundata::ImmunData] whose `$annotations` gains: +#' * `clonal_rank_bin` - integer-like label with the applied rank threshold +#' (outside all thresholds -> `NA`). +#' +#' @rdname annotate_clonality +#' @concept Clonality +#' @export +annotate_clonality_rank <- register_immunarch_method( + core = annotate_clonality_rank_impl, + family = "annotate_clonality", + name = "rank", + need_repertoires = TRUE +) + + +#' @keywords internal +annotate_clonality_prop_impl <- function( + idata, bins = c( + Hyperexpanded = 1e-2, + Large = 1e-3, + Medium = 1e-4, + Small = 1e-5, + Rare = 1e-6 + )) { + checkmate::check_numeric(bins, lower = 0, min.len = 1) + + bins <- sort(bins, decreasing = TRUE) + + clonality_df <- core_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")) + annotate_immundata(idata, + clonality_df |> + select( + immundata::imd_schema("receptor"), + immundata::imd_schema("repertoire"), + clonal_prop_bin + ), + by = by_cols + ) +} + + +#' @description +#' `annotate_clonality_prop()` - label each receptor by **proportion bin** +#' using named thresholds (matched in descending order; else `"Ultra-rare"`). +#' +#' @inheritParams airr_clonality_prop +#' +#' @return +#' An [immundata::ImmunData] whose `$annotations` gains: +#' * `clonal_prop_bin` - label from `names(bins)` or `"Ultra-rare"`. +#' +#' @rdname annotate_clonality +#' @concept Clonality +#' @export +annotate_clonality_prop <- register_immunarch_method( + core = annotate_clonality_prop_impl, + family = "annotate_clonality", + name = "prop", + need_repertoires = TRUE +) diff --git a/R/v1_core_clonality.R b/R/v1_core_clonality.R new file mode 100644 index 00000000..fcb91328 --- /dev/null +++ b/R/v1_core_clonality.R @@ -0,0 +1,61 @@ +#' @keywords internal +core_clonality_rank <- function(idata, bins) { + checkmate::check_numeric(bins, lower = 1) + + bins <- sort(bins, decreasing = FALSE) + + sql_expr <- paste0( + "CASE ", + paste0(map_chr( + bins, + ~ cli::format_inline("WHEN ROW_NUMBER() OVER (PARTITION BY {immundata::imd_schema('repertoire')} ORDER BY {immundata::imd_schema('proportion')} DESC) <= {.x} THEN {.x}") + ), collapse = " "), " ELSE NULL END" + ) + + clonality_df <- idata$annotations |> + select(all_of(c( + immundata::imd_schema("repertoire"), + immundata::imd_schema("receptor"), + immundata::imd_schema("proportion") + ))) |> + distinct(!!immundata::imd_schema_sym("repertoire"), + !!immundata::imd_schema_sym("receptor"), + .keep_all = TRUE + ) |> + arrange() |> + as_tbl() |> + mutate(clonal_rank_bin = dbplyr::sql(sql_expr)) |> + as_duckdb_tibble() |> + compute() + + clonality_df +} + + +#' @keywords internal +core_clonality_prop <- function(idata, bins) { + sql_expr <- paste0( + "CASE ", + paste0(map2_chr( + bins, names(bins), + ~ sprintf("WHEN %s >= %s THEN '%s'", immundata::imd_schema("proportion"), .x, .y) + ), collapse = " "), " ELSE 'Ultra-rare' END" + ) + + clonality_df <- idata$annotations |> + select(all_of(c( + immundata::imd_schema("repertoire"), + immundata::imd_schema("receptor"), + immundata::imd_schema("proportion") + ))) |> + distinct(!!immundata::imd_schema_sym("repertoire"), + !!immundata::imd_schema_sym("receptor"), + .keep_all = TRUE + ) |> + duckplyr::as_tbl() |> + mutate(clonal_prop_bin = dbplyr::sql(sql_expr)) |> + duckplyr::as_duckdb_tibble() |> + compute() + + clonality_df +} diff --git a/R/v1_migration_updates.R b/R/v1_migration_updates.R new file mode 100644 index 00000000..7019e278 --- /dev/null +++ b/R/v1_migration_updates.R @@ -0,0 +1,60 @@ +#' @keywords internal +immunarch_v1_update_oct_2025 <- function() { + cli::cli_h1("{cli::col_green('immunarch')} {cli::col_yellow('0.10.0')} -- Critical Pre-release Notice") + + cli::cli_alert_warning("Update #1 [Oct 2025] -- Major changes are coming in {cli::col_green('immunarch')} {cli::col_yellow('1.0.0')}!") + cli::cli_text(cli::col_yellow(cli::spark_line(runif(110, 0, 1)))) + + cli::cli_par() + cli::cli_text() + cli::cli_text( + "Hi, this is Vadim Nazarov speaking - author of {cli::col_green('immunarch')}. ", + "{cli::col_green('immunarch')} is finally graduating out of the {cli::col_yellow('0.x.y')} development cycle. ", + "I'm preparing our {cli::col_yellow('1.0.0')} release, which will remain stable and free of sudden changes until we approach {cli::col_yellow('2.0.0')}. ", + "A scientific publication will accompany it for proper citation. ", + "Significant changes are coming, and I want to ensure you have everything you need to migrate to the new version." + ) + + cli::cli_par() + cli::cli_text() + cli::cli_text("Here's a preview of what's coming in {cli::col_green('immunarch')} {cli::col_yellow('1.0.0')}:") + cli::cli_bullets(c( + "i" = "Some computationally intensive or advanced features (e.g., distance computations, graph-based analyses, dimensionality reduction techniques) will move to separate packages, making {cli::col_green('immunarch')} much lighter to install and manage.", + "i" = "New functions will replace older ones to make code more readable and maintainable. Legacy functions will remain temporarily, but they won't be updated and will be removed {cli::col_yellow('around 2027')}.", + "i" = "We will discontinue support for most custom file formats because the AIRR ecosystem is now mature enough; most tools adhere to the AIRR standard.", + "i" = "The package will transition from data frames to the new {cli::col_blue('ImmunData')} structure, better suited for handling larger, more complex, and multimodal datasets (e.g., single-cell, spatial).", + "i" = "{cli::col_blue('ImmunData')} is available in the separate {cli::col_blue('immundata')} package, which you can already install via {cli::col_cyan('pak::pkg_install(\"immundata\")')}.", + "i" = "The {cli::col_blue('ImmunData')}-based computations will be significantly faster, will support datasets larger than RAM, and will fully adhere to AIRR Community standards.", + "i" = "There are currently only a handful of functions that implement {cli::col_blue('ImmunData')}-based computations. However, if you want to start learning it, or you have large-scale data, now is the best time: tutorials are available at {.url https://github.com/immunomind/immundata} and {.url https://immunomind.github.io/docs/}." + )) + + cli::cli_par() + cli::cli_text() + cli::cli_text( + "See the dedicated migration guide for what you can do now and how to prepare for the future:" + ) + cli::cli_text(">> visit {.url https://immunomind.github.io/docs/tutorials/migration}") + + cli::cli_par() + cli::cli_text() + cli::cli_text( + "See the comprehensive tutorial on how to analyse single-cell AIRR data:" + ) + cli::cli_text(">> visit {.url https://immunomind.github.io/docs/tutorials/single_cell}") + + cli::cli_par() + cli::cli_text() + cli::cli_alert_success("Thank you for supporting {cli::col_green('immunarch')} from its early days. Your feedback, contributions, and trust have driven its evolution, and I deeply appreciate it.") + + cli::cli_par() + cli::cli_text() + cli::cli_alert_info("Questions, comments, ideas? I'm available via:") + cli::cli_text(">> Support email: {.url mailto:support@immunomind.com}") + cli::cli_text(">> GitHub tickets: {.url https://github.com/immunomind/immunarch}") + cli::cli_text(">> LinkedIn: {.url https://www.linkedin.com/in/vdnaz/}") + + cli::cli_par() + cli::cli_text() + cli::cli_text("--") + cli::cli_text("Vadim I. Nazarov") +} diff --git a/R/v1_migration_utils.R b/R/v1_migration_utils.R new file mode 100644 index 00000000..79d0bb33 --- /dev/null +++ b/R/v1_migration_utils.R @@ -0,0 +1,44 @@ +#' Get the Latest immunarch Update +#' +#' Retrieves an update message for immunarch. +#' +#' If `datepoint` is set to `"latest"`, the function returns the most recent update. +#' Otherwise, specify the update date key (e.g., `"Apr 2025"`) to retrieve that particular update. +#' If no matching update is found, a warning is issued along with available update keys. +#' +#' @param datepoint A string specifying the update date. Use `"latest"` for the most recent update +#' or supply a valid date key (e.g., `"Apr 2025"`). +#' +#' @return A character string with the update details or a warning if the key is not found. +#' +#' @seealso [list_immunarch_news()] +#' +#' @concept migration_utility +#' +#' @export +get_immunarch_news <- function(datepoint = "latest") { + if (datepoint == "latest") { + immunarch_v1_updates[[length(immunarch_v1_updates)]]() + } else if (datepoint %in% names(immunarch_v1_updates)) { + immunarch_v1_updates[[datepoint]]() + } else { + cli::cli_alert_warning("No {datepoint} date in the list of {cli::col_green('immunarch')} updates. Available update names are: {immunarch:::list_immunarch_news()}") + } +} + +#' List Available immunarch Updates +#' +#' Returns the list of available update keys for immunarch v1. +#' +#' @return A character vector containing all the date keys for the available updates. +#' +#' @seealso [get_immunarch_news()] +#' +#' @concept migration_utility +#' +#' @export +list_immunarch_news <- function() { + for (i in seq_along(names(immunarch_v1_updates))) { + cat(names(immunarch_v1_updates), " -> ", "run immunarch::get_immunarch_news(", '"', names(immunarch_v1_updates), '"', ")", sep = "") + } +} diff --git a/R/v1_package.R b/R/v1_package.R new file mode 100644 index 00000000..42322b89 --- /dev/null +++ b/R/v1_package.R @@ -0,0 +1,28 @@ +make_immunarch_features <- function(ires, method_name = NULL, feature_col = NULL, value_col = NULL) { + checkmate::check_data_frame(ires) + checkmate::check_character(method_name, null.ok = TRUE) + checkmate::check_character(feature_col, null.ok = TRUE) + checkmate::check_character(value_col, null.ok = TRUE) + + to_rename <- c("feature" = feature_col, "value" = value_col) + + if (is.null(method_name)) { + ires <- ires |> + mutate(method = method_name) + } + + ires |> + rename(to_rename) +} + +immunarch_methods <- function(family_name = NULL) { + checkmate::check_string(family_name) + + if (is.null(family_name)) { + ls(IMMUNARCH_METHOD_REGISTRY) + } else if (family_name %in% IMMUNARCH_METHOD_REGISTRY) { + ls(IMMUNARCH_METHOD_REGISTRY[[family_name]]) + } else { + cli::cli_abort("No such family name: {family_name}") + } +} diff --git a/R/zzz.R b/R/zzz.R new file mode 100644 index 00000000..b9a94425 --- /dev/null +++ b/R/zzz.R @@ -0,0 +1,40 @@ +#' Get a list of package updates +#' @concept migration_utility +immunarch_v1_updates <- c( + "Oct 2025" = immunarch_v1_update_oct_2025 +) + +.onAttach <- function(libname, pkgname) { + lines <- c( + paste0("Hi, this is Vadim Nazarov - author of ", cli::col_green("immunarch"), "."), + paste0( + cli::col_green("immunarch"), + " is moving toward its 1.0 release. It will be faster, more user-friendly, and ready for publication. ", + "Some functions will be deprecated or replaced with newer, more powerful methods." + ), + "", + "- Click {.run [get_immunarch_news()](immunarch::get_immunarch_news())} to read the latest update (what changed, what's new, how to migrate, what's next).", + "", + "- Click {.run [list_immunarch_news()](immunarch::list_immunarch_news())} to list all updates (latest: {cli::col_yellow('#1, Oct 2025')}).", + "", + "- Migration guide: {.url https://immunomind.github.io/docs/tutorials/migration}", + "", + "To load the package without this message: {.code suppressPackageStartupMessages(library('immunarch'))}", + "", + "- Vadim I. Nazarov" + ) + + msg <- paste(lines, collapse = "\n") + cli::cli_inform(cli::format_inline(msg), class = "packageStartupMessage") +} + + +.onLoad <- function(libname, pkgname) { + op <- options() + op.immunarch <- list( + immunarch.autojoin = FALSE # default + ) + toset <- !(names(op.immunarch) %in% names(op)) + if (any(toset)) options(op.immunarch[toset]) + invisible() +} diff --git a/README.md b/README.md index 56c74261..2acccc21 100644 --- a/README.md +++ b/README.md @@ -1,198 +1,242 @@ -[![Follow](https://img.shields.io/twitter/follow/immunomind.svg?style=social)](https://twitter.com/intent/follow?screen_name=immunomind) -[![CRAN](http://www.r-pkg.org/badges/version-ago/immunarch?style=flat-square)](https://cran.r-project.org/package=immunarch) -[![Downloads_all](http://cranlogs.r-pkg.org/badges/grand-total/immunarch)](https://www.r-pkg.org/pkg/immunarch) -[![Downloads_week](http://cranlogs.r-pkg.org/badges/last-week/immunarch)](https://www.r-pkg.org/pkg/immunarch) -[![Issues](https://img.shields.io/github/issues/immunomind/immunarch?style=flat-square)](https://github.com/immunomind/immunarch/issues) -[![CI](https://gitlab.com/immunomind/immunarch/badges/master/pipeline.svg?style=flat-square)](https://gitlab.com/immunomind/immunarch/-/jobs) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3367200.svg)](https://doi.org/10.5281/zenodo.3367200) -![Visitors](https://visitor-badge.glitch.me/badge?page_id=immunomind.immunarch) -[![Downloads_all](http://cranlogs.r-pkg.org/badges/grand-total/tcR)](https://www.r-pkg.org/pkg/tcR) -[![Downloads_week](http://cranlogs.r-pkg.org/badges/last-week/tcR)](https://www.r-pkg.org/pkg/tcR) +
+

🧬 immunarchMulti-modal immune repertoire analysis in R

+
+--- -# `immunarch` --- Fast and Seamless Exploration of Single-cell and Bulk T-cell/Antibody Immune Repertoires in R - -## Why `immunarch`? -- **Work with any type of data:** single-cell, bulk, data tables, databases --- you name it. -- **Community at the heart:** ask questions, share knowledge and thrive in the community of almost 30,000 researchers and medical scientists worldwide. **Pfizer, Novartis, Regeneron, Stanford, UCSF** and **MIT** trust us. -- **One plot --- one line:** write a [whole PhD thesis in 8 lines of code](https://twitter.com/Nusob88/status/1127601201112129536) or reproduce almost any publication in 5-10 lines of `immunarch` code. -- **Be on the bleeding edge of science:** we regularly update `immunarch` with the latest methods. [Let us know what you need!](#help-the-community) -- **Automatic format detection and parsing** for all popular immunosequencing formats: from **MiXCR** and **ImmunoSEQ** to **10XGenomics** and **ArcherDX**. - - -### Lightning-fast Start -```r -install.packages("immunarch") # Install the package -library(immunarch); data(immdata) # Load the package and the test dataset -repOverlap(immdata$data) %>% vis() # Compute and visualise the most important statistics: -geneUsage(immdata$data[[1]]) %>% vis() # public clonotypes, gene usage, sample diversity -repDiversity(immdata$data) %>% vis(.by = "Status", .meta = immdata$meta) # Group samples -``` - + + +

+ Tutorials + | + API reference + | + Ecosystem + | + Publication (coming soon...) +

-### From Berkeley with devotion +--- -`immunarch` is brought to you by [ImmunoMind](https://immunomind.com) --- a [UC Berkeley SkyDeck](https://www.forbes.com/sites/avivalegatt/2019/01/07/launch-your-startup-at-these-five-college-incubators/) startup. ImmunoMind improves the design of adoptive T-cell therapies such as CAR-T by precisely identifying T-cell subpopulations and their immune profile. ImmunoMind's tools are trusted by researchers from top pharma companies and universities, including 10X Genomics, Pfizer, Regeneron, UCSF, MIT, Stanford, John Hopkins School of Medicine and Vanderbilt University. +`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: -[![Follow](https://img.shields.io/twitter/follow/immunomind.svg?style=social)](https://twitter.com/intent/follow?screen_name=immunomind) +- **Multi-modal immune profiling:** compute receptor- and repertoire-level statistics leveraging single-cell, spatial, immunogenicity or any other receptor annotations; ---- +- **Immunomics at scale:** work seamlessly with datasets that don't fit in memory; -## Table of Contents +- **Immune biomarker discovery:** stratify cohorts and timepoints, derive repertoire signatures (diversity/clonality, V/J usage, similarity), and track antigen-annotated clonotypes; -- [Introduction](#introduction) -- [Contact](#contact) -- [Installation](#installation) -- [Features](#features) -- [Quick Start](#quick-start) -- [Bugs and Issues](#bugs-and-issues) -- [Contribution](#help-the-community) -- [Citation](#citation) +- **Feature engineering:** build Machine Learning-ready feature tables (receptor-, ssample- and cohort-level) from core repertoire metrics and annotations, with consistent IDs/metadata for downstream statistics or modeling; -## Introduction +- **Modular, extendable, adaptable:** add new analyses and metrics via a extension API, and use adapters to interoperate with other AIRR tools and formats. -`immunarch` is an R package designed to analyse T-cell receptor (TCR) and B-cell receptor (BCR) repertoires, mainly tailored to medical scientists and bioinformaticians. The mission of `immunarch` is to make immune sequencing data analysis as effortless as possible and help you focus on research instead of coding. +## 🤔 Why `immunarch`? -## Contact -Create a ticket with a bug or question on [GitHub Issues](https://github.com/immunomind/immunarch/issues) to get help from the community and enrich it with your experience. If you need to send us sensitive data, feel free to contact us via [support@immunomind.io](mailto:support@immunomind.io). +As immune repertoire sequencing becomes a mainstream technology, adopted by major platforms and integrated into more translational and clinical workflows, tooling expectations are changing rapidly. +The pace of innovation and data growth sometimes outstrips what even the most dedicated tool developers can deliver. +That's why it's the perfect moment to step back and rethink **how** and **why** we analyze AIRR data. +Instead of racing to patch each new problem, we need to prepare for the **next epoch** of immunomics. -## Installation +**What defines this next epoch?** -### Latest release on CRAN -In order to install `immunarch` execute the following command: +A massive shift in focus: from pure research towards biomarker discovery, personalized immunotherapies, and integration of immune repertoire data into real clinical decision-making. -```r -install.packages("immunarch") -``` +Today's AIRR analysis must handle: -That's it, you can start using `immunarch` now! See the [Quick Start](#quick-start) section below to dive into immune repertoire data analysis. If you run in any trouble during installation, take a look at the [Installation Troubleshooting](https://immunarch.com/articles/v1_introduction.html#installation-troubleshooting) section. +- **Multi-modal data:** bulk and single-cell V(D)J, spatial transcriptomics, gene expression, clinical metadata, and antigen specificity -- all together; -Note: there are quite a lot of dependencies to install with the package because it installs all the widely-used packages for data analysis and visualisation. You got both the AIRR data analysis framework and the full Data Science package ecosystem with only one command, making `immunarch` the entry-point for single-cell & immune repertoire Data Science. +- **Massive scale:** experiments that move from gigabytes to tens or hundreds of gigabytes, or even terabytes; +- **Reproducibility and collaboration:** workflows that need to be shared, versioned, and rerun months or years later, sometimes by new teams. -### Latest release on GitHub -If the above command doesn't work for any reason, try installing `immunarch` directly from its repository: +With this new landscape, the **how** and **why** of AIRR data analysis are evolving: -```r -install.packages(c("devtools", "pkgload")) # skip this if you already installed these packages -devtools::install_github("immunomind/immunarch") -devtools::reload(pkgload::inst("immunarch")) -``` +- The focus is moving from "can I parse my data?" to "can I robustly extract insights, find biomarkers, and build ML-ready features for discovery or diagnostics?" +- It's not enough for a toolkit to just work. It needs to scale, interoperate, and empower new kinds of science, including complex Deep Learning and foundation models. -### Latest pre-release on GitHub -Since releasing on CRAN is limited to one release per one or two months, you can install the latest pre-release version with all the bleeding edge and optimised features directly from the code repository. In order to install the latest pre-release version, you need to execute the following commands: +By taking a step back and rethinking the core "how" and "why" of AIRR analysis, `immunarch` prepares you for the next epoch of immunomics -- so your science is ready, whatever comes next. -```r -install.packages(c("devtools", "pkgload")) # skip this if you already installed these packages -devtools::install_github("immunomind/immunarch", ref="dev") -devtools::reload(pkgload::inst("immunarch")) -``` +--- -You can find the list of releases of `immunarch` here: https://github.com/immunomind/immunarch/releases +> [!WARNING] +> `immunarch` is evolving towards `1.0` version and undergoing huge changes. +> Please check the updates here: https://github.com/immunomind/immunarch/issues/432 +> +> To install the latest pre-1.0 version, use `pak::pkg_install("immunomind/immunarch@0.9.1")` +> +> To install the latest 1.0 pre-release version, use `pak::pkg_install("immunomind/immunarch")` +--- -## Key Features +- 🤔 [Why `immundata`?](#-why--immundata-) +- 📦 [Installation](#-installation) +- ⚡ [Quick Start](#-quick-start) +- [📄 Documentation](#-documentation) +- [🪲 Bugs and Issues](#-bugs-and-issues) +- 🏷 [About](#-about) + - [Citation](#citation) + - [License](#license) + - [Author and contributors](#author-and-contributors) + - [Commercial usage](#commercial-usage) -1. Data agnostic. Fast and easy manipulation of immune repertoire data: +--- - + The package automatically detects the format of your files---no more guessing what format is *that* file, just pass them to the package; - - + Supports all popular TCR and BCR analysis and post-analysis formats, including single-cell data: [ImmunoSEQ](https://www.adaptivebiotech.com/adaptive-immunosequencing/), [IMGT](https://www.imgt.org/IMGTindex/IMGTHighV-QUEST.php), [MiTCR](https://github.com/milaboratory/mitcr), [MiXCR](https://github.com/milaboratory/mixcr), [MiGEC](https://github.com/mikessh/migec), [MigMap](https://github.com/mikessh/migmap), [VDJtools](https://github.com/mikessh/vdjtools), [tcR](https://github.com/imminfo/tcr), [AIRR](http://docs.airr-community.org/en/latest/), [10XGenomics](https://www.10xgenomics.com/resources/datasets?menu%5Bproducts.name%5D=Single+Cell+Immune+Profiling), ArcherDX. More coming in the future; +## 📦 Installation - + Works on any data source you are comfortable with: R data frames, data tables from [data.table](https://rdatatable.gitlab.io/data.table/), databases like [MonetDB](https://github.com/MonetDB), Apache Spark data frames via [sparklyr](https://spark.posit.co/); - - + Tutorial is available [here](https://immunarch.com/articles/v2_data.html). +### Prerequisites -2. Beginner-friendly. Immune repertoire analysis made simple: +Before installing any release or pre-release version of `immunarch`, please install `pak` that will simplify the installation of any package, not just `immunarch`: - + Most methods are incorporated in a couple of main functions with clear naming---no more remembering dozens and dozens of functions with obscure names. For details see [link](https://immunarch.com/articles/web_only/v3_basic_analysis.html); +```r +install.packages("pak", repos = sprintf("https://r-lib.github.io/p/pak/stable/%s/%s/%s", .Platform$pkgType, R.Version()$os, R.Version()$arch)) +``` - + Repertoire overlap analysis *(common indices including overlap coefficient, Jaccard index and Morisita's overlap index)*. Tutorial is available [here](https://immunarch.com/articles/web_only/v4_overlap.html); - - + Gene usage estimation *(correlation, Jensen-Shannon Divergence, clustering)*. Tutorial is available [here](https://immunarch.com/articles/web_only/v5_gene_usage.html); +More info if needed is available on [pak website](https://pak.r-lib.org/#arrow_down-installation). - + Diversity evaluation *(ecological diversity index, Gini index, inverse Simpson index, rarefaction analysis)*. Tutorial is available [here](https://immunarch.com/articles/web_only/v6_diversity.html); +### Install the latest version - + Tracking of clonotypes across time points, widely used in vaccination and cancer immunology domains. Tutorial is available [here](https://immunarch.com/articles/web_only/v8_tracking.html); - - + K-mer distribution measures and statistics. Tutorial is available [here](https://immunarch.com/articles/web_only/v9_kmers.html); - - + Coming in the next releases: CDR3 amino acid physical and chemical properties assessment, mutation networks. +To install the latest release of `immunarch`, simply run: -3. Seamless publication-ready plots with a built-in tool for visualisation manipulation: +```r +pak::pkg_install("immunomind/immunarch") +``` - + Rich visualisation procedures with [ggplot2](https://ggplot2.tidyverse.org/); - - + Built-in tool `FixVis` makes your plots publication-ready: easily change font sizes, text angles, titles, legends and many more with clear-cut GUI; - - + Tutorial is available [here](https://immunarch.com/articles/web_only/v7_fixvis.html). - - -## Quick start -The gist of the typical TCR or BCR data analysis workflow can be reduced to the next few lines of code. +Mind that this will install the package from our GitHub instead of CRAN. This method is much preferred due to limitations of CRAN and reliance on other packages, which are distributed via `pak` as well. -### Use `immunarch` data +### Other installation options -**1) Load the package and the data** +We will periodically release `immunarch` on CRAN. To install it from CRAN, run ```r -library(immunarch) # Load the package into R -data(immdata) # Load the test dataset +pak::pkg_install("immunarch") ``` -**2) Calculate and visualise basic statistics** +If you are willing to try unstable yet bleeding edge features, or if there are some hot fix for your open GitHub ticket, please install the development version: ```r -repExplore(immdata$data, "lens") %>% vis() # Visualise the length distribution of CDR3 -repClonality(immdata$data, "homeo") %>% vis() # Visualise the relative abundance of clonotypes +pak::pkg_install("immunomind/immunarch@dev") ``` -**3) Explore and compare T-cell and B-cell repertoires** + +## ⚡ Quick Start + ```r -repOverlap(immdata$data) %>% vis() # Build the heatmap of public clonotypes shared between repertoires -geneUsage(immdata$data[[1]]) %>% vis() # Visualise the V-gene distribution for the first repertoire -repDiversity(immdata$data) %>% vis(.by = "Status", .meta = immdata$meta) # Visualise the Chao1 diversity of repertoires, grouped by the patient status +# Install `pak` - a blazingly-fast package manager +install.packages("pak", repos = sprintf("https://r-lib.github.io/p/pak/stable/%s/%s/%s", .Platform$pkgType, R.Version()$os, R.Version()$arch)) + +# Install and load immunarch along with the pre-packaged data +pak::pkg_install("immundata/immunarch") +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_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") +immdata <- read_repertoires("", metadata = mdtable) + +# Use your own data by reading sample files directly +mdtable <- read_metadata("data/metadata.csv") +immdata <- read_repertoires("data/*.tsv.gz", metadata = mdtable) ``` -### Use your own data +Oh, and one small thing. Even if you have tens of gigabytes of the data, you won't need to adapt the code to a server. +The code will be exactly the same — `immunarch` got your back thanks to [`immundata`](https://github.com/immunomind/immundata/). + + +## 📄 Documentation + +To get a list of available methods and their descriptions, run the default help command in R on specific functions or on a function family prefix: ```r -library(immunarch) # Load the package into R -immdata <- repLoad("path/to/your/data") # Replace it with the path to your data. Immunarch automatically detects the file format. -``` +# This is the same +?airr_stats +# as this +?airr_stats_genes + +# Basic statistics - gene usage, length distribution +?airr_stats + +# Public receptor indices - overlap, jaccard, morisita +?airr_public -### Advanced methods +# Clonality analysis - clonal lines, occupied space, clonal space homeostasis +?airr_clonality -For advanced methods such as clonotype annotation, clonotype tracking, k-mer analysis and public repertoire analysis see "Tutorials". +# Diversity analysis - pielou, shannon, chao1 +?airr_diversity + +# ... more to come ... +``` + +More detailed documentation, guides and comprehensive tutorials are available on the ecosystem website: [https://immunomind.github.io/docs/](https://immunomind.github.io/docs/). -## Bugs and Issues +## 🪲 Bugs and Issues -The mission of `immunarch` is to make bulk and single-cell immune repertoires analysis painless. All bug reports, documentation improvements, enhancements and ideas are appreciated. Just let us know via [GitHub](https://github.com/immunomind/immunarch/issues) (preferably) or [support@immunomind.io](mailto:support@immunomind.io) (in case of private data). +The mission of `immunarch` is to make bulk and single-cell immune repertoires analysis painless. All bug reports, documentation improvements, enhancements and ideas are appreciated. Just let us know via [GitHub](https://github.com/immunomind/immunarch/issues) (preferably) or [support@immunomind.com](mailto:support@immunomind.com) (in case of private data). Bug reports must: 1. Include a short, self-contained R snippet reproducing the problem. -2. Add a minimal data sample for us to reproduce the problem. In case of sensitive data you can send it to [support@immunomind.io](mailto:support@immunomind.io) instead of GitHub issues. +2. Add a minimal data sample for us to reproduce the problem. In case of sensitive data you can send it to [support@immunomind.com](mailto:support@immunomind.com) instead of GitHub issues. 3. Explain why the current behavior is wrong/not desired and what you expect instead. 4. If the issue is about visualisations, please attach a picture to the issue. In other case we wouldn't be able to reproduce the bug and fix it. +We are always open to contributions. There are three ways to contribute: -## Help the community +1. Create an issue [here](https://github.com/immunomind/immunarch/issues) and describe what would you like to improve or discuss. -Aspiring to help the community build the ecosystem of scRNAseq & AIRR analysis tools? Found a bug? A typo? Would like to improve documentation, add a method or optimise an algorithm? +2. Create an issue or find one [here](https://github.com/immunomind/immunarch/issues), fork the repository and make a pull request with the bugfix or improvement. -We are always open to contributions. There are two ways to contribute: +3. Find an existing issue and help others resolve this. -1. Create an issue [here](https://github.com/immunomind/immunarch/issues) and describe what would you like to improve or discuss. -2. Create an issue or find one [here](https://github.com/immunomind/immunarch/issues), fork the repository and make a pull request with the bugfix or improvement. +## 🏷 About +### Citation -## Citation +> Temporary citation is below. The main manuscript is in preparation. Preprint on BioArxiv is coming soon as of 2025. ImmunoMind Team. (2019). immunarch: An R Package for Painless Bioinformatics Analysis of T-Cell and B-Cell Immune Repertoires. Zenodo. http://doi.org/10.5281/zenodo.3367200 @@ -211,14 +255,20 @@ BibTex: For EndNote citation import the [`immunarch-citation.xml`](https://gitlab.com/immunomind/immunarch/raw/master/immunarch-citation.xml?inline=false) file. -Preprint on BioArxiv is coming soon. - -## License +### License The package is freely distributed under the Apache-2.0 license. You can read more about it [here](https://www.tldrlegal.com/license/apache-license-2-0-apache-2-0). -For commercial or server use, please contact ImmunoMind via [support@immunomind.io](mailto:support@immunomind.io) about solutions for biomarker data science of single-cell immune repertoires. +### Author and contributors + +- **Vadim I. Nazarov – main author and developer** +- Vasily Tsvetkov +- Aleksandr Popov +- Ivan Balashov + +### Commercial usage +`immunarch` is free to use for commercial usage as per Apache-2.0 license. However, corporate users will not get a prioritized support for `immunarch`- or AIRR-related issues. The priority of open-source tool `immunarch` is open-source science. -## Commercial Support +If you are looking for prioritized support and setting up your data pipelines, consider contacting [Vadim Nazarov](https://www.linkedin.com/in/vdnaz/) for commercial consulting / support options / workshops and training sessions / designing data platforms and machine learning systems for multi-omics / or anything related. diff --git a/_pkgdown.yml b/_pkgdown.yml index e6e95042..cb97fe46 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1,198 +1,178 @@ url: https://immunarch.com template: - params: + bootstrap: 5 + bslib: bootswatch: cosmo + pkgdown-nav-height: 100px + params: ganalytics: UA-128418614-2 - docsearch: - api_key: '94207562f34b455c0796790d104e3549' - index_name: 'immunarch' authors: ImmunoMind: - href: https://immunomind.io + href: https://immunomind.com Vadim I. Nazarov: href: https://www.linkedin.com/in/vdnaz Vasily O. Tsvetkov: href: https://www.linkedin.com/in/vasily-tsvetkov-227218ab - Siarhei Fiadziushchanka: - href: https://www.linkedin.com/in/sergey-f-709b0415b/ - Eugene Rumynskiy: - href: https://www.linkedin.com/in/erumynskiy/ Aleksandr A. Popov: href: https://www.linkedin.com/in/aleksandr-popov-634878105/ Ivan Balashov: href: https://www.linkedin.com/in/ivan-balashov/ - Maria Samokhina: - href: https://www.linkedin.com/in/maria-volobueva-b0856a223/ articles: -- title: All tutorials +- title: "Immunarch v0.9" + subtitle: "Deprecated" desc: ~ contents: - - '`v1_introduction`' - - '`v2_data`' - - '`web_only/v21_singlecell`' - - '`web_only/v3_basic_analysis`' - - '`web_only/load_mixcr`' - - '`web_only/load_10x`' - - '`web_only/v4_overlap`' - - '`web_only/v5_gene_usage`' - - '`web_only/v6_diversity`' - - '`web_only/v7_fixvis`' - - '`web_only/v8_tracking`' - - '`web_only/v9_kmers`' - - '`web_only/v11_db`' - - '`web_only/community`' - - '`web_only/repFilter_v3`' - - '`web_only/v10_prop`' - - '`web_only/BCRpipeline`' - - '`web_only/clustering`' + - '`web_only_v0/introduction`' + - '`web_only_v0/data`' + - '`web_only_v0/v21_singlecell`' + - '`web_only_v0/v3_basic_analysis`' + - '`web_only_v0/load_mixcr`' + - '`web_only_v0/load_10x`' + - '`web_only_v0/v4_overlap`' + - '`web_only_v0/v5_gene_usage`' + - '`web_only_v0/v6_diversity`' + - '`web_only_v0/v7_fixvis`' + - '`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`' + - '`web_only_v0/clustering`' navbar: + bg: dark + type: dark structure: - left: [articles, reference, covid19] - right: [im_link, twitter, github] + left: [tutorial, articles, reference] + right: [github] components: home: ~ news: ~ - covid19: - text: "COVID-19" - href: https://github.com/immunomind/covid19 + tutorial: + text: "Immunarch v1.0" + href: https://immunomind.github.io/docs/tutorials/single-cell/ + migration: + text: "Migration Guide" + href: https://immunomind.github.io/docs/tutorials/migration/ reference: - text: Reference + text: "Reference" href: reference/index.html articles: - text: Start Here + text: "Immunarch v0.9" menu: - - text: Installation & troubleshooting - href: articles/v1_introduction.html + - text: "Installation & troubleshooting" + href: articles/web_only_v0/introduction.html + - text: '---' - text: First steps + - text: Data loading - href: articles/v2_data.html + href: articles/web_only_v0/data.html + - text: 'How-to: Loading MiXCR Data' - href: articles/web_only/load_mixcr.html + href: articles/web_only_v0/load_mixcr.html + - text: 'How-to: Loading 10x Genomics Data' - href: articles/web_only/load_10x.html + href: articles/web_only_v0/load_10x.html + - text: 'How-to: Single-cell and paired chain data' - href: articles/web_only/v21_singlecell.html + href: articles/web_only_v0/v21_singlecell.html + - text: Basic statistics and clonality - href: articles/web_only/v3_basic_analysis.html + href: articles/web_only_v0/v3_basic_analysis.html + - text: 'Data filtering' - href: articles/web_only/repFilter_v3.html + href: articles/web_only_v0/repFilter_v3.html + - text: '---' + - text: Repertoire-level exploration and comparison + - text: Repertoire overlap and public clonotypes - href: articles/web_only/v4_overlap.html + href: articles/web_only_v0/v4_overlap.html + - text: Gene usage - href: articles/web_only/v5_gene_usage.html + href: articles/web_only_v0/v5_gene_usage.html + - text: Diversity estimation - href: articles/web_only/v6_diversity.html + href: articles/web_only_v0/v6_diversity.html + - text: '---' + - text: Clonotype-level exploration and comparison + - text: Track clonotypes across samples and time - href: articles/web_only/v8_tracking.html + href: articles/web_only_v0/v8_tracking.html + - text: Annotate clonotypes using immune receptor databases - href: articles/web_only/v11_db.html + href: articles/web_only_v0/v11_db.html + - text: Kmer and sequence motif analysis and visualisation - href: articles/web_only/v9_kmers.html + href: articles/web_only_v0/v9_kmers.html + - text: '---' + - text: Preparing to publication + - text: Make your plots publication-ready with fixVis - href: articles/web_only/v7_fixvis.html + href: articles/web_only_v0/v7_fixvis.html + - text: '---' + - text: BCR analysis + - text: BCR pipeline - href: articles/web_only/BCRpipeline.html + href: articles/web_only_v0/BCRpipeline.html + - text: Clustering - href: articles/web_only/clustering.html - twitter: - icon: fa-lg fa-twitter - href: http://twitter.com/immunomind - im_link: - text: ImmunoMind - href: https://immunomind.io + href: articles/web_only_v0/clustering.html github: icon: fa-github href: https://github.com/immunomind/immunarch reference: -- title: Bulk and single-cell data -- subtitle: Loading and saving any data - contents: - - has_concept("io") -- subtitle: Filtering data - contents: - - has_concept("filters") -- subtitle: Single-cell - desc: More coming soon! - contents: - - has_concept("single_cell") -- subtitle: Preprocessing - contents: - - has_concept("preprocessing") -- title: BCR data -- subtitle: Clustering - contents: - - has_concept("distance") - - has_concept("seq_cluster") -- subtitle: BCR pipeline - contents: - - has_concept("germline") - - has_concept("align_lineage") - - has_concept("phylip") - - has_concept("somatic_hypermutation") -- title: Basic immune repertoire statistics -- subtitle: Exploratory data analysis - contents: - - has_concept("explore") -- subtitle: Clonality analysis - contents: - - has_concept("clonality") -- title: Clonotype annotation and dynamics -- subtitle: Clonotype annotation - desc: Annotate clonotypes in immune repertoires using external immune receptor databases (VDJDB, McPAS and PIRD). - contents: - - has_concept("annotation") -- subtitle: Immune repertoire dynamics - desc: Track the differences in clonotype abundances over time. - contents: - - has_concept("dynamics") -- title: Compare repertoires -- subtitle: Repertoire diversity analysis - contents: - - has_concept("diversity") -- subtitle: Gene usage - desc: V-gene and J-gene usage statistics, analysis and visualisations - contents: - - has_concept("gene_usage") -- subtitle: Overlap - contents: - - starts_with("repOverlap") - - has_concept("overlap") -- subtitle: Public repertoire - contents: - - has_concept("pubrep") -- title: Advanced immune repertoire analysis -- subtitle: Kmers analysis - contents: - - has_concept("k-mers") -- subtitle: Post-analysis - desc: Advanced methods for post-analysis of gene usage, overlap and other statistics. - contents: - - has_concept("post_analysis") -- title: Visualisations -- subtitle: General visualisation functions - desc: Functions for visualisations of different data types. For analysis-specific visualisation see related sections. - contents: - - starts_with("vis") - - has_concept("vis") -- subtitle: Publication-ready plots - contents: - - has_concept("fixvis") -- title: Utilities -- subtitle: Data - contents: +- title: Stable, v1.0 +- subtitle: ... work in progress ... + +- contents: + - has_lifecycle("stable") + +- title: Experimental, v1.0 + +- subtitle: Repertoire descriptive statistics +- contents: + - starts_with("airr_stats") + +- subtitle: Clonality +- contents: + - starts_with("airr_clonality") + +- subtitle: Diversity +- contents: + - starts_with("airr_diversity") + +- subtitle: Public indices +- contents: + - starts_with("airr_public") + +- subtitle: Technical +- contents: + - has_lifecycle("experimental") - has_concept("data") -- subtitle: Public utility utilities - contents: - - has_concept("utility_public") -- subtitle: Internal utility functions - contents: + - has_concept("migration_utility") + - -starts_with("airr_stats") + - -starts_with("airr_clonality") + - -starts_with("airr_diversity") + - -starts_with("airr_public") + +- title: Under Question, v0.9 -> v1.0 + +- contents: - has_concept("utility_private") + - has_concept("utility_public") + - has_concept("preprocessing") + +- title: Deprecated, v0.9 + +- contents: + - has_lifecycle("deprecated") diff --git a/immunr.Rproj b/immunr.Rproj index bc9a80da..533e5cdf 100644 --- a/immunr.Rproj +++ b/immunr.Rproj @@ -1,4 +1,5 @@ Version: 1.0 +ProjectId: da9e8f01-a5c3-4f70-bcaf-16f0a2db91d0 RestoreWorkspace: Default SaveWorkspace: Default diff --git a/man/aa_properties.Rd b/man/aa_properties.Rd index 9f4a4068..8386bc3e 100644 --- a/man/aa_properties.Rd +++ b/man/aa_properties.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data_docs.R +% Please edit documentation in R/v0_data_docs.R \docType{data} \name{aa_properties} \alias{aa_properties} diff --git a/man/aa_table.Rd b/man/aa_table.Rd index f57d6781..f5a0b57b 100644 --- a/man/aa_table.Rd +++ b/man/aa_table.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data_docs.R +% Please edit documentation in R/v0_data_docs.R \docType{data} \name{aa_table} \alias{aa_table} diff --git a/man/add_class.Rd b/man/add_class.Rd index b2940057..f20a1087 100644 --- a/man/add_class.Rd +++ b/man/add_class.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{add_class} \alias{add_class} \title{Add a new class attribute} diff --git a/man/airr_clonality.Rd b/man/airr_clonality.Rd new file mode 100644 index 00000000..4ee7aa34 --- /dev/null +++ b/man/airr_clonality.Rd @@ -0,0 +1,131 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/v1_airr_clonality.R +\name{airr_clonality} +\alias{airr_clonality} +\alias{airr_clonality_line} +\alias{airr_clonality_rank} +\alias{airr_clonality_prop} +\title{Clonality - receptor overabundance statistics for immune repertoires} +\usage{ +airr_clonality_line( + idata, + limit = 1e+05, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_clonality_rank( + idata, + bins = c(10, 30, 100, 300, 1000, 10000, 1e+05), + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_clonality_prop( + idata, + bins = c(Hyperexpanded = 0.01, Large = 0.001, Medium = 1e-04, Small = 1e-05, Rare = + 1e-06), + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) +} +\arguments{ +\item{idata}{An \code{ImmunData} object.} + +\item{limit}{Positive integer >= 10: maximum number of top receptors to keep +\strong{per repertoire} (default \code{100000}).} + +\item{autojoin}{Logical. If TRUE, join repertoire metadata by the schema repertoire id. +Change the default behaviour by calling \code{options(immunarch.autojoin = FALSE)}.} + +\item{format}{String. One of \code{"long"} ("long" tibble with \code{imd_repertoire_id}, facet +columns, and \code{value}; useful for visualizations) or \code{"wide"} (wide/unmelted table of features, +with each row corresponding to a specific repertoire / pair of repertoires; useful for Machine Learning).} + +\item{bins}{A \strong{named} numeric vector of thresholds (e.g., +\code{c(Hyperexpanded = 1e-2, Large = 1e-3, ...)}). Names become bin labels and +must be non-empty. Internally sorted in descending order.} +} +\value{ +\subsection{\code{airr_clonality_line}}{ + +A tibble with columns: +\itemize{ +\item \code{repertoire_id} - repertoire identifier +\item \code{index} - rank within repertoire (1 = most abundant) +\item \code{count} - receptor count used for ranking +\item plus any repertoire metadata columns carried from \code{idata$repertoires} +} +} + +\subsection{\code{airr_clonality_rank}}{ + +A tibble with +\itemize{ +\item \code{repertoire_id} +\item \code{clonal_rank_bin} - the rank threshold (e.g., \code{10}, \code{100}, ...) +\item \code{occupied_prop} - sum of \code{proportion} within the bin +\item plus repertoire metadata columns from \code{idata$repertoires} +} +} + +\subsection{\code{airr_clonality_prop}}{ + +A tibble with +\itemize{ +\item \code{repertoire_id} +\item \code{clonal_prop_bin} - factor-like label from \code{names(bins)} or \code{"Ultra-rare"} +\item \code{occupied_prop} - sum of \code{proportion} within the bin +\item plus repertoire metadata columns from \code{idata$repertoires} +} +} +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} + +A family of functions to quantify \strong{receptor overabundance} per repertoire. Helps in deciphering the structure and partition the repertoire. +\subsection{Available functions}{ + +Supported methods are the following. +} + +\code{airr_clonality_line} - build ranked abundance lines: for each +repertoire, take the top \code{limit} receptors by \code{count} and attach repertoire +metadata. Useful for per-repertoire rank-abundance plots. + +\code{airr_clonality_rank} - aggregate clonal space by \strong{rank bins}. +Receptors are ordered by \code{proportion} within each repertoire; each receptor +is assigned to the smallest threshold in \code{bins} that contains its rank. + +\code{airr_clonality_prop} - aggregate clonal space by \strong{proportion bins}. +Each receptor is assigned to a named bin according to its \code{proportion} +(e.g., \code{Hyperexpanded >= 1e-2}, \code{Large >= 1e-3}, ...). Thresholds are matched in +descending order; unmatched receptors fall into \code{"Ultra-rare"}. +} +\examples{ +# Load data +immdata <- get_test_idata() |> agg_repertoires("Therapy") + +# +# airr_clonality_line +# +top_line <- airr_clonality_line(immdata, limit = 1000) + +# +# airr_clonality_rank +# +rank_stat <- airr_clonality_rank(immdata, bins = c(10, 100)) + +# +# airr_clonality_prop +# +prop_stat <- airr_clonality_prop(immdata) + +} +\seealso{ +\itemize{ +\item Per-repertoire summaries: \link{annotate_clonality} +\item Data container: \link[immundata:ImmunData]{immundata::ImmunData} +} +} +\concept{Clonality} diff --git a/man/airr_diversity.Rd b/man/airr_diversity.Rd new file mode 100644 index 00000000..f6e7b710 --- /dev/null +++ b/man/airr_diversity.Rd @@ -0,0 +1,207 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/v1_airr_diversity.R +\name{airr_diversity} +\alias{airr_diversity} +\alias{airr_diversity_dxx} +\alias{airr_diversity_chao1} +\alias{airr_diversity_shannon} +\alias{airr_diversity_pielou} +\alias{airr_diversity_index} +\alias{airr_diversity_hill} +\title{Diversity - estimating the heterogeneity of immune repertoires} +\usage{ +airr_diversity_dxx( + idata, + perc = 50, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_diversity_chao1( + idata, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_diversity_shannon( + idata, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_diversity_pielou( + idata, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_diversity_index( + idata, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_diversity_hill( + idata, + q = 0:5, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) +} +\arguments{ +\item{idata}{An \code{ImmunData} object.} + +\item{perc}{A number or numeric vector in \verb{(0, 100]} (default \code{50}), e.g. +\code{50} for D50, \code{20} for D20.} + +\item{autojoin}{Logical. If TRUE, join repertoire metadata by the schema repertoire id. +Change the default behaviour by calling \code{options(immunarch.autojoin = FALSE)}.} + +\item{format}{String. One of \code{"long"} ("long" tibble with \code{imd_repertoire_id}, facet +columns, and \code{value}; useful for visualizations) or \code{"wide"} (wide/unmelted table of features, +with each row corresponding to a specific repertoire / pair of repertoires; useful for Machine Learning).} + +\item{q}{A scalar or vector of non-negative orders. Defaults to \code{0:5}.} +} +\value{ +\subsection{\code{airr_diversity_dxx}}{ + +A tibble with: +\itemize{ +\item \code{imd_repertoire_id} +\item \code{perc} +\item \code{dxx} - minimal count of top receptors to reach \verb{perc\%} +\item plus repertoire metadata from \code{idata$repertoires} +} +} + +\subsection{\code{airr_diversity_chao1}}{ + +A tibble with: +\itemize{ +\item \code{imd_repertoire_id} +\item \code{Estimator} - number of species +\item \code{SD} - standard deviation for the estimator value +\item \code{Conf.95.lo} - CI 0.025 +\item \code{Conf.95.hi} - CI 0.975 +\item plus repertoire metadata from \code{idata$repertoires} +} +} + +\subsection{\code{airr_diversity_shannon}}{ + +A tibble with: +\itemize{ +\item \code{imd_repertoire_id} +\item \code{shannon} - entropy in bits +} +} + +\subsection{\code{airr_diversity_pielou}}{ + +A tibble with: +\itemize{ +\item \code{imd_repertoire_id} +\item \code{shannon} +\item \code{n_receptors} +\item \code{pielou} - evenness in \verb{[0, 1]} (NA if \code{S <= 1}) +} +} + +\subsection{\code{airr_diversity_index}}{ + +A tibble with: +\itemize{ +\item \code{imd_repertoire_id} +\item \code{q = 1} +\item \code{hill_number} +\item plus repertoire metadata from \code{idata$repertoires} +} +} + +\subsection{\code{airr_diversity_hill}}{ + +A tibble with: +\itemize{ +\item \code{imd_repertoire_id} +\item \code{q} - Hill order +\item \code{hill_number} - true diversity of order \code{q} +\item plus repertoire metadata from \code{idata$repertoires} +} +} +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} + +A family of functions to quantify \strong{receptor diversity} per repertoire. A characteristic of a whole repertoire. +\subsection{Available functions}{ + +Supported methods are the following. +} + +\code{airr_diversity_dxx} - \strong{coverage diversity}: minimal number of +top receptors needed to reach \verb{perc\%} of clonal space (by \code{proportion}). +Great for spotting dominance/overexpansion and for quick, interpretable dashboards +(e.g., D50 = receptors to cover half of the repertoire). + +\code{airr_diversity_chao1} - Chao1 estimator is a nonparameteric +asymptotic estimator of species richness (number of species in a population). +One of the most used methods for estimating immune repertoire diversity. + +\code{airr_diversity_shannon} - Shannon entropy (base 2) per repertoire +computed from \code{proportion}. Ideal when you want a single evenness-aware +diversity score; pair with Pielou/Hill for samples with very different richness. + +\code{airr_diversity_pielou} - Pielou's evenness \code{H / log2(S)} with +richness \code{S}. Best when you need a \strong{size-normalized} evenness score that's +comparable across repertoires with different receptor counts. + +\code{airr_diversity_index} - convenience alias for Hill number with +\code{q = 1} (\code{exp(Shannon)} using natural log). A solid \strong{default single metric} +that's relatively robust to rare-count noise and easy to compare across samples. + +\code{airr_diversity_hill} - Hill numbers ("true diversity") for +orders \verb{q \eqn{\in}{in} \{0, 1, 2, ...\}}: \code{q=0} richness, \code{q=1} exp(Shannon), \code{q>1} +emphasizes abundant receptors. Perfect when you want a \strong{diversity profile} +that tunes sensitivity to rare vs. abundant clonotypes. +} +\examples{ +# Load data +immdata <- get_test_idata() |> agg_repertoires("Therapy") + +# +# airr_diversity_dxx +# +d50 <- airr_diversity_dxx(immdata, perc = 50) +d_multi <- airr_diversity_dxx(immdata, perc = c(20, 50, 80)) + +# +# airr_diversity_chao1 +# +chao <- airr_diversity_chao1(immdata) + +# +# airr_diversity_shannon +# +sh <- airr_diversity_shannon(immdata) + +# +# airr_diversity_pielou +# +pj <- airr_diversity_pielou(immdata) + +# +# airr_diversity_index +# +idx <- airr_diversity_index(immdata) + +# +# airr_diversity_hill +# +hill <- airr_diversity_hill(immdata, q = c(0, 1, 2)) + +} +\seealso{ +\link[immundata:ImmunData]{immundata::ImmunData} +} +\concept{Diversity} diff --git a/man/airr_public.Rd b/man/airr_public.Rd new file mode 100644 index 00000000..f6cde9c2 --- /dev/null +++ b/man/airr_public.Rd @@ -0,0 +1,81 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/v1_airr_public.R +\name{airr_public} +\alias{airr_public} +\alias{airr_public_intersection} +\alias{airr_public_jaccard} +\title{Public indices - pairwise repertoire overlap} +\usage{ +airr_public_intersection( + idata, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_public_jaccard( + idata, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) +} +\arguments{ +\item{idata}{An \code{ImmunData} object.} + +\item{autojoin}{Logical. If TRUE, join repertoire metadata by the schema repertoire id. +Change the default behaviour by calling \code{options(immunarch.autojoin = FALSE)}.} + +\item{format}{String. One of \code{"long"} ("long" tibble with \code{imd_repertoire_id}, facet +columns, and \code{value}; useful for visualizations) or \code{"wide"} (wide/unmelted table of features, +with each row corresponding to a specific repertoire / pair of repertoires; useful for Machine Learning).} +} +\value{ +\subsection{\code{airr_public_intersection}}{ + +A \strong{symmetric numeric matrix} where rows/columns are \code{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. +} + +\subsection{\code{airr_public_jaccard}}{ + +A \strong{symmetric numeric matrix} where rows/columns are \code{repertoire_id} and each +cell is the Jaccard similarity in \verb{[0, 1]}. The diagonal is \code{1}. Row/column +names are repertoire IDs. +} +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} + +A family of functions to quantify \strong{public or shared receptors} between repertoire. +\subsection{Available functions}{ + +Supported methods are the following. +} + +\code{airr_public_intersection} - number of \strong{shared receptors} between +each pair of repertoires (intersection size). Handy for quick overlap heatmaps, +QC of replicate similarity, or spotting donor-shared "public" clonotypes. + +\code{airr_public_jaccard} - \strong{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. +} +\examples{ +# Load data +immdata <- get_test_idata() |> agg_repertoires("Therapy") + +# +# airr_public_intersection +# +m_pub <- airr_public_intersection(immdata) + +# +# airr_public_jaccard +# +m_jac <- airr_public_jaccard(immdata) + +} +\seealso{ +\link[immundata:ImmunData]{immundata::ImmunData} +} +\concept{Public indices} diff --git a/man/airr_stats.Rd b/man/airr_stats.Rd new file mode 100644 index 00000000..b3bba5b1 --- /dev/null +++ b/man/airr_stats.Rd @@ -0,0 +1,153 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/v1_airr_stats.R +\name{airr_stats} +\alias{airr_stats} +\alias{airr_stats_chains} +\alias{airr_stats_lengths} +\alias{airr_stats_genes} +\title{Compute key immune repertoire statistics} +\usage{ +airr_stats_chains( + idata, + locus_col = NA, + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_stats_lengths( + idata, + seq_col = "cdr3_aa", + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +airr_stats_genes( + idata, + gene_col = "v_call", + level = c("receptor", "barcode"), + by = c(NA, "locus"), + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) +} +\arguments{ +\item{idata}{An \code{ImmunData} object.} + +\item{locus_col}{Column in \code{idata$annotations} that stores the locus (e.g. +\code{"locus"}). If \code{NULL} or missing, the result is not split by locus.} + +\item{autojoin}{Logical. If TRUE, join repertoire metadata by the schema repertoire id. +Change the default behaviour by calling \code{options(immunarch.autojoin = FALSE)}.} + +\item{format}{String. One of \code{"long"} ("long" tibble with \code{imd_repertoire_id}, facet +columns, and \code{value}; useful for visualizations) or \code{"wide"} (wide/unmelted table of features, +with each row corresponding to a specific repertoire / pair of repertoires; useful for Machine Learning).} + +\item{seq_col}{Character vector with names of the columns containing +sequences.} + +\item{gene_col}{A single column name in \code{idata$annotations} with gene segment +calls (e.g., \code{"v_call"}, \code{"d_call"}, \code{"j_call"}, \code{"c_call"}). Default is +\code{"v_call"}.} + +\item{level}{One of \code{"receptor"} or \code{"barcode"}. If \code{"receptor"} (default), +the function counts \strong{unique receptors} (one per receptor ID) that carry a +given gene segment. If \code{"barcode"}, the function \strong{sums counts} (e.g., +cells/UMIs) per gene segment using the column defined by +\code{immundata::imd_schema("count")}.} + +\item{by}{Either \code{NULL} (no split) or \code{"locus"}. When \code{"locus"}, the result +is further split by the locus column if present (as given by +\code{immundata::imd_schema("locus")}); otherwise a warning is emitted and the +split is ignored.} +} +\value{ +\subsection{\code{airr_stats_chains} Returns a tibble with columns:}{ +\itemize{ +\item \code{repertoire_id} -- repertoire identifier +\item \code{locus} -- TRA, TRB, IGH, ... (present only if \code{locus_col} is supplied) +\item \code{n_chains} -- number of chains +} +} + +\subsection{\code{airr_stats_lengths} Returns a tibble with columns:}{ +\itemize{ +\item \code{repertoire_id} -- repertoire identifier +\item \code{seq_len} -- lengths of sequences +\item \code{n} -- number of receptors +} +} + +\subsection{\code{airr_stats_genes} A tibble with columns:}{ +\itemize{ +\item \code{repertoire_id} - repertoire identifier +\item \emph{(optional)} \code{locus} - TRA, TRB, IGH, ... (present only when \code{by = "locus"} +and the locus column exists) +\item \verb{} - the gene segment value (e.g., V gene) +\item \code{n} - the measure: +\itemize{ +\item if \code{level = "receptor"}: number of receptors carrying the gene segment +\item if \code{level = "barcode"}: sum of counts across receptors for the segment +} +} +} +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} + +A family of functions that extract \strong{core descriptive statistics} from an \code{ImmunData} object. +\subsection{Available functions}{ + +Supported methods are the following. +} + +\code{airr_stats_chains} --- count V(D)J \emph{chains} per repertoire +(optionally split by locus). Quickly gauges capture depth per repertoire +and, when split by locus, reveals TRA/TRB/IGH balance. Use it for QC, +library-size checks, and to spot locus-specific dropouts or +over-representation. + +\code{airr_stats_lengths} --- count the number of sequence lengths +per repertoire. Summarizes the CDR3 length distribution, a sensitive QC +fingerprint of repertoire prep and selection. Helpful for detecting +primer/UMI biases, comparing cohorts, and deriving length-based features for +models. + +\code{airr_stats_genes} - count V(D)J gene segments per repertoire, +optionally split by locus and using either receptor counts or barcode/UMI +counts as the measure. Profiles V/D/J gene usage to characterize repertoire +composition and germline biases, with optional locus split. Useful for +cohort comparisons, flagging clonal expansions, and producing ML-ready +features for repertoire-level ML tasks. +} +\examples{ +# Load data +immdata <- get_test_idata() |> agg_repertoires("Therapy") + +# +# airr_stats_chains +# +airr_stats_chains(immdata) + +# +# airr_stats_lengths +# +airr_stats_lengths(immdata) + +# +# airr_stats_genes +# +# V gene usage by receptor count +airr_stats_genes(immdata, gene_col = "v_call", level = "receptor") + +# V gene usage by summed cell/UMI counts (if a count column is present) +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{ +\link[immundata:ImmunData]{immundata::ImmunData} +} +\concept{Key AIRR statistics} diff --git a/man/annotate_clonality.Rd b/man/annotate_clonality.Rd new file mode 100644 index 00000000..be815b2c --- /dev/null +++ b/man/annotate_clonality.Rd @@ -0,0 +1,82 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/v1_annotate_clonality.R +\name{annotate_clonality} +\alias{annotate_clonality} +\alias{annotate_clonality_rank} +\alias{annotate_clonality_prop} +\title{Annotate clonality - per-receptor labels for overabundance} +\usage{ +annotate_clonality_rank( + idata, + bins = c(10, 30, 100, 300, 1000, 10000, 1e+05), + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) + +annotate_clonality_prop( + idata, + bins = c(Hyperexpanded = 0.01, Large = 0.001, Medium = 1e-04, Small = 1e-05, Rare = + 1e-06), + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) +} +\arguments{ +\item{idata}{An \link[immundata:ImmunData]{immundata::ImmunData} object.} + +\item{bins}{A \strong{named} numeric vector of thresholds (e.g., +\code{c(Hyperexpanded = 1e-2, Large = 1e-3, ...)}). Names become bin labels and +must be non-empty. Internally sorted in descending order.} + +\item{autojoin}{Logical. If TRUE, join repertoire metadata by the schema repertoire id. +Change the default behaviour by calling \code{options(immunarch.autojoin = FALSE)}.} + +\item{format}{String. One of \code{"long"} ("long" tibble with \code{imd_repertoire_id}, facet +columns, and \code{value}; useful for visualizations) or \code{"wide"} (wide/unmelted table of features, +with each row corresponding to a specific repertoire / pair of repertoires; useful for Machine Learning).} +} +\value{ +An \link[immundata:ImmunData]{immundata::ImmunData} whose \verb{$annotations} gains: +\itemize{ +\item \code{clonal_rank_bin} - integer-like label with the applied rank threshold +(outside all thresholds -> \code{NA}). +} + +An \link[immundata:ImmunData]{immundata::ImmunData} whose \verb{$annotations} gains: +\itemize{ +\item \code{clonal_prop_bin} - label from \code{names(bins)} or \code{"Ultra-rare"}. +} +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} + +A small family of helpers that \strong{add clonality labels to each receptor} in +an \link[immundata:ImmunData]{immundata::ImmunData} object. +\subsection{Available functions}{ +\itemize{ +\item \code{annotate_clonality_rank()} - label by \strong{rank bins} within each repertoire. +\item \code{annotate_clonality_prop()} - label by \strong{proportion bins} (named thresholds). +} +} + +\code{annotate_clonality_rank()} - for each repertoire, receptors are ordered by +within-repertoire abundance (proportion) and assigned a \strong{rank bin} label. + +\code{annotate_clonality_prop()} - label each receptor by \strong{proportion bin} +using named thresholds (matched in descending order; else \code{"Ultra-rare"}). +} +\examples{ +\dontrun{ +idata <- get_test_idata() |> agg_repertoires("Therapy") +idata_rank <- annotate_clonality_rank(idata) +idata_prop <- annotate_clonality_prop(idata) +} + +} +\seealso{ +\itemize{ +\item Per-repertoire summaries: \link{airr_clonality} +\item Data container: \link[immundata:ImmunData]{immundata::ImmunData} +} +} +\concept{Clonality} diff --git a/man/apply_symm.Rd b/man/apply_symm.Rd index ab351614..df35a2b1 100644 --- a/man/apply_symm.Rd +++ b/man/apply_symm.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{apply_symm} \alias{apply_symm} \alias{apply_asymm} @@ -21,7 +21,7 @@ apply_asymm(.datalist, .fun, ..., .diag = NA, .verbose = TRUE) \item{.verbose}{if TRUE then output a progress bar.} } \value{ -Matrix with values M[i,j] = fun(datalist[i], datalist[j]) +Matrix with values M(i,j) = fun(datalist(i), datalist(j)) } \description{ Apply the given function to every pair in the given datalist. Function either diff --git a/man/bcrdata.Rd b/man/bcrdata.Rd index 5af8aee0..68b6f6a5 100644 --- a/man/bcrdata.Rd +++ b/man/bcrdata.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data_docs.R +% Please edit documentation in R/v0_data_docs.R \docType{data} \name{bcrdata} \alias{bcrdata} @@ -9,9 +9,9 @@ A list of two elements. The first element ("data") is a list of 1 element named that contains immune repertoire data frame. The second element ("meta") is empty metadata table. \describe{ - \item{data}{List of immune repertoire data frames.} - \item{meta}{Metadata} - ... +\item{data}{List of immune repertoire data frames.} +\item{meta}{Metadata} +... } } \usage{ diff --git a/man/bunch_translate.Rd b/man/bunch_translate.Rd index 29acfaf9..e843611e 100644 --- a/man/bunch_translate.Rd +++ b/man/bunch_translate.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{bunch_translate} \alias{bunch_translate} \alias{translate_bunch} diff --git a/man/check_distribution.Rd b/man/check_distribution.Rd index 7b206647..656d7395 100644 --- a/man/check_distribution.Rd +++ b/man/check_distribution.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{check_distribution} \alias{check_distribution} \title{Check and normalise distributions} diff --git a/man/coding.Rd b/man/coding.Rd index 0283251d..1239913f 100644 --- a/man/coding.Rd +++ b/man/coding.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocessing.R +% Please edit documentation in R/v0_preprocessing.R \name{coding} \alias{coding} \alias{noncoding} @@ -17,13 +17,13 @@ outofframes(.data) } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, Apache Spark DataFrame from "copy_to" or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -34,13 +34,13 @@ Filtered data frame. \description{ Filter out clonotypes with non-coding, coding, in-frame or out-of-frame CDR3 sequences: -`coding()` - remove all non-coding sequences (i.e., remove all sequences with stop codons and frame shifts); +\code{coding()} - remove all non-coding sequences (i.e., remove all sequences with stop codons and frame shifts); -`noncoding()` - remove all coding sequences (i.e., leave sequences with stop codons and frame shifts only); +\code{noncoding()} - remove all coding sequences (i.e., leave sequences with stop codons and frame shifts only); -`inframes()` - remove all out-of-frame sequences (i.e., remove all sequences with frame shifts); +\code{inframes()} - remove all out-of-frame sequences (i.e., remove all sequences with frame shifts); -`outofframes()` - remove all in-frame sequences (i.e., leave sequences with frame shifts only). +\code{outofframes()} - remove all in-frame sequences (i.e., leave sequences with frame shifts only). Note: the function will remove all clonotypes sequences with NAs in the CDR3 amino acid column. } diff --git a/man/dbAnnotate.Rd b/man/dbAnnotate.Rd index 4e4e2979..21407d3d 100644 --- a/man/dbAnnotate.Rd +++ b/man/dbAnnotate.Rd @@ -1,39 +1,41 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/annotation.R +% Please edit documentation in R/v0_annotation.R \name{dbAnnotate} \alias{dbAnnotate} -\title{Annotate clonotypes in immune repertoires using clonotype databases such as VDJDB and MCPAS} +\title{Annotate clonotypes in immune repertoires using clonotype databases (e.g., VDJDB, McPAS)} \usage{ dbAnnotate(.data, .db, .data.col, .db.col) } \arguments{ \item{.data}{The data to process. It can be a \link{data.frame}, a -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} \item{.db}{A data frame or a data table with an immune receptor database. See \link{dbLoad} on how to load databases into R.} -\item{.data.col}{Character vector. Vector of columns in the input repertoires to use for clonotype search. E.g., `"CDR3.aa"` or `c("CDR3.aa", "V.name")`.} +\item{.data.col}{Character vector. Vector of columns in the input repertoires to use for clonotype search. E.g., \code{"CDR3.aa"} or \code{c("CDR3.aa", "V.name")}.} \item{.db.col}{Character vector. Vector of columns in the database to use for clonotype search. The order must match the order of ".data.col". -E.g., if ".data.col" is `c("CDR3.aa", "V.name")`, then ".db.col" must have the exact order of columns. i.e., the first column must correspond +E.g., if ".data.col" is \code{c("CDR3.aa", "V.name")}, then ".db.col" must have the exact order of columns. i.e., the first column must correspond to CDR3 amino acid sequences, and the second column must correspond to V gene segment names.} } \value{ Data frame with input sequences and counts or proportions for each of the input repertoire. } \description{ -Annotate clonotypes using immune receptor databases with known condition-associated receptors. -Before using this function, you need to download database files first. -For more details see the tutorial \url{https://immunarch.com/articles/web_only/v11_db.html}. +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +Annotate clonotypes by matching them to known condition-associated immune receptors in a database. +Before using this function, you must download or load the relevant database files. +For more information, see the \href{https://immunarch.com/articles/web_only/v11_db.html}{online tutorial}. } \examples{ data(immdata) diff --git a/man/dbLoad.Rd b/man/dbLoad.Rd index 68dfda69..f3c5f988 100644 --- a/man/dbLoad.Rd +++ b/man/dbLoad.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/annotation.R +% Please edit documentation in R/v0_annotation.R \name{dbLoad} \alias{dbLoad} \title{Load clonotype databases such as VDJDB and McPAS into the R workspace} @@ -28,6 +28,8 @@ Pass NA (by default) to load all available conditions.} Data frame with the input database records. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + The function automatically detects the database format and loads it into R. Additionally, the function provides a general query interface to databases that allows filtering by species, chain types (i.e., locus) and pathology (i.e., antigen species). @@ -36,7 +38,7 @@ Currently we support three popular databases: VDJDB - \url{https://github.com/antigenomics/vdjdb-db} -McPAS-TCR - \url{http://friedmanlab.weizmann.ac.il/McPAS-TCR/} +McPAS-TCR - \url{https://friedmanlab.weizmann.ac.il/McPAS-TCR/} TBAdb from PIRD - \url{https://db.cngb.org/pird/} } diff --git a/man/dot-quant_column_choice.Rd b/man/dot-quant_column_choice.Rd index 5831881b..db8b9382 100644 --- a/man/dot-quant_column_choice.Rd +++ b/man/dot-quant_column_choice.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{.quant_column_choice} \alias{.quant_column_choice} \title{Get a column's name using the input alias} diff --git a/man/entropy.Rd b/man/entropy.Rd index 35ee98c2..8d750c30 100644 --- a/man/entropy.Rd +++ b/man/entropy.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/info_theory.R +% Please edit documentation in R/v0_info_theory.R \name{entropy} \alias{entropy} \alias{kl_div} @@ -37,6 +37,8 @@ cross_entropy(.alpha, .beta, .base = 2, .do.norm = NA, A numeric value. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Compute information-based estimates and distances. } \examples{ diff --git a/man/figures/lifecycle-deprecated.svg b/man/figures/lifecycle-deprecated.svg new file mode 100644 index 00000000..b61c57c3 --- /dev/null +++ b/man/figures/lifecycle-deprecated.svg @@ -0,0 +1,21 @@ + + lifecycle: deprecated + + + + + + + + + + + + + + + lifecycle + + deprecated + + diff --git a/man/figures/lifecycle-experimental.svg b/man/figures/lifecycle-experimental.svg new file mode 100644 index 00000000..5d88fc2c --- /dev/null +++ b/man/figures/lifecycle-experimental.svg @@ -0,0 +1,21 @@ + + lifecycle: experimental + + + + + + + + + + + + + + + lifecycle + + experimental + + diff --git a/man/figures/lifecycle-stable.svg b/man/figures/lifecycle-stable.svg new file mode 100644 index 00000000..9bf21e76 --- /dev/null +++ b/man/figures/lifecycle-stable.svg @@ -0,0 +1,29 @@ + + lifecycle: stable + + + + + + + + + + + + + + + + lifecycle + + + + stable + + + diff --git a/man/figures/lifecycle-superseded.svg b/man/figures/lifecycle-superseded.svg new file mode 100644 index 00000000..db8d757f --- /dev/null +++ b/man/figures/lifecycle-superseded.svg @@ -0,0 +1,21 @@ + + lifecycle: superseded + + + + + + + + + + + + + + + lifecycle + + superseded + + diff --git a/man/fixVis.Rd b/man/fixVis.Rd index 295cca89..03ff421d 100644 --- a/man/fixVis.Rd +++ b/man/fixVis.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/shiny.R +% Please edit documentation in R/v0_shiny.R \name{fixVis} \alias{fixVis} \title{Manipulate ggplot plots and create publication-ready plots} @@ -13,6 +13,8 @@ fixVis(.plot = NA) No return value because it is an application. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + The \code{fixVis} is a built-in software tool for the manipulation of plots, such as adjusting title text font and size, axes, and more. It is a powerful tool designed to produce publication-ready plots with minimal amount of coding. diff --git a/man/geneUsage.Rd b/man/geneUsage.Rd index f83ff5f4..fd019ce9 100644 --- a/man/geneUsage.Rd +++ b/man/geneUsage.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/gene_usage.R +% Please edit documentation in R/v0_gene_usage.R \name{geneUsage} \alias{geneUsage} \alias{get_aliases} @@ -17,13 +17,13 @@ geneUsage( } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections,or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -38,12 +38,10 @@ Pass NA if you want to compute gene statistics at the clonotype level without re Pass "count" to use the "Clones" column to weight genes by abundance of their corresponding clonotypes.} \item{.ambig}{An option to handle ambiguous gene assigments, e.g., "TRAV1,TRAV2". - - -- Pass "inc" to include all possible gene segments, so "TRAV1,TRAV2" is counted as a different gene segment. - -- Pass "exc" to exclude all ambiguous gene assignments, so "TRAV1,TRAV2" is excluded from the resultant gene table. - +\itemize{ +\item Pass "inc" to include all possible gene segments, so "TRAV1,TRAV2" is counted as a different gene segment. +\item Pass "exc" to exclude all ambiguous gene assignments, so "TRAV1,TRAV2" is excluded from the resultant gene table. +} We recommend to turn it on by passing "inc" (turned on by default). You can exclude data for the cases where @@ -58,6 +56,8 @@ or pick only first from the set. Set it to "exc", "inc" or "maj", respectively.} A data frame with rows corresponding to gene segments and columns corresponding to the input samples. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + An utility function to analyse the immune receptor gene usage (IGHD, IGHJ, IDHV, IGIJ, IGKJ, IGKV, IGLJ, IGLV, TRAJ, TRAV, TRBD, etc.) and statistics. For gene details run \code{gene_stats()}. diff --git a/man/geneUsageAnalysis.Rd b/man/geneUsageAnalysis.Rd index 64dd023a..a1e19cb6 100644 --- a/man/geneUsageAnalysis.Rd +++ b/man/geneUsageAnalysis.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/gene_usage_analysis.R +% Please edit documentation in R/v0_gene_usage_analysis.R \name{geneUsageAnalysis} \alias{geneUsageAnalysis} \title{Post-analysis of V-gene and J-gene statistics: PCA, clustering, etc.} @@ -20,8 +20,8 @@ geneUsageAnalysis( ) } \arguments{ -\item{.data}{The \code{\link{geneUsageAnalysis}} function runs on the output from -\code{\link{geneUsage}}.} +\item{.data}{The \code{\link[=geneUsageAnalysis]{geneUsageAnalysis()}} function runs on the output from +\code{\link[=geneUsage]{geneUsage()}}.} \item{.method}{A string that defines the type of analysis to perform. Can be "pca", "mds", "js", "kmeans", "hclust", "dbscan" or "cor" if you want to calculate @@ -44,20 +44,22 @@ smoothing.} \item{.verbose}{A logical value.} -\item{.k}{The number of clusters to create, passed as \code{k} to \link[factoextra]{hcut} or as \code{centers} to \link{kmeans}.} +\item{.k}{The number of clusters to create, passed as \code{k} to \link[factoextra:hcut]{hcut} or as \code{centers} to \link{kmeans}.} \item{.eps}{A numerical value, DBscan epsylon parameter, see -\code{\link{immunr_dbscan}}.} +\code{\link[=immunr_dbscan]{immunr_dbscan()}}.} -\item{.perp}{A numerical value, t-SNE perplexity, see \code{\link{immunr_tsne}}.} +\item{.perp}{A numerical value, t-SNE perplexity, see \code{\link[=immunr_tsne]{immunr_tsne()}}.} -\item{.theta}{A numerical value, t-SNE theta parameter, see \code{\link{immunr_tsne}}.} +\item{.theta}{A numerical value, t-SNE theta parameter, see \code{\link[=immunr_tsne]{immunr_tsne()}}.} } \value{ Depends on the last element in the \code{.method} string. See \link{immunr_tsne} for more info. } \description{ -The \code{\link{geneUsageAnalysis}} function deploys several +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +The \code{\link[=geneUsageAnalysis]{geneUsageAnalysis()}} function deploys several data analysis methods, including PCA, multidimensional scaling, Jensen-Shannon divergence, k-means, hierarchical clustering, DBscan, and different correlation coefficients. diff --git a/man/gene_segments.Rd b/man/gene_segments.Rd index 7f9ef638..6e81d885 100644 --- a/man/gene_segments.Rd +++ b/man/gene_segments.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data_docs.R +% Please edit documentation in R/v0_data_docs.R \docType{data} \name{gene_segments} \alias{gene_segments} diff --git a/man/gene_stats.Rd b/man/gene_stats.Rd index 3fcb8876..1da224a6 100644 --- a/man/gene_stats.Rd +++ b/man/gene_stats.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/gene_usage.R +% Please edit documentation in R/v0_gene_usage.R \name{gene_stats} \alias{gene_stats} \title{WIP} @@ -16,4 +16,4 @@ WIP gene_stats() get_genes("hs.trbv", "segment") } -\concept{gene_usage} +\concept{data} diff --git a/man/getKmers.Rd b/man/getKmers.Rd index bfa423d8..f1b8c1c7 100644 --- a/man/getKmers.Rd +++ b/man/getKmers.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/kmers.R +% Please edit documentation in R/v0_kmers.R \name{getKmers} \alias{getKmers} \alias{get.kmers} @@ -10,13 +10,13 @@ getKmers(.data, .k, .col = c("aa", "nt"), .coding = TRUE) } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections,or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -32,7 +32,7 @@ pass "nt" for CDR3 nucleotide sequences.} Data frame with two columns (k-mers and their counts). } \description{ -Calculate the k-mer statistics of immune repertoires +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/get_immunarch_news.Rd b/man/get_immunarch_news.Rd new file mode 100644 index 00000000..e623626f --- /dev/null +++ b/man/get_immunarch_news.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/v1_migration_utils.R +\name{get_immunarch_news} +\alias{get_immunarch_news} +\title{Get the Latest immunarch Update} +\usage{ +get_immunarch_news(datepoint = "latest") +} +\arguments{ +\item{datepoint}{A string specifying the update date. Use \code{"latest"} for the most recent update +or supply a valid date key (e.g., \code{"Apr 2025"}).} +} +\value{ +A character string with the update details or a warning if the key is not found. +} +\description{ +Retrieves an update message for immunarch. +} +\details{ +If \code{datepoint} is set to \code{"latest"}, the function returns the most recent update. +Otherwise, specify the update date key (e.g., \code{"Apr 2025"}) to retrieve that particular update. +If no matching update is found, a warning is issued along with available update keys. +} +\seealso{ +\code{\link[=list_immunarch_news]{list_immunarch_news()}} +} +\concept{migration_utility} diff --git a/man/group_from_metadata.Rd b/man/group_from_metadata.Rd index e9bce0a7..eb720f0e 100644 --- a/man/group_from_metadata.Rd +++ b/man/group_from_metadata.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{group_from_metadata} \alias{group_from_metadata} \title{Get a character vector of samples' groups from the input metadata file} diff --git a/man/has_class.Rd b/man/has_class.Rd index 6d7a39db..1f42a004 100644 --- a/man/has_class.Rd +++ b/man/has_class.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{has_class} \alias{has_class} \title{Check for the specific class} diff --git a/man/im_common_args.Rd b/man/im_common_args.Rd new file mode 100644 index 00000000..247c712a --- /dev/null +++ b/man/im_common_args.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/aaa-registry.R +\name{im_common_args} +\alias{im_common_args} +\title{Common arguments for immundata helpers} +\usage{ +im_common_args( + autojoin = getOption("immundata.autojoin", TRUE), + format = c("long", "wide") +) +} +\arguments{ +\item{autojoin}{Logical. If TRUE, join repertoire metadata by the schema repertoire id. +Change the default behaviour by calling \code{options(immunarch.autojoin = FALSE)}.} + +\item{format}{String. One of \code{"long"} ("long" tibble with \code{imd_repertoire_id}, facet +columns, and \code{value}; useful for visualizations) or \code{"wide"} (wide/unmelted table of features, +with each row corresponding to a specific repertoire / pair of repertoires; useful for Machine Learning).} +} +\description{ +Common arguments for immundata helpers +} +\keyword{internal} diff --git a/man/immdata.Rd b/man/immdata.Rd index 2b401d71..4b659f8d 100644 --- a/man/immdata.Rd +++ b/man/immdata.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data_docs.R +% Please edit documentation in R/v0_data_docs.R \docType{data} \name{immdata} \alias{immdata} @@ -8,9 +8,9 @@ A list of two elements. The first element ("data") is a list with data frames with clonotype tables. The second element ("meta") is a metadata table. \describe{ - \item{data}{List of immune repertoire data frames.} - \item{meta}{Metadata} - ... +\item{data}{List of immune repertoire data frames.} +\item{meta}{Metadata} +... } } \usage{ diff --git a/man/immunarch_v1_updates.Rd b/man/immunarch_v1_updates.Rd new file mode 100644 index 00000000..be0ba856 --- /dev/null +++ b/man/immunarch_v1_updates.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/zzz.R +\docType{data} +\name{immunarch_v1_updates} +\alias{immunarch_v1_updates} +\title{Get a list of package updates} +\format{ +An object of class \code{list} of length 1. +} +\usage{ +immunarch_v1_updates +} +\description{ +Get a list of package updates +} +\concept{migration_utility} +\keyword{datasets} diff --git a/man/immunr_data_format.Rd b/man/immunr_data_format.Rd index e052e246..94d8f6fb 100644 --- a/man/immunr_data_format.Rd +++ b/man/immunr_data_format.Rd @@ -1,39 +1,27 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/immunr_data_format.R +% Please edit documentation in R/v0_immunr_data_format.R \docType{data} \name{immunr_data_format} \alias{immunr_data_format} \alias{immunarch_data_format} \title{Specification of the data format used by immunarch dataframes} \description{ -- "Clones" - number of barcodes (events, UMIs) or reads; - -- "Proportion" - proportion of barcodes (events, UMIs) or reads; - -- "CDR3.nt" - CDR3 nucleotide sequence; - -- "CDR3.aa" - CDR3 amino acid sequence; - -- "V.name" - names of aligned Variable gene segments; - -- "D.name" - names of aligned Diversity gene segments or NA; - -- "J.name" - names of aligned Joining gene segments; - -- "V.end" - last positions of aligned V gene segments (1-based); - -- "D.start" - positions of D'5 end of aligned D gene segments (1-based); - -- "D.end" - positions of D'3 end of aligned D gene segments (1-based); - -- "J.start" - first positions of aligned J gene segments (1-based); - -- "VJ.ins" - number of inserted nucleotides (N-nucleotides) at V-J junction (-1 for receptors with VDJ recombination); - -- "VD.ins" - number of inserted nucleotides (N-nucleotides) at V-D junction (-1 for receptors with VJ recombination); - -- "DJ.ins" - number of inserted nucleotides (N-nucleotides) at D-J junction (-1 for receptors with VJ recombination); - -- "Sequence" - full nucleotide sequence. +\itemize{ +\item "Clones" - number of barcodes (events, UMIs) or reads; +\item "Proportion" - proportion of barcodes (events, UMIs) or reads; +\item "CDR3.nt" - CDR3 nucleotide sequence; +\item "CDR3.aa" - CDR3 amino acid sequence; +\item "V.name" - names of aligned Variable gene segments; +\item "D.name" - names of aligned Diversity gene segments or NA; +\item "J.name" - names of aligned Joining gene segments; +\item "V.end" - last positions of aligned V gene segments (1-based); +\item "D.start" - positions of D'5 end of aligned D gene segments (1-based); +\item "D.end" - positions of D'3 end of aligned D gene segments (1-based); +\item "J.start" - first positions of aligned J gene segments (1-based); +\item "VJ.ins" - number of inserted nucleotides (N-nucleotides) at V-J junction (-1 for receptors with VDJ recombination); +\item "VD.ins" - number of inserted nucleotides (N-nucleotides) at V-D junction (-1 for receptors with VJ recombination); +\item "DJ.ins" - number of inserted nucleotides (N-nucleotides) at D-J junction (-1 for receptors with VJ recombination); +\item "Sequence" - full nucleotide sequence. +} } \concept{data} diff --git a/man/immunr_hclust.Rd b/man/immunr_hclust.Rd index 3b2f2617..c5dd80bc 100644 --- a/man/immunr_hclust.Rd +++ b/man/immunr_hclust.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/clustering.R +% Please edit documentation in R/v0_clustering.R \name{immunr_hclust} \alias{immunr_hclust} \alias{immunr_kmeans} @@ -16,39 +16,40 @@ immunr_dbscan(.data, .eps, .dist = TRUE) \arguments{ \item{.data}{Matrix or data frame with features, distance matrix or output from \link{repOverlapAnalysis} or \link{geneUsageAnalysis} functions.} -\item{.k}{The number of clusters to create, defined as \code{k} to \link[factoextra]{hcut} or as \code{centers} to \link{kmeans}.} +\item{.k}{The number of clusters to create, defined as \code{k} to \link[factoextra:hcut]{hcut} or as \code{centers} to \link{kmeans}.} -\item{.k.max}{Limits the maximum number of clusters. It is passed as \code{k.max} to \link{fviz_nbclust} for \code{immunr_hclust} and \code{immunr_kmeans}.} +\item{.k.max}{Limits the maximum number of clusters. It is passed as \code{k.max} to \link[factoextra:fviz_nbclust]{factoextra::fviz_nbclust} for \code{immunr_hclust} and \code{immunr_kmeans}.} -\item{.method}{Passed to \link[factoextra]{hcut} or as \link{fviz_nbclust}. +\item{.method}{Passed to \link[factoextra:hcut]{factoextra::hcut} or as \link[factoextra:fviz_nbclust]{factoextra::fviz_nbclust}. -In case of \link[factoextra]{hcut} the agglomeration method is going to be used (argument \code{hc_method}). +In case of \link[factoextra:hcut]{factoextra::hcut} the agglomeration method is going to be used (argument \code{hc_method}). -In case of \link{fviz_nbclust} it is the method to be used for estimating the optimal number of clusters (argument \code{method}).} +In case of \link[factoextra:fviz_nbclust]{factoextra::fviz_nbclust} it is the method to be used for estimating the optimal number of clusters (argument \code{method}).} \item{.dist}{If TRUE then ".data" is expected to be a distance matrix. If FALSE then the euclidean distance is computed for the input objects.} -\item{.eps}{Local radius for expanding clusters, minimal distance between points to expand clusters. Passed as \code{eps} to \link[fpc]{dbscan}.} +\item{.eps}{Local radius for expanding clusters, minimal distance between points to expand clusters. Passed as \code{eps} to \link[fpc:dbscan]{dbscan}.} } \value{ -\code{immunr_hclust} - list with two elements. The first element is an output from \link{hcut}. -The second element is an output from \link{fviz_nbclust} +\code{immunr_hclust} - list with two elements. The first element is an output from \link[factoextra:hcut]{factoextra::hcut}. +The second element is an output from \link[factoextra:fviz_nbclust]{factoextra::fviz_nbclust} \code{immunr_kmeans} - list with three elements. The first element is an output from \link{kmeans}. -The second element is an output from \link{fviz_nbclust}. +The second element is an output from \link[factoextra:fviz_nbclust]{factoextra::fviz_nbclust}. The third element is the input dataset \code{.data}. -\code{immunr_dbscan} - list with two elements. The first element is an output from \link{dbscan}. +\code{immunr_dbscan} - list with two elements. The first element is an output from \link[fpc:dbscan]{fpc::dbscan}. The second element is the input dataset \code{.data}. } \description{ -Clusters the data with one of the following methods: - -- \code{immunr_hclust} clusters the data using the hierarchical clustering from \link[factoextra]{hcut}; - -- \code{immunr_kmeans} clusters the data using the K-means algorithm from \link{kmeans}; +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} -- \code{immunr_dbscan} clusters the data using the DBSCAN algorithm from \link[fpc]{dbscan}. +Clusters the data with one of the following methods: +\itemize{ +\item \code{immunr_hclust} clusters the data using the hierarchical clustering from \link[factoextra:hcut]{hcut}; +\item \code{immunr_kmeans} clusters the data using the K-means algorithm from \link{kmeans}; +\item \code{immunr_dbscan} clusters the data using the DBSCAN algorithm from \link[fpc:dbscan]{dbscan}. +} } \examples{ data(immdata) diff --git a/man/immunr_pca.Rd b/man/immunr_pca.Rd index ecca8196..65124b91 100644 --- a/man/immunr_pca.Rd +++ b/man/immunr_pca.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/dimensions.R +% Please edit documentation in R/v0_dimensions.R \name{immunr_pca} \alias{immunr_pca} \alias{immunr_mds} @@ -26,29 +26,30 @@ if you want to visualise results.} \item{.dist}{If TRUE then assumes that ".data" is a distance matrix.} -\item{.perp}{The perplexity parameter for \link[Rtsne]{Rtsne}. Sepcifies the number -of neighbours each data point must have in the resulting plot.} +\item{.perp}{The perplexity parameter for Rtsne. Specifies the number +of neighbors each data point must have in the resulting plot.} -\item{...}{Other parameters passed to \link[Rtsne]{Rtsne}.} +\item{...}{Other parameters passed to Rtsne.} } \value{ \code{immunr_pca} - an output from \link{prcomp}. -\code{immunr_mds} - an output from \link{isoMDS}. +\code{immunr_mds} - an output from isoMDS. -\code{immunr_tsne} - an output from \link{Rtsne}. +\code{immunr_tsne} - an output from Rtsne. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Collects a set of principal variables, reducing the number of not important variables to analyse. Dimensionality reduction makes data analysis algorithms work faster and sometimes more accurate, since it also reduces noise in the data. Currently available methods are: - -- \code{immunr_pca} performs PCA (Principal Component Analysis) using \link{prcomp}; - -- \code{immunr_mds} performs MDS (Multi-Dimensional Scaling) using \link[MASS]{isoMDS}; - -- \code{immunr_tsne} performs tSNE (t-Distributed Stochastic Neighbour Embedding) using \link[Rtsne]{Rtsne}. +\itemize{ +\item \code{immunr_pca} performs PCA (Principal Component Analysis) using \link{prcomp}; +\item \code{immunr_mds} performs MDS (Multi-Dimensional Scaling) using isoMODS from MASS package. +\item \code{immunr_tsne} performs tSNE (t-Distributed Stochastic Neighbour Embedding) using Rtsne Rtsne package. +} } \examples{ data(immdata) diff --git a/man/inc_overlap.Rd b/man/inc_overlap.Rd index 64bea612..743ccaec 100644 --- a/man/inc_overlap.Rd +++ b/man/inc_overlap.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/overlap.R +% Please edit documentation in R/v0_overlap.R \name{inc_overlap} \alias{inc_overlap} \title{Incremental counting of repertoire similarity} @@ -17,13 +17,13 @@ inc_overlap( } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -52,6 +52,8 @@ top N clonotypes.} List with overlap matrices. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + For reference please look up https://www.pnas.org/content/111/16/5980 (Fig. 4). } \examples{ diff --git a/man/list_immunarch_news.Rd b/man/list_immunarch_news.Rd new file mode 100644 index 00000000..1c559391 --- /dev/null +++ b/man/list_immunarch_news.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/v1_migration_utils.R +\name{list_immunarch_news} +\alias{list_immunarch_news} +\title{List Available immunarch Updates} +\usage{ +list_immunarch_news() +} +\value{ +A character vector containing all the date keys for the available updates. +} +\description{ +Returns the list of available update keys for immunarch v1. +} +\seealso{ +\code{\link[=get_immunarch_news]{get_immunarch_news()}} +} +\concept{migration_utility} diff --git a/man/matrixdiagcopy.Rd b/man/matrixdiagcopy.Rd index 86568927..2661e85d 100644 --- a/man/matrixdiagcopy.Rd +++ b/man/matrixdiagcopy.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{matrixdiagcopy} \alias{matrixdiagcopy} \title{Copy the upper matrix triangle to the lower one} @@ -19,7 +19,7 @@ Copy the upper matrix triangle to the lower one mat <- matrix(0, 3, 3) mat -mat[1, 3] <- 1 +mat(1, 3) <- 1 mat <- immunarch:::matrixdiagcopy(mat) mat } diff --git a/man/pubRep.Rd b/man/pubRep.Rd index 49fd4df1..a5f83bb5 100644 --- a/man/pubRep.Rd +++ b/man/pubRep.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/public.R +% Please edit documentation in R/v0_public.R \name{pubRep} \alias{pubRep} \alias{publicRepertoire} @@ -17,13 +17,13 @@ pubRep( } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -49,15 +49,14 @@ in the public repertoire table. Set NA (by default) to have the maximal amount o } \value{ Data table with columns for: - -- Clonotypes (e.g., CDR3 sequence, or two columns for CDR3 sequence and V gene) - -- Incidence of clonotypes - -- Per-sample proportions or counts +\itemize{ +\item Clonotypes (e.g., CDR3 sequence, or two columns for CDR3 sequence and V gene) +\item Incidence of clonotypes +\item Per-sample proportions or counts +} } \description{ -Create a repertoire of public clonotypes +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ # Subset the data to make the example faster to run diff --git a/man/pubRepApply.Rd b/man/pubRepApply.Rd index 5cfe9d5c..5c8f8405 100644 --- a/man/pubRepApply.Rd +++ b/man/pubRepApply.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/public.R +% Please edit documentation in R/v0_public.R \name{pubRepApply} \alias{pubRepApply} \alias{publicRepertoireApply} @@ -13,14 +13,14 @@ pubRepApply(.pr1, .pr2, .fun = function(x) log10(x[1])/log10(x[2])) \item{.pr2}{Second public repertoire.} \item{.fun}{A function to apply to pairs of frequencies of same clonotypes from "pr1" and "pr2". -By default - \code{log(X) / log(Y)} where \code{X,Y} - frequencies of the same clonotype, +By default - \code{log(X) / log(Y)} where \verb{X,Y} - frequencies of the same clonotype, found in both public repertoires.} } \value{ Work in progress. } \description{ -Work In Progress +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/pubRepFilter.Rd b/man/pubRepFilter.Rd index d57ed369..b8191ca9 100644 --- a/man/pubRepFilter.Rd +++ b/man/pubRepFilter.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/public.R +% Please edit documentation in R/v0_public.R \name{pubRepFilter} \alias{pubRepFilter} \alias{publicRepertoireFilter} @@ -20,6 +20,8 @@ pubRepFilter(.pr, .meta, .by, .min.samples = 1) Data frame with filtered clonotypes. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Filter our clonotypes with low incidence in a specific group. } \examples{ diff --git a/man/pubRepStatistics.Rd b/man/pubRepStatistics.Rd index 4ce5aeb1..a93bd13d 100644 --- a/man/pubRepStatistics.Rd +++ b/man/pubRepStatistics.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/public.R +% Please edit documentation in R/v0_public.R \name{pubRepStatistics} \alias{pubRepStatistics} \title{Statistics of number of public clonotypes for each possible combinations of repertoires} @@ -17,7 +17,7 @@ pubRepStatistics(.data, .by = NA, .meta = NA) Data frame with incidence statistics per sample. } \description{ -Statistics of number of public clonotypes for each possible combinations of repertoires +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/public_matrix.Rd b/man/public_matrix.Rd index 07ea842d..539d4824 100644 --- a/man/public_matrix.Rd +++ b/man/public_matrix.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/public.R +% Please edit documentation in R/v0_public.R \name{public_matrix} \alias{public_matrix} \title{Get a matrix with public clonotype frequencies} @@ -13,7 +13,7 @@ public_matrix(.data) Matrix with per-sample clonotype counts / proportions only. } \description{ -Get a matrix with public clonotype frequencies +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/register_immunarch_method.Rd b/man/register_immunarch_method.Rd new file mode 100644 index 00000000..a76dc663 --- /dev/null +++ b/man/register_immunarch_method.Rd @@ -0,0 +1,88 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/aaa-registry.R +\name{register_immunarch_method} +\alias{register_immunarch_method} +\title{Register an Immunarch method (developer)} +\usage{ +register_immunarch_method( + core, + family, + name, + register_family = TRUE, + required_cols = NULL, + need_repertoires = TRUE +) +} +\arguments{ +\item{core}{A function with signature \verb{function(idata, ...)}. This is your core +implementation; it must accept an \code{ImmunData} as the first argument and \strong{must not} +declare \code{autojoin}, \code{format}, or \code{features}.} + +\item{family}{String. Method family name used for dispatch (e.g., \code{"airr_stats"}).} + +\item{name}{String. Method name within the family (e.g., \code{"lengths"}).} + +\item{register_family}{Logical (default \code{TRUE}). If \code{TRUE}, attempts to create/ensure +the family environment by calling \code{register_airr_family()} when available.} + +\item{required_cols}{Character vector of column names that \strong{must} be present in +\code{idata$annotations}. Use this to declare the minimal input schema your core needs.} + +\item{need_repertoires}{Logical. Use this to declare the necessity of having aggregated +repertoires.} +} +\value{ +A \strong{function} - the user-facing wrapper around \code{core}. Typical usage is to +assign it to the exported symbol of the method, e.g.: +\code{airr_stats_lengths <- register_immunarch_method(...)}. +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} +} +\details{ +Wrap a core implementation into a user-facing function and (optionally) +register it in the in-memory method registry. The wrapper \strong{adds common +arguments} and \strong{runs safety checks} so your core stays minimal. +\subsection{What your core must look like}{ +\itemize{ +\item Signature: \verb{function(idata, ...)} +\item \strong{Must not} declare \code{autojoin}, \code{format}, or \code{features} - these are added by the wrapper. +} +} + +\subsection{What the wrapper adds}{ +\itemize{ +\item Common args from \code{im_common_args()}: \code{autojoin}, \code{format}, \code{features} +(with \code{autojoin} default controlled by \code{getOption("immunarch.autojoin", FALSE)}). +\item Validates \code{idata} is an \link[immundata:ImmunData]{immundata::ImmunData} object. +\item Ensures all columns in \code{required_cols} exist in \code{idata$annotations}. +\item If \code{autojoin = TRUE} and the result is a data frame containing the repertoire id +column (\code{immundata::imd_schema("repertoire")}), joins repertoire metadata from +\code{idata$repertoires}. +} +} +} +\examples{ +\dontrun{ +# Minimal core implementation (must accept `idata`) +airr_stats_lengths_impl <- function(idata, seq_col = "cdr3_aa") { + dplyr::as_tibble(idata$annotations) |> + dplyr::distinct(.data[[immundata::imd_schema("repertoire")]], .data[[seq_col]]) |> + dplyr::mutate(seq_len = nchar(.data[[seq_col]])) |> + dplyr::count(.data[[immundata::imd_schema("repertoire")]], seq_len, name = "n") +} + +# Register and expose a user-facing function +airr_stats_lengths <- register_immunarch_method( + core = airr_stats_lengths_impl, + family = "airr_stats", + name = "lengths", + required_cols = c("cdr3_aa", immundata::imd_schema("repertoire")) +) + +# Optional: call via dispatcher +# make_airr_dispatcher("airr_stats")(idata = immdata, method = "lengths") +} + +} +\keyword{internal} diff --git a/man/repAlignLineage.Rd b/man/repAlignLineage.Rd index 577ab94a..ad565f41 100644 --- a/man/repAlignLineage.Rd +++ b/man/repAlignLineage.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/align_lineage.R +% Please edit documentation in R/v0_align_lineage.R \name{repAlignLineage} \alias{repAlignLineage} \title{Aligns all sequences incliding germline within each clonal lineage within each cluster} @@ -7,7 +7,7 @@ repAlignLineage(.data, .min_lineage_sequences, .prepare_threads, .align_threads, .nofail) } \arguments{ -\item{.data}{The data to be processed. Can be \link{data.frame}, \link{data.table} +\item{.data}{The data to be processed. Can be \link{data.frame}, \link[data.table:data.table]{data.table::data.table} or a list of these objects.} \item{.min_lineage_sequences}{If number of sequences in the same clonal lineage and the same @@ -29,17 +29,23 @@ Used to avoid raising errors in examples on computers where Clustal W is not ins \value{ Dataframe or list of dataframes (if input is a list with multiple samples). The dataframe has these columns: -* Cluster: cluster name -* Germline: germline sequence -* Alignment: DNAbin object with alignment -* Sequences: nested dataframe containing all sequences for this combination - of cluster and germline; it has columns - * Sequence, CDR1.nt, CDR2.nt, CDR3.nt, FR1.nt, FR2.nt, FR3.nt, FR4.nt, V.allele, J.allele, - V.aa, J.aa: all values taken from the input dataframe - * Clone.ID: taken from the input dataframe, or created (filled with row numbers) if missing - * Clones: taken from the input dataframe, or created (filled with '1' values) if missing +\itemize{ +\item Cluster: cluster name +\item Germline: germline sequence +\item Alignment: DNAbin object with alignment +\item Sequences: nested dataframe containing all sequences for this combination +of cluster and germline; it has columns +\itemize{ +\item Sequence, CDR1.nt, CDR2.nt, CDR3.nt, FR1.nt, FR2.nt, FR3.nt, FR4.nt, V.allele, J.allele, +V.aa, J.aa: all values taken from the input dataframe +\item Clone.ID: taken from the input dataframe, or created (filled with row numbers) if missing +\item Clones: taken from the input dataframe, or created (filled with '1' values) if missing +} +} } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + This function aligns all sequences (incliding germline) that belong to one clonal lineage and one cluster. After clustering and building the clonal lineage and germline, the next step is to analyze the degree of mutation and maturity of each clonal lineage. This allows for diff --git a/man/repClonalFamily.Rd b/man/repClonalFamily.Rd index 1f1adb78..64b3468c 100644 --- a/man/repClonalFamily.Rd +++ b/man/repClonalFamily.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/phylip.R +% Please edit documentation in R/v0_phylip.R \name{repClonalFamily} \alias{repClonalFamily} \title{Builds a phylogenetic tree using the sequences of a clonal lineage} @@ -25,21 +25,25 @@ Used to avoid raising errors in examples on computers where PHYLIP is not instal \value{ Dataframe or list of dataframes (if input is a list with multiple samples). The dataframe has these columns: -* Cluster: cluster name -* Germline.Input: germline sequence, like it was in the input; not aligned -* Germline.Output: germline sequence, parsed from PHYLIP dnapars function output; - it contains difference of germline from the common ancestor; "." characters mean - matching letters -* Common.Ancestor: common ancestor sequence, parsed from PHYLIP dnapars function output -* Trunk.Length: mean trunk length, representing the distance between the most recent - common ancestor and germline sequence as a measure of the maturity of a lineage -* Tree: output tree in "phylo" format, loaded from by PHYLIP dnapars function output -* TreeStats: nested dataframe containing data about tree nodes, needed for visualization -* Sequences: nested dataframe containing all sequences for this combination of cluster - and germline; it contains regions from original sequences, saved for - repSomaticHypermutation() calculation, and also data needed for visualizations +\itemize{ +\item Cluster: cluster name +\item Germline.Input: germline sequence, like it was in the input; not aligned +\item Germline.Output: germline sequence, parsed from PHYLIP dnapars function output; +it contains difference of germline from the common ancestor; "." characters mean +matching letters +\item Common.Ancestor: common ancestor sequence, parsed from PHYLIP dnapars function output +\item Trunk.Length: mean trunk length, representing the distance between the most recent +common ancestor and germline sequence as a measure of the maturity of a lineage +\item Tree: output tree in "phylo" format, loaded from by PHYLIP dnapars function output +\item TreeStats: nested dataframe containing data about tree nodes, needed for visualization +\item Sequences: nested dataframe containing all sequences for this combination of cluster +and germline; it contains regions from original sequences, saved for +repSomaticHypermutation() calculation, and also data needed for visualizations +} } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + This function uses the PHYLIP package to make phylogenetic analysis. For making trees it uses maximum parsimony methods. } diff --git a/man/repClonality.Rd b/man/repClonality.Rd index 11bbb29c..d537b8ce 100644 --- a/man/repClonality.Rd +++ b/man/repClonality.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/clonality.R +% Please edit documentation in R/v0_clonality.R \name{repClonality} \alias{repClonality} \alias{clonality} @@ -22,13 +22,13 @@ repClonality( } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -67,6 +67,8 @@ with clonality statistics. Otherwise, it returns a numeric matrix with clonality statistics for all input repertoires. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + \code{repClonality} function encompasses several methods to measure clonal proportions in a given repertoire. } diff --git a/man/repDiversity.Rd b/man/repDiversity.Rd index 1f72f601..c5835f6f 100644 --- a/man/repDiversity.Rd +++ b/man/repDiversity.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/diversity.R +% Please edit documentation in R/v0_diversity.R \name{repDiversity} \alias{repDiversity} \alias{chao1} @@ -30,13 +30,13 @@ repDiversity( } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -82,7 +82,7 @@ div, gini, gini.simp, inv.simp, raref return numeric vector of length 1 with value. chao1 returns 4 values: estimated number of species, standart deviation of -this number and two 95% confidence intervals for the species number. +this number and two 95\% confidence intervals for the species number. hill returns a vector of specified length \code{.max.q - .min.q} @@ -97,6 +97,8 @@ For rarefaction the function returns either a matrix with diversity estimatinos on different step of the simulaiton process or a list with such matrices. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + This is a utility function to estimate the diversity of species or objects in the given distribution. Note: functions will check if .data is a distribution of a random variable (sum == 1) or not. @@ -104,36 +106,30 @@ To force normalisation and / or to prevent this, set .do.norm to TRUE (do normal or FALSE (don't do normalisation), respectively. } \details{ -- True diversity, or the effective number of types, refers to the number +\itemize{ +\item True diversity, or the effective number of types, refers to the number of equally-abundant types needed for the average proportional abundance of the types to equal that observed in the dataset of interest where all types may not be equally abundant. - -- Inverse Simpson index is the effective number of types that is obtained when +\item Inverse Simpson index is the effective number of types that is obtained when the weighted arithmetic mean is used to quantify average proportional abundance of types in the dataset of interest. - -- The Gini coefficient measures the inequality among values +\item The Gini coefficient measures the inequality among values of a frequency distribution (for example levels of income). A Gini coefficient of zero expresses perfect equality, where all values are the same (for example, where everyone has the same income). A Gini coefficient of one (or 100 percents ) expresses maximal inequality among values (for example where only one person has all the income). - -- The Gini-Simpson index is the probability of interspecific encounter, i.e., probability that two entities +\item The Gini-Simpson index is the probability of interspecific encounter, i.e., probability that two entities represent different types. - -- Chao1 estimator is a nonparameteric asymptotic estimator of species richness (number of species in a population). - -- Rarefaction is a technique to assess species richness from the results of sampling through extrapolation. - -- Hill numbers are a mathematically unified family of diversity indices (differing among themselves +\item Chao1 estimator is a nonparameteric asymptotic estimator of species richness (number of species in a population). +\item Rarefaction is a technique to assess species richness from the results of sampling through extrapolation. +\item Hill numbers are a mathematically unified family of diversity indices (differing among themselves only by an exponent q). - -- d50 is a recently developed immune diversity estimate. It calculates the minimum number of distinct clonotypes +\item d50 is a recently developed immune diversity estimate. It calculates the minimum number of distinct clonotypes amounting to greater than or equal to 50 percent of a total of sequencing reads obtained following amplification and sequencing - -- dXX is a similar to d50 index where XX corresponds to desirable percent of total sequencing reads. +\item dXX is a similar to d50 index where XX corresponds to desirable percent of total sequencing reads. +} } \examples{ data(immdata) diff --git a/man/repExplore.Rd b/man/repExplore.Rd index dcc39b0c..a94eec0e 100644 --- a/man/repExplore.Rd +++ b/man/repExplore.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/explore.R +% Please edit documentation in R/v0_explore.R \name{repExplore} \alias{repExplore} \title{Main function for exploratory data analysis: compute the distribution of lengths, clones, etc.} @@ -13,13 +13,13 @@ repExplore( } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -51,6 +51,8 @@ with exploratory analysis statistics. Otherwise, it returns a numeric matrix with exploratory analysis statistics for all input repertoires. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + The \code{repExplore} function calculates the basic statistics of repertoire: the number of unique immune receptor clonotypes, their relative abundances, and sequence length distribution across the input dataset. diff --git a/man/repFilter.Rd b/man/repFilter.Rd index aa54c7b3..d136490c 100644 --- a/man/repFilter.Rd +++ b/man/repFilter.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/filters.R +% Please edit documentation in R/v0_filters.R \name{repFilter} \alias{repFilter} \alias{include} @@ -27,35 +27,39 @@ Default value: 'by.clonotype'.} \item{.query}{Filtering query. It's a named list of filters that will be applied to data. Possible values for names in this list are dependent on filter methods: -- by.meta: filters by metadata. Names in the named list are metadata column headers. -- by.repertoire: filters by the number of clonotypes or total number of clones in sample. +\itemize{ +\item by.meta: filters by metadata. Names in the named list are metadata column headers. +\item by.repertoire: filters by the number of clonotypes or total number of clones in sample. Possible names in the named list are "n_clonotypes" and "n_clones". -- by.clonotype: filters by data in all samples. Names in the named list are +\item by.clonotype: filters by data in all samples. Names in the named list are data column headers. Elements of the named list for each of the filters are filtering options. Possible values for filtering options: -- include("STR1", "STR2", ...): keeps only rows with matching values. +\item include("STR1", "STR2", ...): keeps only rows with matching values. Available for methods: "by.meta", "by.clonotype". -- exclude("STR1", "STR2", ...): removes rows with matching values. +\item exclude("STR1", "STR2", ...): removes rows with matching values. Available for methods: "by.meta", "by.clonotype". -- lessthan(value): keeps rows/samples with numeric values less than specified. +\item lessthan(value): keeps rows/samples with numeric values less than specified. Available for methods: "by.meta", "by.repertoire", "by.clonotype". -- morethan(value): keeps rows/samples with numeric values more than specified. +\item morethan(value): keeps rows/samples with numeric values more than specified. Available for methods: "by.meta", "by.repertoire", "by.clonotype". -- interval(from, to): keeps rows/samples with numeric values that fits in this interval. +\item interval(from, to): keeps rows/samples with numeric values that fits in this interval. from is inclusive, to is exclusive. Available for methods: "by.meta", "by.repertoire", "by.clonotype". -Default value: 'list(CDR3.aa = exclude("partial", "out_of_frame"))'.} +Default value: 'list(CDR3.aa = exclude("partial", "out_of_frame"))'. +}} \item{.match}{Matching method for "include" and "exclude" options in query. Possible values: -- exact: matches only the exact specified string; -- startswith: matches all strings starting with the specified substring; -- substring: matches all strings containing the specified substring. -Default value: 'exact'.} +\itemize{ +\item exact: matches only the exact specified string; +\item startswith: matches all strings starting with the specified substring; +\item substring: matches all strings containing the specified substring. +Default value: 'exact'. +}} } \description{ -Main function for data filtering +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/repGermline.Rd b/man/repGermline.Rd index c3acad2e..652916d8 100644 --- a/man/repGermline.Rd +++ b/man/repGermline.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/germline.R +% Please edit documentation in R/v0_germline.R \name{repGermline} \alias{repGermline} \title{Creates germlines for clonal lineages} @@ -7,7 +7,7 @@ repGermline(.data, .species, .min_nuc_outside_cdr3, .threads) } \arguments{ -\item{.data}{The data to be processed. Can be \link{data.frame}, \link{data.table} +\item{.data}{The data to be processed. Can be \link{data.frame}, \link[data.table:data.table]{data.table::data.table} or a list of these objects. It must have columns in the immunarch compatible format \link{immunarch_data_format}.} @@ -26,12 +26,16 @@ outside of CDR3 to be considered good for further alignment.} } \value{ Data with added columns: -* Sequence (FR1+CDR1+FR2+CDR2+FR3+CDR3+FR4 in nucleotides; the column will be replaced if exists) -* V.allele, J.allele (chosen alleles of V and J genes), -* V.aa, J.aa (V and J sequences from original clonotype, outside CDR3, converted to amino acids) -* Germline.sequence (combined germline nucleotide sequence) +\itemize{ +\item Sequence (FR1+CDR1+FR2+CDR2+FR3+CDR3+FR4 in nucleotides; the column will be replaced if exists) +\item V.allele, J.allele (chosen alleles of V and J genes), +\item V.aa, J.aa (V and J sequences from original clonotype, outside CDR3, converted to amino acids) +\item Germline.sequence (combined germline nucleotide sequence) +} } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + This function creates germlines for clonal lineages. B cell clonal lineage represents a set of B cells that presumably have a common origin (arising from the same VDJ rearrangement event) and a common ancestor. Each clonal lineage has its own germline sequence diff --git a/man/repLoad.Rd b/man/repLoad.Rd index 6d9eeaf8..516c8878 100644 --- a/man/repLoad.Rd +++ b/man/repLoad.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/io.R +% Please edit documentation in R/v0_io.R \name{repLoad} \alias{repLoad} \title{Load immune repertoire files into the R workspace} @@ -9,14 +9,12 @@ repLoad(.path, .mode = "paired", .coding = TRUE, ...) \arguments{ \item{.path}{A character string specifying the path to the input data. Input data can be one of the following: - -- a single repertoire file. +\itemize{ +\item a single repertoire file. In this case \code{repLoad} returns an R \link{data.frame}; - -- a vector of paths to repertoire files. +\item a vector of paths to repertoire files. Same as in the case with no metadata file presented in the next section below; - -- a path to the folder with repertoire files and, if available, metadata file "metadata.txt". +\item a path to the folder with repertoire files and, if available, metadata file "metadata.txt". If the metadata file if presented, then the \code{repLoad} returns a list with two elements "data" and "meta". "data" is an another list with repertoire R \link{data.frame}s. "meta" is a data frame with the metadata. If the metadata file "metadata.txt" is not presented, then the \code{repLoad} creates a dummy metadata file with @@ -24,7 +22,8 @@ sample names and returns a list with two elements "data" and "meta". If input data has multiple chains or cell types stored in the same file (for example, like in 10xGenomics repertoire files), such repertoire files will be splitted to different R data frames with only one type of chain and cell presented. The metadata file will have additional columns specifying -cell and chain types for different samples.} +cell and chain types for different samples. +}} \item{.mode}{Either "single" for single chain data or "paired" for paired chain data. @@ -38,12 +37,14 @@ By default, 10X Genomics data will be loaded as paired chain data, and other fil } \value{ A list with two named elements: - - - "data" is a list of input samples; - - - "meta" is a data frame with sample metadata. +\itemize{ +\item "data" is a list of input samples; +\item "meta" is a data frame with sample metadata. +} } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + The \code{repLoad} function loads repertoire files into R workspace in the immunarch format where you can immediately use them for the analysis. \code{repLoad} automatically detects the right format for @@ -58,35 +59,26 @@ It can have any number of additional columns with arbitrary names. The first column should contain base names of files without extensions in your folder. Example: \tabular{llll}{ - Sample \tab Sex \tab Age \tab Status\cr - immunoseq_1 \tab M \tab 1 \tab C\cr - immunoseq_2 \tab M \tab 2 \tab C\cr - immunoseq_3 \tab FALSE \tab 3 \tab A +Sample \tab Sex \tab Age \tab Status\cr +immunoseq_1 \tab M \tab 1 \tab C\cr +immunoseq_2 \tab M \tab 2 \tab C\cr +immunoseq_3 \tab FALSE \tab 3 \tab A } Currently, Immunarch support the following formats: - -- "immunoseq" - ImmunoSEQ of any version. http://www.adaptivebiotech.com/immunoseq - -- "mitcr" - MiTCR. https://github.com/milaboratory/mitcr - -- "mixcr" - MiXCR (the "all" files) of any version. https://github.com/milaboratory/mixcr - -- "migec" - MiGEC. http://migec.readthedocs.io/en/latest/ - -- "migmap" - For parsing IgBLAST results postprocessed with MigMap. https://github.com/mikessh/migmap - -- "tcr" - tcR, our previous package. https://imminfo.github.io/tcr/ - -- "vdjtools" - VDJtools of any version. http://vdjtools-doc.readthedocs.io/en/latest/ - -- "imgt" - IMGT HighV-QUEST. http://www.imgt.org/HighV-QUEST/ - -- "airr" - adaptive immune receptor repertoire (AIRR) data format. http://docs.airr-community.org/en/latest/datarep/overview.html - -- "10x" - 10XGenomics clonotype annotations tables. https://support.10xgenomics.com/single-cell-vdj/software/pipelines/latest/output/annotation - -- "archer" - ArcherDX clonotype tables. https://archerdx.com/ +\itemize{ +\item "immunoseq" - ImmunoSEQ of any version. http://www.adaptivebiotech.com/immunoseq +\item "mitcr" - MiTCR. https://github.com/milaboratory/mitcr +\item "mixcr" - MiXCR (the "all" files) of any version. https://github.com/milaboratory/mixcr +\item "migec" - MiGEC. http://migec.readthedocs.io/en/latest/ +\item "migmap" - For parsing IgBLAST results postprocessed with MigMap. https://github.com/mikessh/migmap +\item "tcr" - tcR, our previous package. https://imminfo.github.io/tcr/ +\item "vdjtools" - VDJtools of any version. http://vdjtools-doc.readthedocs.io/en/latest/ +\item "imgt" - IMGT HighV-QUEST. http://www.imgt.org/HighV-QUEST/ +\item "airr" - adaptive immune receptor repertoire (AIRR) data format. http://docs.airr-community.org/en/latest/datarep/overview.html +\item "10x" - 10XGenomics clonotype annotations tables. https://support.10xgenomics.com/single-cell-vdj/software/pipelines/latest/output/annotation +\item "archer" - ArcherDX clonotype tables. https://archerdx.com/ +} } \examples{ # To load the data from a single file (note that you don't need to specify the data format): diff --git a/man/repOverlap.Rd b/man/repOverlap.Rd index 75201b13..0677ac6d 100644 --- a/man/repOverlap.Rd +++ b/man/repOverlap.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/overlap.R +% Please edit documentation in R/v0_overlap.R \name{repOverlap} \alias{repOverlap} \title{Main function for public clonotype statistics calculations} @@ -22,13 +22,13 @@ repOverlap( } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -75,6 +75,8 @@ If only two repertoires were provided, return value is single numeric value. If one of the incremental method is chosen, return list of overlap matrix. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + The \code{repOverlap} function is designed to analyse the overlap between two or more repertoires. It contains a number of methods to compare immune receptor sequences that are shared between individuals. diff --git a/man/repOverlapAnalysis.Rd b/man/repOverlapAnalysis.Rd index 40db2ad8..d4cdf1e9 100644 --- a/man/repOverlapAnalysis.Rd +++ b/man/repOverlapAnalysis.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/overlap_analysis.R +% Please edit documentation in R/v0_overlap_analysis.R \name{repOverlapAnalysis} \alias{repOverlapAnalysis} \title{Post-analysis of public clonotype statistics: PCA, clustering, etc.} @@ -17,7 +17,7 @@ repOverlapAnalysis( } \arguments{ \item{.data}{Any distance matrix between pairs of repertoires. You can also pass your -output from \code{\link{repOverlap}}.} +output from \code{\link[=repOverlap]{repOverlap()}}.} \item{.method}{A string that defines the type of analysis to perform.} @@ -25,26 +25,28 @@ output from \code{\link{repOverlap}}.} \item{.raw}{A logical value. Set TRUE if you want to receive raw output of clustering or dimensionality reduction function of choice. Set FALSE if you want to receive -processed output that can be subjected to visualisation with \code{\link{vis}} function.} +processed output that can be subjected to visualisation with \code{\link[=vis]{vis()}} function.} -\item{.perp}{A numerical value, t-SNE parameter, see \code{\link{immunr_tsne}}.} +\item{.perp}{A numerical value, t-SNE parameter, see \code{\link[=immunr_tsne]{immunr_tsne()}}.} -\item{.theta}{A numerical value, t-SNE parameter, see \code{\link{immunr_tsne}}.} +\item{.theta}{A numerical value, t-SNE parameter, see \code{\link[=immunr_tsne]{immunr_tsne()}}.} -\item{.eps}{A numerical value, DBscan epsylon parameter, see \code{\link{immunr_dbscan}}.} +\item{.eps}{A numerical value, DBscan epsylon parameter, see \code{\link[=immunr_dbscan]{immunr_dbscan()}}.} -\item{.k}{The number of clusters to create, passed as \code{k} to \link[factoextra]{hcut} or as \code{centers} to \link{kmeans}.} +\item{.k}{The number of clusters to create, passed as \code{k} to \link[factoextra:hcut]{hcut} or as \code{centers} to \link{kmeans}.} } \value{ Depends on the last element in the \code{.method} string. See \link{immunr_tsne} for more info. } \description{ -The \code{\link{repOverlapAnalysis}} function contains advanced data +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +The \code{\link[=repOverlapAnalysis]{repOverlapAnalysis()}} function contains advanced data analysis methods. You can use several clustering and dimensionality reduction techniques in order to investigate further the difference between repertoires provided. -To cluster a subset of similar data with \code{\link{repOverlapAnalysis}} you can +To cluster a subset of similar data with \code{\link[=repOverlapAnalysis]{repOverlapAnalysis()}} you can perform hierarchical clustering, k-means or dbscan ('hclust', 'kmeans', 'dbscan' respectively). diff --git a/man/repSample.Rd b/man/repSample.Rd index 008ab92c..f1c1bc06 100644 --- a/man/repSample.Rd +++ b/man/repSample.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/sampling.R +% Please edit documentation in R/v0_sampling.R \name{repSample} \alias{repSample} \title{Downsampling and resampling of immune repertoires} @@ -13,13 +13,13 @@ repSample( } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -38,6 +38,8 @@ repertoires to the size of the smallest repertoire in the ".data".} Subsampled immune repertoire or a list of subsampled immune repertoires. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Sample (downsample) repertoires using different approches. } \details{ diff --git a/man/repSave.Rd b/man/repSave.Rd index 539fb9c4..d2e79a25 100644 --- a/man/repSave.Rd +++ b/man/repSave.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/io.R +% Please edit documentation in R/v0_io.R \name{repSave} \alias{repSave} \title{Save immune repertoires to the disk} @@ -23,6 +23,8 @@ name if a single dataframe is provided to .data argument.} No return value. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + The \code{repSave} function is deigned to save your data to the disk in desirable format. Currently supports "immunarch" and "vdjtools" file formats. } @@ -31,9 +33,10 @@ It is not necessary to create directories beforehand. If the provided directory does not exist it will be created automatically. } \examples{ +\dontrun{ data(immdata) # Reduce data to save time on examples -immdata$data <- purrr::map(immdata$data, ~ .x \%>\% head(10)) +immdata$data <- map(immdata$data, ~ .x \%>\% head(10)) dirpath <- tempdir() # Save the list of repertoires repSave(immdata, dirpath) @@ -43,4 +46,5 @@ new_immdata <- repLoad(dirpath) # sum(immdata$data[[2]] != new_immdata$data[[2]], na.rm = TRUE) # sum(immdata$meta != new_immdata$meta, na.rm = TRUE) } +} \concept{io} diff --git a/man/repSomaticHypermutation.Rd b/man/repSomaticHypermutation.Rd index e6d8e767..4ec0fc15 100644 --- a/man/repSomaticHypermutation.Rd +++ b/man/repSomaticHypermutation.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/somatic_hypermutation.R +% Please edit documentation in R/v0_somatic_hypermutation.R \name{repSomaticHypermutation} \alias{repSomaticHypermutation} \title{Calculates number of mutations against the germline for each clonotype} @@ -21,16 +21,20 @@ The dataframe has all the columns from repClonalFamily() output dataframe, with column unnested: the resulting dataframe has one line per clonotype. Clone.ID column contains original IDs for clonotypes, and can be used as dataframe key. New columns are added: -* Germline.Alignment.V: contains V gene alignment of current clonotype with the germline -* Germline.Alignment.J: contains J gene alignment of current clonotype with the germline -* Substitutions: contains number of substitutions in the alignment (summary for V and J) -* Insertions: contains number of insertions in the clonotype relative to germline - (summary for V and J) -* Deletions: contains number of deletions in the clonotype relative to germline - (summary for V and J) -* Mutations: contains total number of mutations in the alignment (summary for V and J) +\itemize{ +\item Germline.Alignment.V: contains V gene alignment of current clonotype with the germline +\item Germline.Alignment.J: contains J gene alignment of current clonotype with the germline +\item Substitutions: contains number of substitutions in the alignment (summary for V and J) +\item Insertions: contains number of insertions in the clonotype relative to germline +(summary for V and J) +\item Deletions: contains number of deletions in the clonotype relative to germline +(summary for V and J) +\item Mutations: contains total number of mutations in the alignment (summary for V and J) +} } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + This function aligns V and J genes from the germline in each cluster with corresponding genes in each clonotype, saves the alignments for purpose of visualization, and calculates number of mutations for each clonotype. diff --git a/man/scdata.Rd b/man/scdata.Rd index 14d06d90..b395e3bd 100644 --- a/man/scdata.Rd +++ b/man/scdata.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/data_docs.R +% Please edit documentation in R/v0_data_docs.R \docType{data} \name{scdata} \alias{scdata} @@ -11,9 +11,9 @@ A list of four elements: "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} - ... +\item{data}{List of immune repertoire data frames.} +\item{meta}{Metadata} +... } } \usage{ diff --git a/man/select_barcodes.Rd b/man/select_barcodes.Rd index ebca611a..3b00c2b5 100644 --- a/man/select_barcodes.Rd +++ b/man/select_barcodes.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/singlecell.R +% Please edit documentation in R/v0_singlecell.R \name{select_barcodes} \alias{select_barcodes} \title{Select specific clonotypes using barcodes from single-cell metadata} @@ -8,13 +8,13 @@ select_barcodes(.data, .barcodes, .force.list = FALSE) } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -31,6 +31,8 @@ with clonotype barcodes corresponding to the input barcodes. The output list nam in the ".barcode" argument (Seurat::Idents() case only). } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Subsets the input immune repertoire by barcodes. Creates a vector of barcodes to subset or a vector cluster IDs and corresponding barcodes to get a list of immune repertoires corresponding to cluster IDs. diff --git a/man/select_clusters.Rd b/man/select_clusters.Rd index bbae94a7..cfd01257 100644 --- a/man/select_clusters.Rd +++ b/man/select_clusters.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/singlecell.R +% Please edit documentation in R/v0_singlecell.R \name{select_clusters} \alias{select_clusters} \title{Split the immune repertoire data to clusters from single-cell barcodes} @@ -21,6 +21,8 @@ A list with two elements "data" and "meta" with updated immune repertoire tables metadata. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Given the vector of barcodes from Seurat, splits the input repertoires to separate subsets following the barcodes' assigned IDs. Useful in case you want to split immune repertoires by patients or clusters. diff --git a/man/seqCluster.Rd b/man/seqCluster.Rd index e726ad0b..f112051a 100644 --- a/man/seqCluster.Rd +++ b/man/seqCluster.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/seqCluster.R +% Please edit documentation in R/v0_seqCluster.R \name{seqCluster} \alias{seqCluster} \title{Function for assigning clusters based on sequences similarity} @@ -8,7 +8,7 @@ seqCluster(.data, .dist, .perc_similarity, .nt_similarity, .fixed_threshold) } \arguments{ \item{.data}{The data which was used to caluculate .dist object. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format \link{immunarch_data_format}} @@ -26,14 +26,17 @@ the threshold of allowing a 1 in n nucleotides mismatch in sequencies.} Immdata data format object. Same as .data, but with extra 'Cluster' column with clusters assigned. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Graph clustering based on distances between sequences } \examples{ - +\dontrun{ data(immdata) # In this example, we will use only 2 samples with 500 clonotypes in each for time saving input_data <- lapply(immdata$data[1:2], head, 500) dist_result <- seqDist(input_data) cluster_result <- seqCluster(input_data, dist_result, .fixed_threshold = 1) } +} \concept{seq_cluster} diff --git a/man/seqDist.Rd b/man/seqDist.Rd index 6ae7762c..ac5172d3 100644 --- a/man/seqDist.Rd +++ b/man/seqDist.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/distance.R +% Please edit documentation in R/v0_distance.R \name{seqDist} \alias{seqDist} \title{Function for computing distance for sequences} @@ -9,7 +9,7 @@ seqDist(.data, .col = 'CDR3.nt', .method = 'hamming', } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format \link{immunarch_data_format}} @@ -40,14 +40,16 @@ In case of user-defined function, it should take x and y parameters as input and Named list of list with \link{dist} objects for given repertoires for each combination of .group_by variable(s) and/or sequence length of .col. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Computing sequential distances between clonotypes from two repertoires: } \examples{ - +\dontrun{ data(immdata) # Reducing data to save time on examples -immdata$data <- purrr::map(immdata$data, ~ .x \%>\% head(10)) -# Computing hamming distance for the first two repertoires in \code{'immdata'} +immdata$data <- map(immdata$data, ~ .x \%>\% head(10)) +# Computing hamming distance for the first two repertoires in `'immdata'` seqDist(immdata$data[1:2]) # Here we define a custom distance function @@ -63,5 +65,7 @@ f <- function(x, y) { } seqDist(immdata$data[1:2], .method = f, .group_by_seqLength = FALSE) +} + } \concept{distance} diff --git a/man/set_pb.Rd b/man/set_pb.Rd index 69682d05..1787395b 100644 --- a/man/set_pb.Rd +++ b/man/set_pb.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{set_pb} \alias{set_pb} \alias{add_pb} diff --git a/man/spectratype.Rd b/man/spectratype.Rd index b52d9dc0..46c0014e 100644 --- a/man/spectratype.Rd +++ b/man/spectratype.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/spectratyping.R +% Please edit documentation in R/v0_spectratyping.R \name{spectratype} \alias{spectratype} \title{Immune repertoire spectratyping} @@ -8,13 +8,13 @@ spectratype(.data, .quant = c("id", "count"), .col = "nt") } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} @@ -33,7 +33,7 @@ Clonal counts of equal clonotypes will be summed up.} Data frame with distributions of clonotypes per CDR3 length. } \description{ -Immune repertoire spectratyping +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ # Load the data diff --git a/man/split_to_kmers.Rd b/man/split_to_kmers.Rd index c456ce7b..13f65399 100644 --- a/man/split_to_kmers.Rd +++ b/man/split_to_kmers.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/kmers.R +% Please edit documentation in R/v0_kmers.R \name{split_to_kmers} \alias{split_to_kmers} \alias{kmer_profile} @@ -34,7 +34,7 @@ For more information see https://en.wikipedia.org/wiki/Position_weight_matrix.} \code{kmer_profile} - a matrix with per-position amino acid statistics. } \description{ -Analysis immune repertoire kmer statistics: sequence profiles, etc. +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/switch_type.Rd b/man/switch_type.Rd index 898ce890..4d911208 100644 --- a/man/switch_type.Rd +++ b/man/switch_type.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tools.R +% Please edit documentation in R/v0_tools.R \name{switch_type} \alias{switch_type} \alias{process_col_argument} diff --git a/man/top.Rd b/man/top.Rd index ec7f63d0..d46f40e1 100644 --- a/man/top.Rd +++ b/man/top.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocessing.R +% Please edit documentation in R/v0_preprocessing.R \name{top} \alias{top} \title{Get the N most abundant clonotypes} @@ -8,13 +8,13 @@ top(.data, .n = 10) } \arguments{ \item{.data}{The data to be processed. Can be \link{data.frame}, -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} diff --git a/man/trackClonotypes.Rd b/man/trackClonotypes.Rd index 20cc1d5d..22c93398 100644 --- a/man/trackClonotypes.Rd +++ b/man/trackClonotypes.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/dynamics.R +% Please edit documentation in R/v0_dynamics.R \name{trackClonotypes} \alias{trackClonotypes} \title{Track clonotypes across time and data points} @@ -8,25 +8,24 @@ trackClonotypes(.data, .which = list(1, 15), .col = "aa", .norm = TRUE) } \arguments{ \item{.data}{The data to process. It can be a \link{data.frame}, a -\link{data.table}, or a list of these objects. +\link[data.table:data.table]{data.table::data.table}, or a list of these objects. Every object must have columns in the immunarch compatible format. \link{immunarch_data_format} Competent users may provide advanced data representations: -DBI database connections, Apache Spark DataFrame from \link{copy_to} or a list +DBI database connections, or a list of these objects. They are supported with the same limitations as basic objects. Note: each connection must represent a separate repertoire.} \item{.which}{An argument that regulates which clonotypes to choose for tracking. There are three options for this argument: - -1) passes a list with two elements \code{list(X, Y)}, where \code{X} is the name or the index of a target repertoire from ".data", and +\enumerate{ +\item passes a list with two elements \code{list(X, Y)}, where \code{X} is the name or the index of a target repertoire from ".data", and \code{Y} is the number of the most abundant clonotypes to take from \code{X}. - -2) passes a character vector of sequences to take from all data frames; - -3) passes a data frame (data table, database) with one or more columns - first for sequences, and other for gene segments (if applicable). +\item passes a character vector of sequences to take from all data frames; +\item passes a data frame (data table, database) with one or more columns - first for sequences, and other for gene segments (if applicable). +} See the "Examples" below with examples for each option.} @@ -43,6 +42,8 @@ in the function output.} Data frame with input sequences and counts or proportions for each of the input repertoire. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Tracks the temporal dynamics of clonotypes in repertoires. For example, tracking across multiple time points after vaccination. diff --git a/man/vis.Rd b/man/vis.Rd index eff1ffa0..22f92818 100644 --- a/man/vis.Rd +++ b/man/vis.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis} \alias{vis} \title{One function to visualise them all} @@ -15,6 +15,8 @@ vis(.data, ...) A ggplot2, pheatmap or circlize object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Output from every function in immunarch can be visualised with a single function - \code{vis}. The \code{vis} automatically detects the type of the data and draws a proper visualisation. For example, output @@ -26,54 +28,50 @@ See "Details" for the list of available visualisations. List of available visualisations for different kinds of data. Basic analysis: - -- Exploratory analysis results (from \link{repExplore}) - see \link{vis.immunr_exp_vol}; - -- Clonality statistics (from \link{repClonality}) - see \link{vis.immunr_homeo}. +\itemize{ +\item Exploratory analysis results (from \link{repExplore}) - see \link{vis.immunr_exp_vol}; +\item Clonality statistics (from \link{repClonality}) - see \link{vis.immunr_homeo}. +} Overlaps and public clonotypes: - -- Overlaps (from \link{repOverlap}) using heatmaps, circos plots, polar area plots - see \link{vis.immunr_ov_matrix}; - -- Overlap clustering (from \link{repOverlapAnalysis}) - see \link{vis.immunr_hclust}; - -- Repertoire incremental overlaps (from \link{repOverlap}) - see \link{vis.immunr_inc_overlap}; - -- Public repertoire abundance (from \link{pubRep}) - vis \link{vis.immunr_public_repertoire}. +\itemize{ +\item Overlaps (from \link{repOverlap}) using heatmaps, circos plots, polar area plots - see \link{vis.immunr_ov_matrix}; +\item Overlap clustering (from \link{repOverlapAnalysis}) - see \link{vis.immunr_hclust}; +\item Repertoire incremental overlaps (from \link{repOverlap}) - see \link{vis.immunr_inc_overlap}; +\item Public repertoire abundance (from \link{pubRep}) - vis \link{vis.immunr_public_repertoire}. +} Gene usage: - -- Gene usage statistics (from \link{geneUsage}) using bar plots, box plots - see \link{vis.immunr_gene_usage}; - -- Gene usage distances (from \link{geneUsageAnalysis}) using heatmaps, circos plots, polar area plots - see \link{vis.immunr_ov_matrix}; - -- Gene usage clustering (from \link{geneUsageAnalysis}) - see \link{vis.immunr_hclust}. +\itemize{ +\item Gene usage statistics (from \link{geneUsage}) using bar plots, box plots - see \link{vis.immunr_gene_usage}; +\item Gene usage distances (from \link{geneUsageAnalysis}) using heatmaps, circos plots, polar area plots - see \link{vis.immunr_ov_matrix}; +\item Gene usage clustering (from \link{geneUsageAnalysis}) - see \link{vis.immunr_hclust}. +} Diversity estimation: - -- Diversity estimations (from \link{repDiversity}) - see \link{vis.immunr_chao1}. +\itemize{ +\item Diversity estimations (from \link{repDiversity}) - see \link{vis.immunr_chao1}. +} BCR analysis: - -- Clonal tree (from \link{repClonalFamily}) - see \link{vis.clonal_family} and \link{vis.clonal_family_tree}. +\itemize{ +\item Clonal tree (from \link{repClonalFamily}) - see \link{vis.clonal_family} and \link{vis.clonal_family_tree}. +} Advanced analysis: - -- Repertoire dynamics (from \link{trackClonotypes}) - see \link{vis.immunr_dynamics}; - -- Sequence logo plots of amino acid distributions (from \link{kmer_profile}) - see \link{vis_seqlogo}; - -- Kmers distributions (from \link{getKmers}) - see \link{vis.immunr_kmer_table}; - -- Mutation networks (from mutationNetwork) - Work In Progress on vis.immunr_mutation_network; - -- CDR3 amino acid properties, e.g., biophysical (from cdrProp) - Work In Progress on vis.immunr_cdr_prop. +\itemize{ +\item Repertoire dynamics (from \link{trackClonotypes}) - see \link{vis.immunr_dynamics}; +\item Sequence logo plots of amino acid distributions (from \link{kmer_profile}) - see \link{vis_seqlogo}; +\item Kmers distributions (from \link{getKmers}) - see \link{vis.immunr_kmer_table}; +\item Mutation networks (from mutationNetwork) - Work In Progress on vis.immunr_mutation_network; +\item CDR3 amino acid properties, e.g., biophysical (from cdrProp) - Work In Progress on vis.immunr_cdr_prop. +} Additionaly, we provide a wrapper functions for visualisations of common data types: - -- Any data frames or matrices using heatmaps - see \link{vis_heatmap} and \link{vis_heatmap2}; - -- Any data frames or matrices using circos plots - see \link{vis_circos}. +\itemize{ +\item Any data frames or matrices using heatmaps - see \link{vis_heatmap} and \link{vis_heatmap2}; +\item Any data frames or matrices using circos plots - see \link{vis_circos}. +} } \examples{ # Load the test data diff --git a/man/vis.clonal_family.Rd b/man/vis.clonal_family.Rd index 79b71eff..dcdcc33d 100644 --- a/man/vis.clonal_family.Rd +++ b/man/vis.clonal_family.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.clonal_family} \alias{vis.clonal_family} \title{Visualise clonal family tree: wrapper for calling on the entire repClonalFamily output} @@ -7,7 +7,7 @@ \method{vis}{clonal_family}(.data, ...) } \arguments{ -\item{.data}{Clonal families from 1 or multiple samples: \code{\link{repClonalFamily}} output.} +\item{.data}{Clonal families from 1 or multiple samples: \code{\link[=repClonalFamily]{repClonalFamily()}} output.} \item{...}{Not used here.} } @@ -15,7 +15,7 @@ A ggraph object. } \description{ -Visualise clonal family tree: wrapper for calling on the entire repClonalFamily output +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(bcrdata) diff --git a/man/vis.clonal_family_tree.Rd b/man/vis.clonal_family_tree.Rd index 7aba8f06..d88d3feb 100644 --- a/man/vis.clonal_family_tree.Rd +++ b/man/vis.clonal_family_tree.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.clonal_family_tree} \alias{vis.clonal_family_tree} \title{Visualise clonal family tree} @@ -7,7 +7,7 @@ \method{vis}{clonal_family_tree}(.data, ...) } \arguments{ -\item{.data}{Single clonal family tree data from 1 cluster: 1 element from TreeStats column from \code{\link{repClonalFamily}} output.} +\item{.data}{Single clonal family tree data from 1 cluster: 1 element from TreeStats column from \code{\link[=repClonalFamily]{repClonalFamily()}} output.} \item{...}{Not used here.} } @@ -15,7 +15,7 @@ A ggraph object. } \description{ -Visualise clonal family tree +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(bcrdata) diff --git a/man/vis.immunr_chao1.Rd b/man/vis.immunr_chao1.Rd index acb0c94a..8f8f9384 100644 --- a/man/vis.immunr_chao1.Rd +++ b/man/vis.immunr_chao1.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_chao1} \alias{vis.immunr_chao1} \alias{vis.immunr_dxx} @@ -23,7 +23,7 @@ ) } \arguments{ -\item{.data}{Output from \code{\link{repDiversity}}.} +\item{.data}{Output from \code{\link[=repDiversity]{repDiversity()}}.} \item{.by}{Pass NA if you want to plot samples without grouping. @@ -56,16 +56,18 @@ Disabled if no group passed to the ".by" argument.} A ggplot2 object. } \description{ -An utility function to visualise the output from \code{\link{repDiversity}}. +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +An utility function to visualise the output from \code{\link[=repDiversity]{repDiversity()}}. } \details{ If data is grouped, then statistical tests for comparing means of groups will be performed, unless \code{.test = FALSE} is supplied. In case there are only two groups, the Wilcoxon rank sum test (https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test) is performed -(R function \code{\link{wilcox.test}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. -In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link{kruskal.test}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. +(R function \code{\link[=wilcox.test]{wilcox.test()}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. +In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal\%E2\%80\%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link[=kruskal.test]{kruskal.test()}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. A significant Kruskal-Wallis test indicates that at least one sample stochastically dominates one other sample. Adjusted for multiple comparisons P-values are plotted on the top of groups. -P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm%E2%80%93Bonferroni_method) (also known as Holm-Bonferroni correction). +P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm\%E2\%80\%93Bonferroni_method) (also known as Holm-Bonferroni correction). You can execute the command \code{?p.adjust} in the R console to see more. } \examples{ diff --git a/man/vis.immunr_clonal_prop.Rd b/man/vis.immunr_clonal_prop.Rd index 732350ee..7834b015 100644 --- a/man/vis.immunr_clonal_prop.Rd +++ b/man/vis.immunr_clonal_prop.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_clonal_prop} \alias{vis.immunr_clonal_prop} \alias{vis.immunr_homeo} @@ -20,7 +20,7 @@ ) } \arguments{ -\item{.data}{Output from \code{\link{repClonality}}.} +\item{.data}{Output from \code{\link[=repClonality]{repClonality()}}.} \item{.by}{Pass NA if you want to plot samples without grouping. @@ -53,16 +53,18 @@ Disabled if no group passed to the ".by" argument.} A ggplot2 object. } \description{ -An utility function to visualise the output from \code{\link{repClonality}}. +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +An utility function to visualise the output from \code{\link[=repClonality]{repClonality()}}. } \details{ If data is grouped, then statistical tests for comparing means of groups will be performed, unless \code{.test = FALSE} is supplied. In case there are only two groups, the Wilcoxon rank sum test (https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test) is performed -(R function \code{\link{wilcox.test}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. -In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link{kruskal.test}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. +(R function \code{\link[=wilcox.test]{wilcox.test()}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. +In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal\%E2\%80\%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link[=kruskal.test]{kruskal.test()}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. A significant Kruskal-Wallis test indicates that at least one sample stochastically dominates one other sample. Adjusted for multiple comparisons P-values are plotted on the top of groups. -P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm%E2%80%93Bonferroni_method) (also known as Holm-Bonferroni correction). +P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm\%E2\%80\%93Bonferroni_method) (also known as Holm-Bonferroni correction). You can execute the command \code{?p.adjust} in the R console to see more. } \examples{ diff --git a/man/vis.immunr_dynamics.Rd b/man/vis.immunr_dynamics.Rd index a7fedb08..668ff6e6 100644 --- a/man/vis.immunr_dynamics.Rd +++ b/man/vis.immunr_dynamics.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_dynamics} \alias{vis.immunr_dynamics} \title{Visualise clonotype dynamics} @@ -22,7 +22,7 @@ by timepoints. Either See "Examples" below for more details.} A ggplot2 object. } \description{ -Visualise clonotype dynamics +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ # Load an example data that comes with immunarch diff --git a/man/vis.immunr_exp_vol.Rd b/man/vis.immunr_exp_vol.Rd index 70e370db..b8e54b15 100644 --- a/man/vis.immunr_exp_vol.Rd +++ b/man/vis.immunr_exp_vol.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_exp_vol} \alias{vis.immunr_exp_vol} \alias{vis.immunr_exp_count} @@ -20,7 +20,7 @@ ) } \arguments{ -\item{.data}{Output from \code{\link{repExplore}}.} +\item{.data}{Output from \code{\link[=repExplore]{repExplore()}}.} \item{.by}{Pass NA if you want to plot samples without grouping. @@ -53,16 +53,18 @@ Disabled if no group passed to the ".by" argument.} A ggplot2 object. } \description{ -An utility function to visualise the output from \code{\link{repExplore}}. +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +An utility function to visualise the output from \code{\link[=repExplore]{repExplore()}}. } \details{ If data is grouped, then statistical tests for comparing means of groups will be performed, unless \code{.test = FALSE} is supplied. In case there are only two groups, the Wilcoxon rank sum test (https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test) is performed -(R function \code{\link{wilcox.test}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. -In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link{kruskal.test}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. +(R function \code{\link[=wilcox.test]{wilcox.test()}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. +In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal\%E2\%80\%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link[=kruskal.test]{kruskal.test()}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. A significant Kruskal-Wallis test indicates that at least one sample stochastically dominates one other sample. Adjusted for multiple comparisons P-values are plotted on the top of groups. -P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm%E2%80%93Bonferroni_method) (also known as Holm-Bonferroni correction). +P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm\%E2\%80\%93Bonferroni_method) (also known as Holm-Bonferroni correction). You can execute the command \code{?p.adjust} in the R console to see more. } \examples{ diff --git a/man/vis.immunr_gene_usage.Rd b/man/vis.immunr_gene_usage.Rd index 939fc26c..c252977b 100644 --- a/man/vis.immunr_gene_usage.Rd +++ b/man/vis.immunr_gene_usage.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_gene_usage} \alias{vis.immunr_gene_usage} \title{Histograms and boxplots (general case / gene usage)} @@ -10,31 +10,28 @@ \item{.data}{Output from the \link{geneUsage} function.} \item{.plot}{String specifying the plot type: - -- "hist" for histograms using \link{vis_hist}; - -- "heatmap" for heatmaps using \link{vis_heatmap}; - -- "heatmap2" for heatmaps using \link{vis_heatmap2}; - -- "circos" for circos plots using \link{vis_circos}.} +\itemize{ +\item "hist" for histograms using \link{vis_hist}; +\item "heatmap" for heatmaps using \link{vis_heatmap}; +\item "heatmap2" for heatmaps using \link{vis_heatmap2}; +\item "circos" for circos plots using \link{vis_circos}. +}} \item{...}{Other arguments passed to corresponding functions depending on the plot type: - -- "hist" - passes arguments to \link{vis_hist}; - -- "box" - passes arguments to \link{vis_box}; - -- "heatmap" - passes arguments to \link{vis_heatmap}; - -- "heatmap2" - passes arguments to \link{vis_heatmap2} and \link{heatmap} from the "pheatmap" package; - -- "circos" - passes arguments to \link{vis_circos} and \link{chordDiagram} from the "circlize" package.} +\itemize{ +\item "hist" - passes arguments to \link{vis_hist}; +\item "box" - passes arguments to \link{vis_box}; +\item "heatmap" - passes arguments to \link{vis_heatmap}; +\item "heatmap2" - passes arguments to \link{vis_heatmap2} and \link{heatmap} from the "pheatmap" package; +\item "circos" - passes arguments to \link{vis_circos} and \link[circlize:chordDiagram]{circlize::chordDiagram} from the "circlize" package. +}} } \value{ A ggplot2 object, pheatmap or circlize object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualise distributions of genes using heatmaps or other plots. } \examples{ diff --git a/man/vis.immunr_hclust.Rd b/man/vis.immunr_hclust.Rd index 93bb2a6f..0499dc8f 100644 --- a/man/vis.immunr_hclust.Rd +++ b/man/vis.immunr_hclust.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_hclust} \alias{vis.immunr_hclust} \title{Visualisation of hierarchical clustering} @@ -9,7 +9,7 @@ \arguments{ \item{.data}{Clustering results from \link{repOverlapAnalysis} or \link{geneUsageAnalysis}.} -\item{.rect}{Passed to \link{fviz_dend} - whether to add a rectangle around groups.} +\item{.rect}{Passed to \link[factoextra:fviz_dend]{factoextra::fviz_dend} - whether to add a rectangle around groups.} \item{.plot}{A character vector of length one or two specifying which plots to visualise. If "clust" then plot only the clustering. If "best" then plot the number of optimal clusters. @@ -21,6 +21,8 @@ If both then plot both.} Ggplot2 objects inside the patchwork container. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualisation of the results of hierarchical clustering. For other clustering visualisations see \link{vis.immunr_kmeans}. } diff --git a/man/vis.immunr_inc_overlap.Rd b/man/vis.immunr_inc_overlap.Rd index b12a14f9..a065de3d 100644 --- a/man/vis.immunr_inc_overlap.Rd +++ b/man/vis.immunr_inc_overlap.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_inc_overlap} \alias{vis.immunr_inc_overlap} \title{Visualise incremental overlaps} @@ -21,7 +21,7 @@ A ggplot2 object. } \description{ -Visualise incremental overlaps +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/vis.immunr_kmeans.Rd b/man/vis.immunr_kmeans.Rd index 736c133e..ce090099 100644 --- a/man/vis.immunr_kmeans.Rd +++ b/man/vis.immunr_kmeans.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_kmeans} \alias{vis.immunr_kmeans} \alias{vis.immunr_dbscan} @@ -19,15 +19,15 @@ \arguments{ \item{.data}{Clustering results from \link{repOverlapAnalysis} or \link{geneUsageAnalysis}.} -\item{.point}{If TRUE then plot sample points. Passed to \link{fviz_cluster}.} +\item{.point}{If TRUE then plot sample points. Passed to \link[factoextra:fviz_cluster]{factoextra::fviz_cluster}.} -\item{.text}{If TRUE then plot text labels. Passed to \link{fviz_cluster}.} +\item{.text}{If TRUE then plot text labels. Passed to \link[factoextra:fviz_cluster]{factoextra::fviz_cluster}.} -\item{.ellipse}{If TRUE then plot ellipses around all samples. Passed to "ellipse" from \link{fviz_cluster}.} +\item{.ellipse}{If TRUE then plot ellipses around all samples. Passed to "ellipse" from \link[factoextra:fviz_cluster]{factoextra::fviz_cluster}.} -\item{.point.size}{Size of points, passed to "pointsize" from \link{fviz_cluster}.} +\item{.point.size}{Size of points, passed to "pointsize" from \link[factoextra:fviz_cluster]{factoextra::fviz_cluster}.} -\item{.text.size}{Size of text labels, passed to labelsize from \link{fviz_cluster}.} +\item{.text.size}{Size of text labels, passed to labelsize from \link[factoextra:fviz_cluster]{factoextra::fviz_cluster}.} \item{.plot}{A character vector of length one or two specifying which plots to visualise. If "clust" then plot only the clustering. If "best" then plot the number of optimal clusters. @@ -39,6 +39,8 @@ If both then plot both.} Ggplot2 objects inside the pathwork container. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualisation of the results of K-means and DBSCAN clustering. For hierarhical clustering visualisations see \link{vis.immunr_hclust}. } diff --git a/man/vis.immunr_kmer_table.Rd b/man/vis.immunr_kmer_table.Rd index 7b00ea7d..f9d513a2 100644 --- a/man/vis.immunr_kmer_table.Rd +++ b/man/vis.immunr_kmer_table.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_kmer_table} \alias{vis.immunr_kmer_table} \title{Most frequent kmers visualisation.} @@ -27,6 +27,8 @@ A ggplot2 object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Plot a distribution (bar plot) of the most frequent kmers in a data. } \examples{ diff --git a/man/vis.immunr_mds.Rd b/man/vis.immunr_mds.Rd index 9528c305..ba731d9e 100644 --- a/man/vis.immunr_mds.Rd +++ b/man/vis.immunr_mds.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_mds} \alias{vis.immunr_mds} \alias{vis.immunr_pca} @@ -51,16 +51,15 @@ such as age, serostatus or hla.} A ggplot2 object. } \description{ -PCA / MDS / tSNE visualisation (mainly overlap / gene usage) +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \details{ Other visualisation methods: - -- PCA - \link{vis.immunr_pca} - -- MDS - \link{vis.immunr_mds} - -- tSNE - \link{vis.immunr_tsne} +\itemize{ +\item PCA - \link{vis.immunr_pca} +\item MDS - \link{vis.immunr_mds} +\item tSNE - \link{vis.immunr_tsne} +} } \examples{ data(immdata) diff --git a/man/vis.immunr_ov_matrix.Rd b/man/vis.immunr_ov_matrix.Rd index 16601618..1982dfcc 100644 --- a/man/vis.immunr_ov_matrix.Rd +++ b/man/vis.immunr_ov_matrix.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_ov_matrix} \alias{vis.immunr_ov_matrix} \alias{vis.immunr_gu_matrix} @@ -11,25 +11,25 @@ \item{.data}{Output from \link{repOverlap} or \link{geneUsageAnalysis}.} \item{.plot}{A string specifying the plot type: - -- "heatmap" for heatmaps using \link{vis_heatmap}; - -- "heatmap2" for heatmaps using \link{vis_heatmap2}; - -- "circos" for circos plots using \link{vis_circos};} +\itemize{ +\item "heatmap" for heatmaps using \link{vis_heatmap}; +\item "heatmap2" for heatmaps using \link{vis_heatmap2}; +\item "circos" for circos plots using \link{vis_circos}; +}} \item{...}{Other arguments are passed through to the underlying plotting function: - -- "heatmap" - passes arguments to \link{vis_heatmap}; - -- "heatmap2" - passes arguments to \link{vis_heatmap2} and \link{heatmap} from the "pheatmap" package; - -- "circos" - passes arguments to \link{vis_circos} and \link{chordDiagram} from the "circlize" package;} +\itemize{ +\item "heatmap" - passes arguments to \link{vis_heatmap}; +\item "heatmap2" - passes arguments to \link{vis_heatmap2} and \link{heatmap} from the "pheatmap" package; +\item "circos" - passes arguments to \link{vis_circos} and \link[circlize:chordDiagram]{circlize::chordDiagram} from the "circlize" package; +}} } \value{ A ggplot2, pheatmap or circlize object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualises matrices with overlap values or gene usage distances among samples. For details see the links below. } diff --git a/man/vis.immunr_public_repertoire.Rd b/man/vis.immunr_public_repertoire.Rd index c30e780e..691a3477 100644 --- a/man/vis.immunr_public_repertoire.Rd +++ b/man/vis.immunr_public_repertoire.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_public_repertoire} \alias{vis.immunr_public_repertoire} \title{Public repertoire visualisation} @@ -10,12 +10,12 @@ \item{.data}{Public repertoire, an output from \link{pubRep}.} \item{.plot}{A string specifying the plot type: - -- "freq" for visualisation of the distribution of occurrences of clonotypes +\itemize{ +\item "freq" for visualisation of the distribution of occurrences of clonotypes and their frequencies using \link{vis_public_frequencies}. - -- "clonotypes" for visualisation of public clonotype frequenciy correlations between pairs of -samples using \link{vis_public_clonotypes}} +\item "clonotypes" for visualisation of public clonotype frequenciy correlations between pairs of +samples using \link{vis_public_clonotypes} +}} \item{...}{Further arguments passed \link{vis_public_frequencies} or \link{vis_public_clonotypes}, depending on the ".plot" argument.} @@ -24,7 +24,7 @@ depending on the ".plot" argument.} A ggplot2 object. } \description{ -Public repertoire visualisation +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/vis.immunr_public_statistics.Rd b/man/vis.immunr_public_statistics.Rd index 3ceb35ed..c794b99e 100644 --- a/man/vis.immunr_public_statistics.Rd +++ b/man/vis.immunr_public_statistics.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.immunr_public_statistics} \alias{vis.immunr_public_statistics} \title{Visualise sharing of clonotypes among samples} @@ -9,12 +9,14 @@ \arguments{ \item{.data}{Public repertoire - an output from the \link{pubRep} function.} -\item{...}{Other arguments passsed directly to \link{upset}.} +\item{...}{Other arguments passsed directly to \link[UpSetR:upset]{UpSetR::upset}.} } \value{ A ggplot2 object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualise public clonotype frequencies. } \examples{ diff --git a/man/vis.step_failure_ignored.Rd b/man/vis.step_failure_ignored.Rd index 2845a2fd..fee68222 100644 --- a/man/vis.step_failure_ignored.Rd +++ b/man/vis.step_failure_ignored.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis.step_failure_ignored} \alias{vis.step_failure_ignored} \title{Handler for .nofail argument of pipeline steps that prevents examples from crashing @@ -16,6 +16,5 @@ on computers where certain dependencies are not installed} An empty object with "step_failure_ignored" class. } \description{ -Handler for .nofail argument of pipeline steps that prevents examples from crashing -on computers where certain dependencies are not installed +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } diff --git a/man/vis_bar.Rd b/man/vis_bar.Rd index a36ebc41..10e33e93 100644 --- a/man/vis_bar.Rd +++ b/man/vis_bar.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_bar} \alias{vis_bar} \title{Bar plots} @@ -80,7 +80,7 @@ Disabled if no group passed to the ".by" argument.} A ggplot2 object. } \description{ -Bar plots +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ vis_bar(data.frame(Sample = c("A", "B", "C"), Value = c(1, 2, 3))) diff --git a/man/vis_box.Rd b/man/vis_box.Rd index fdaa8b14..8619aa74 100644 --- a/man/vis_box.Rd +++ b/man/vis_box.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_box} \alias{vis_box} \title{Flexible box-plots for visualisation of distributions} @@ -38,7 +38,7 @@ pass NA to ".meta".} \item{.meta}{A metadata object. An R dataframe with sample names and their properties, such as age, serostatus or hla.} -\item{.melt}{If TRUE then apply \link{melt} to the ".data" before plotting. +\item{.melt}{If TRUE then apply \link[reshape2:melt]{reshape2::melt} to the ".data" before plotting. In this case ".data" is supposed to be a data frame with the first character column reserved for names of genes and other numeric columns reserved to counts or frequencies of genes. Each numeric column should be associated with a specific repertoire sample.} @@ -69,6 +69,8 @@ Each numeric column should be associated with a specific repertoire sample.} A ggplot2 object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualisation of distributions using ggplot2-based boxplots. } \examples{ diff --git a/man/vis_circos.Rd b/man/vis_circos.Rd index fb7d0a9c..590fa615 100644 --- a/man/vis_circos.Rd +++ b/man/vis_circos.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_circos} \alias{vis_circos} \title{Visualisation of matrices using circos plots} @@ -11,13 +11,15 @@ vis_circos(.data, .title = NULL, ...) \item{.title}{The The text for the title of the plot.} -\item{...}{Other arguments passed to \link{chordDiagram} from the 'circlize' package.} +\item{...}{Other arguments passed to \link[circlize:chordDiagram]{circlize::chordDiagram} from the 'circlize' package.} } \value{ A circlize object. } \description{ -Visualise matrices with the \link{chordDiagram} function +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +Visualise matrices with the \link[circlize:chordDiagram]{circlize::chordDiagram} function from the circlize package. } \examples{ diff --git a/man/vis_heatmap.Rd b/man/vis_heatmap.Rd index f121e015..412becb5 100644 --- a/man/vis_heatmap.Rd +++ b/man/vis_heatmap.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_heatmap} \alias{vis_heatmap} \title{Visualisation of matrices and data frames using ggplo2-based heatmaps} @@ -57,6 +57,8 @@ just plot coloured cells instead.} A ggplot2 object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Fast and easy visualisations of matrices or data frames with functions based on the ggplot2 package. } diff --git a/man/vis_heatmap2.Rd b/man/vis_heatmap2.Rd index e1bd9c5d..87fa2055 100644 --- a/man/vis_heatmap2.Rd +++ b/man/vis_heatmap2.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_heatmap2} \alias{vis_heatmap2} \title{Visualisation of matrices using pheatmap-based heatmaps} @@ -22,18 +22,20 @@ such as age, serostatus or hla.} \item{.by}{Set NA if you want to plot samples without grouping.} -\item{.title}{The text for the plot's title (same as the "main" argument in \link[pheatmap]{pheatmap}).} +\item{.title}{The text for the plot's title (same as the "main" argument in \link[pheatmap:pheatmap]{pheatmap}).} -\item{.color}{A vector specifying the colors (same as the "color" argument in \link[pheatmap]{pheatmap}). +\item{.color}{A vector specifying the colors (same as the "color" argument in \link[pheatmap:pheatmap]{pheatmap}). Pass NA to use the default pheatmap colors.} -\item{...}{Other arguments for the \link[pheatmap]{pheatmap} function.} +\item{...}{Other arguments for the \link[pheatmap:pheatmap]{pheatmap} function.} } \value{ A pheatmap object. } \description{ -Visualise matrices with the functions based on the \link[pheatmap]{pheatmap} +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +Visualise matrices with the functions based on the \link[pheatmap:pheatmap]{pheatmap} package with minimum amount of arguments. } \examples{ diff --git a/man/vis_hist.Rd b/man/vis_hist.Rd index b15cb753..900d95fe 100644 --- a/man/vis_hist.Rd +++ b/man/vis_hist.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_hist} \alias{vis_hist} \title{Visualisation of distributions using histograms} @@ -52,7 +52,7 @@ to automatically detect the optimal number of columns.} \item{.labs}{A character vector of length two with names for x-axis and y-axis, respectively.} -\item{.melt}{If TRUE then apply \link{melt} to the ".data" before plotting. +\item{.melt}{If TRUE then apply \link[reshape2:melt]{reshape2::melt} to the ".data" before plotting. In this case ".data" is supposed to be a data frame with the first character column reserved for names of genes and other numeric columns reserved to counts or frequencies of genes. Each numeric column should be associated with a specific repertoire sample.} @@ -68,16 +68,18 @@ If NA automatically detects the best way to display legend.} A ggplot2 object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualisation of distributions using ggplot2-based histograms. } \details{ If data is grouped, then statistical tests for comparing means of groups will be performed, unless \code{.test = FALSE} is supplied. In case there are only two groups, the Wilcoxon rank sum test (https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test) is performed -(R function \code{\link{wilcox.test}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. -In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal%E2%80%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link{kruskal.test}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. +(R function \code{\link[=wilcox.test]{wilcox.test()}} with an argument \code{exact = FALSE}) for testing if there is a difference in mean rank values between two groups. +In case there more than two groups, the Kruskal-Wallis test (https://en.wikipedia.org/wiki/Kruskal\%E2\%80\%93Wallis_one-way_analysis_of_variance) is performed (R function \code{\link[=kruskal.test]{kruskal.test()}}), that is equivalent to ANOVA for ranks and it tests whether samples from different groups originated from the same distribution. A significant Kruskal-Wallis test indicates that at least one sample stochastically dominates one other sample. Adjusted for multiple comparisons P-values are plotted on the top of groups. -P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm%E2%80%93Bonferroni_method) (also known as Holm-Bonferroni correction). +P-value adjusting is done using the Holm method (https://en.wikipedia.org/wiki/Holm\%E2\%80\%93Bonferroni_method) (also known as Holm-Bonferroni correction). You can execute the command \code{?p.adjust} in the R console to see more. } \examples{ diff --git a/man/vis_immunr_kmer_profile_main.Rd b/man/vis_immunr_kmer_profile_main.Rd index ab78d593..8362f4f4 100644 --- a/man/vis_immunr_kmer_profile_main.Rd +++ b/man/vis_immunr_kmer_profile_main.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_immunr_kmer_profile_main} \alias{vis_immunr_kmer_profile_main} \title{Visualise kmer profiles} @@ -10,10 +10,10 @@ vis_immunr_kmer_profile_main(.data, .plot, ...) \item{.data}{Kmer data, an output from \link{kmer_profile}.} \item{.plot}{String specifying the plot type: - -- "seqlogo" for traditional sequence logo plots using \link{vis_seqlogo}; - -- "textlogo" for modified approach to sequence logo plots via text labels using \link{vis_textlogo};} +\itemize{ +\item "seqlogo" for traditional sequence logo plots using \link{vis_seqlogo}; +\item "textlogo" for modified approach to sequence logo plots via text labels using \link{vis_textlogo}; +}} \item{...}{Other arguments passed to \link{vis_textlogo} or \link{vis_seqlogo}, depending on the ".plot" argument.} @@ -22,7 +22,7 @@ on the ".plot" argument.} A ggplot2 object. } \description{ -Visualise kmer profiles +#' \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ data(immdata) diff --git a/man/vis_public_clonotypes.Rd b/man/vis_public_clonotypes.Rd index 1b0e1a4d..f774d4c5 100644 --- a/man/vis_public_clonotypes.Rd +++ b/man/vis_public_clonotypes.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_public_clonotypes} \alias{vis_public_clonotypes} \title{Visualisation of public clonotypes} @@ -48,6 +48,8 @@ for the R adjusted coefficient.} A ggplot2 object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualise correlation of public clonotype frequencies in pairs of repertoires. } \examples{ diff --git a/man/vis_public_frequencies.Rd b/man/vis_public_frequencies.Rd index 7701a5f3..8cbdbc01 100644 --- a/man/vis_public_frequencies.Rd +++ b/man/vis_public_frequencies.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_public_frequencies} \alias{vis_public_frequencies} \title{Public repertoire visualisation} @@ -34,6 +34,8 @@ such as age, serostatus or hla.} A ggplot2 object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Visualise public clonotype frequencies. } \examples{ diff --git a/man/vis_textlogo.Rd b/man/vis_textlogo.Rd index 4fd069a7..1bc76907 100644 --- a/man/vis_textlogo.Rd +++ b/man/vis_textlogo.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vis.R +% Please edit documentation in R/v0_vis.R \name{vis_textlogo} \alias{vis_textlogo} \alias{vis_seqlogo} @@ -20,18 +20,20 @@ to plot points on the straight vertical line for each position.} \item{...}{Not used here.} -\item{.scheme}{Character. An argumentt passed to \link{geom_logo} specifying how to colour symbols.} +\item{.scheme}{Character. An argument passed to geom_logo from ggseqlogo package specifying how to colour symbols.} } \value{ A ggplot2 object. } \description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + Plot sequence logo plots for visualising of amino acid motif sequences / profiles. -`vis_textlogo` plots sequences in a text format - each letter has the same height. Useful when there +\code{vis_textlogo} plots sequences in a text format - each letter has the same height. Useful when there are no big differences between occurences of amino acids in the motif. -`vis_seqlogo` is a traditional sequence logo plots. Useful when there are one or two amino acids +\code{vis_seqlogo} is a traditional sequence logo plots. Useful when there are one or two amino acids with clear differences in their occurrences. } \examples{ diff --git a/tests/testthat/helper-preload.R b/tests/testthat/helper-preload.R deleted file mode 100644 index 7430608d..00000000 --- a/tests/testthat/helper-preload.R +++ /dev/null @@ -1,40 +0,0 @@ -apply_DF_DT <- function(df_data, dt_data, .fun, ...) { - res1 <- .fun(df_data, ...) - res2 <- .fun(dt_data, ...) - list(df = res1, dt = res2) -} - -vis_results <- function(res_list, ...) { - p_df <- vis(res_list$df, ...) - p_dt <- vis(res_list$dt, ...) - list(df = p_df, dt = p_dt) -} - -check_for_mutation <- function(.frame, .table) { - expect_equal(lapply(.frame, as.data.table), .table) -} - -# add pretfix -ap <- function(.name, .prefix) { - paste0(.prefix, .name) -} - -add_mock_sample <- function(.immdata, .sample_name, .meta = list(), .empty = FALSE) { - if (.empty) { - # copy only column headers - .immdata$data[[.sample_name]] <- .immdata$data[[1]][0, ] - } else { - # copy dataframe of 1st sample to the new sample - .immdata$data[[.sample_name]] <- .immdata$data[[1]] - } - - # .meta must be a named list containing metadata row (full or partial) for the sample - .meta[["Sample"]] <- .sample_name - .immdata$meta %<>% bind_rows(as.data.frame(.meta)) - - return(.immdata) -} - -data(immdata) -frame_data <- immdata$data -table_data <- lapply(frame_data, as.data.table) diff --git a/tests/testthat/test-align-lineage.R b/tests/testthat/test-align-lineage.R deleted file mode 100644 index 3b111f53..00000000 --- a/tests/testthat/test-align-lineage.R +++ /dev/null @@ -1,100 +0,0 @@ -data(bcrdata) -test_bcr_data <- bcrdata$data %>% top(1000) -test_input <- test_bcr_data %>% - seqCluster(seqDist(test_bcr_data), .fixed_threshold = 3) %>% - repGermline(.threads = 1) %>% - suppressWarnings() - -positive_test_cases <- list( - "Not empty result" = list( - args = list( - .data = test_input, - .min_lineage_sequences = 2, - .prepare_threads = 1, - .align_threads = 1 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result[["full_clones"]]) > 0, TRUE) - } - ), - "Multiple threads" = list( - args = list( - .data = test_input, - .min_lineage_sequences = 2 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result[["full_clones"]]) > 0, TRUE) - } - ), - "Dataframe only" = list( - args = list( - .data = test_input[["full_clones"]], - .min_lineage_sequences = 2, - .prepare_threads = 1, - .align_threads = 1 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result) > 0, TRUE) - } - ) -) - -for (i in seq_along(positive_test_cases)) { - # Arrange - test_name <- names(positive_test_cases)[i] - args <- positive_test_cases[[i]][["args"]] - assert_function <- positive_test_cases[[i]][["assert_function"]] - - # Act - result <- suppressWarnings(do.call(repAlignLineage, args)) - - # Assert - test_that( - test_name, - assert_function(result) - ) -} - -negative_test_cases <- list( - "List of lists" = list( - args = list( - .data = bcrdata - ) - ), - "Missing columns" = list( - args = list( - .data = test_bcr_data[["full_clones"]], - .prepare_threads = 1, - .align_threads = 1 - ) - ), - "Missing Cluster column" = list( - args = list( - .data = subset(test_input[["full_clones"]], select = -c(get("Cluster"))), - .prepare_threads = 1, - .align_threads = 1 - ) - ), - "Missing Germline.sequence column" = list( - args = list( - .data = subset(test_input[["full_clones"]], select = -c(get("Germline.sequence"))), - .prepare_threads = 1, - .align_threads = 1 - ) - ) -) - -for (i in seq_along(negative_test_cases)) { - # Arrange - test_name <- names(negative_test_cases)[i] - args <- negative_test_cases[[i]][["args"]] - - # Act, Assert - test_that( - test_name, - expect_error(suppressWarnings(do.call(repAlignLineage, args))) - ) -} diff --git a/tests/testthat/test-clonal-family.R b/tests/testthat/test-clonal-family.R deleted file mode 100644 index 8c09a65e..00000000 --- a/tests/testthat/test-clonal-family.R +++ /dev/null @@ -1,115 +0,0 @@ -data(bcrdata) -test_bcr_data <- bcrdata$data %>% top(1000) -test_input <- test_bcr_data %>% - seqCluster(seqDist(test_bcr_data), .fixed_threshold = 3) %>% - repGermline(.threads = 1) %>% - repAlignLineage(.min_lineage_sequences = 2, .prepare_threads = 1, .align_threads = 1) %>% - suppressWarnings() - -positive_test_cases <- list( - "Not empty result" = list( - args = list( - .data = test_input, - .threads = 1 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result[["full_clones"]]) > 0, TRUE) - } - ), - "Multiple threads" = list( - args = list( - .data = test_input, - .threads = 8 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result[["full_clones"]]) > 0, TRUE) - } - ), - "Dataframe only" = list( - args = list( - .data = test_input[["full_clones"]], - .threads = 1 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result) > 0, TRUE) - } - ), - "Vis groups" = list( - args = list( - .data = test_input, - .vis_groups = { - clone_ids <- test_input[["full_clones"]] %>% - unnest("Sequences") %>% - extract2("Clone.ID") - list( - Group1 = clone_ids[1], - Group2 = clone_ids[3], - Group3 = list(clone_ids[5], clone_ids[2]), - Group4 = c(clone_ids[7], clone_ids[4]) - ) - }, - .threads = 1 - ), - assert_function = function(result) { - types <- result[["full_clones"]] %>% - unnest("TreeStats") %>% - extract2("Type") - # check that correct number of clonotypes is assigned to each group - expect_equal(tabulate(match(types, "Group1")), 1) - expect_equal(tabulate(match(types, "Group2")), 1) - expect_equal(tabulate(match(types, "Group3")), 2) - expect_equal(tabulate(match(types, "Group4")), 2) - } - ) -) - -for (i in seq_along(positive_test_cases)) { - # Arrange - test_name <- names(positive_test_cases)[i] - args <- positive_test_cases[[i]][["args"]] - assert_function <- positive_test_cases[[i]][["assert_function"]] - - # Act - result <- do.call(repClonalFamily, args) - - # Assert - test_that( - test_name, - assert_function(result) - ) -} - -negative_test_cases <- list( - "List of lists" = list( - args = list( - .data = bcrdata - ) - ), - "Missing columns" = list( - args = list( - .data = test_bcr_data[["full_clones"]], - .threads = 1 - ) - ), - "Missing Alignment column" = list( - args = list( - .data = subset(test_input[["full_clones"]], select = -c(get("Alignment"))), - .threads = 1 - ) - ) -) - -for (i in seq_along(negative_test_cases)) { - # Arrange - test_name <- names(negative_test_cases)[i] - args <- negative_test_cases[[i]][["args"]] - - # Act, Assert - test_that( - test_name, - expect_error(do.call(repClonalFamily, args)) - ) -} diff --git a/tests/testthat/test-clonality.R b/tests/testthat/test-clonality.R deleted file mode 100644 index cf200984..00000000 --- a/tests/testthat/test-clonality.R +++ /dev/null @@ -1,14 +0,0 @@ -for (method in c("clonal.prop", "homeo", "top", "tail")) { - test_name <- paste0("method:", method) - - compute_res <- apply_DF_DT(frame_data, table_data, - repClonality, - .method = method - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) -} diff --git a/tests/testthat/test-distance.R b/tests/testthat/test-distance.R deleted file mode 100644 index 0ebf4eaa..00000000 --- a/tests/testthat/test-distance.R +++ /dev/null @@ -1,72 +0,0 @@ -data(immdata) -library(purrr) -short_immdata <- map(immdata$data, ~ .x %>% head(1000)) # smaller sample size saves time in computations - -f <- function(x, y) { - res <- matrix(nrow = length(x), ncol = length(y)) - for (i in seq_along(x)) { - res[i, ] <- abs(nchar(x[i]) - nchar(y)) - } - dimnames(res) <- list(x, y) - return(as.dist(res)) -} - -# Arrange -positive_test_cases <- list( - "Changing method" = list( - args = list( - .data = short_immdata[1], - .method = "lv" - ), - result = c(0, 6, 6, 0) - ), - "Changing column" = list( - args = list( - .data = short_immdata[1], - .col = "CDR3.aa", - .method = "lv" - ), - result = c(0, 6, 6, 0) - ), - "Custom_func" = list(args = list(.data = short_immdata[1], .method = f, .group_by_seqLength = FALSE), result = c(0, 3, 3, 0)), - "Group_by changing" = list(args = list(.data = short_immdata[1], .group_by = "V.name"), result = c(0, 21, 19, 18, 13, 21, 0, 18, 23, 19, 19, 18, 0, 16, 15, 18, 23, 16, 0, 15, 13, 19, 15, 15, 0)) -) - -negative_test_cases <- list( - "Immdata test" = list( - args = list( - .data = immdata - ) - ), - "Wrong col" = list( - args = list( - .data = short_immdata, - .col = "aa" - ) - ), - "Wrong method" = list( - args = list( - .data = short_immdata, - .method = "ddddd" - ), - "Wrong group_by" = list( - args = list( - .data = short_immdata, - .group_by = "ddddd" - ) - ) - ) -) - -# Act -args <- map(positive_test_cases, "args") -results <- map(positive_test_cases, "result") -positive_act_result <- map(args, ~ do.call(seqDist, .x)[[1]][10]) %>% - map(1) %>% - map(., ~ as.matrix(.x) %>% as.numeric()) -positive_test_values <- list(names(positive_test_cases), positive_act_result, results) -negative_args <- map(negative_test_cases, "args") -# Assert -pmap(positive_test_values, ~ test_that(..1, expect_equal(..2, ..3))) -## for negative tests act can be done only with assert -map2(names(negative_test_cases), negative_args, ~ test_that(.x, expect_error(do.call(seqDist, .y)))) diff --git a/tests/testthat/test-diversity.R b/tests/testthat/test-diversity.R deleted file mode 100644 index 55c7cfc3..00000000 --- a/tests/testthat/test-diversity.R +++ /dev/null @@ -1,48 +0,0 @@ -for (column in c("nt", "aa", "nt+v", "aa+v", "aa+v+j")) { - for (method in c("chao1", "hill", "div", "gini.simp", "inv.simp", "gini", "raref", "dxx", "d50")) { - if (method == "raref") { - for (norm_val in c(TRUE, FALSE)) { - test_name <- paste0("method:", method, ":", column, ".norm:", norm_val) - - compute_res <- apply_DF_DT(frame_data, table_data, - repDiversity, - .method = method, .col = column, .verbose = F, .norm = norm_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } - } else if (method == "dxx") { - for (perc_val in c(10, 25, 75)) { - test_name <- paste0("method:", method, ":", column, ".perc:", perc_val) - - compute_res <- apply_DF_DT(frame_data, table_data, - repDiversity, - .method = method, .col = column, .verbose = F, .perc = perc_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } - } else { - test_name <- paste0("method:", method, ":", column) - - compute_res <- apply_DF_DT(frame_data, table_data, - repDiversity, - .method = method, .col = column, .verbose = F - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } - } -} diff --git a/tests/testthat/test-dynamics.R b/tests/testthat/test-dynamics.R deleted file mode 100644 index 8fe12040..00000000 --- a/tests/testthat/test-dynamics.R +++ /dev/null @@ -1,71 +0,0 @@ -#' -#' -#' -#' trackClonotypes <- function (.data, .which = list(1, 15), .col = "aa", .norm = T) { -#' -#' -#' tc = trackClonotypes(immdata$data, list(1, 10), .col = "aa") -#' tc = trackClonotypes(immdata$data, list("MS1", 20), .col = "nt+v") -#' -#' tc = trackClonotypes(immdata$data, c("CASRGLITDTQYF", "CSASRGSPNEQYF"), .col = "aa") -#' -#' target = immdata$data[[1]] %>% select(CDR3.aa, V.name) %>% head(10) -#' tc = trackClonotypes(immdata$data, target) - - -for (norm_val in c(TRUE, FALSE)) { - for (method in list(list(1, 10), list(names(frame_data)[1], 20))) { - for (column in c("nt", "aa", "nt+v", "aa+v", "nt+j", "aa+j", "aa+v+j")) { - test_name <- paste0("method:1.norm:", norm_val, ".column:", column) - - compute_res <- apply_DF_DT(frame_data, table_data, - trackClonotypes, - .which = method, .col = column, .norm = norm_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - } - } - - target <- c("CASSLEETQYF", "CASSDSSGGANEQFF", "CASSLQETQYF", "CASSLDRETQYF", "CASSPGGGNQPQHF") - column <- "aa" - test_name <- paste0("methid:2.norm:", norm_val, ".column:", column) - - compute_res <- apply_DF_DT(frame_data, table_data, - trackClonotypes, - .which = target, .col = column, .norm = norm_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - method_list <- list() - method_list[["nt+v"]] <- immdata$data[[1]] %>% - select(CDR3.nt, V.name) %>% - head(10) - method_list[["aa+v"]] <- immdata$data[[1]] %>% - select(CDR3.aa, V.name) %>% - head(15) - method_list[["nt+v+j"]] <- immdata$data[[1]] %>% - select(CDR3.nt, V.name, J.name) %>% - head(10) - method_list[["aa"]] <- immdata$data[[1]] %>% - select(CDR3.aa) %>% - head(10) - method_list[["nt"]] <- immdata$data[[1]] %>% - select(CDR3.nt) %>% - head(10) - - for (method_name in names(method_list)) { - test_name <- paste0("methid:3.norm:", norm_val, ".which:", method_name) - - compute_res <- apply_DF_DT(frame_data, table_data, - trackClonotypes, - .which = method_list[[method_name]], .col = column, .norm = norm_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - } -} diff --git a/tests/testthat/test-explore.R b/tests/testthat/test-explore.R deleted file mode 100644 index c4f813d0..00000000 --- a/tests/testthat/test-explore.R +++ /dev/null @@ -1,35 +0,0 @@ -for (column in c("nt", "aa", "nt+v", "aa+v", "aa+v+j")) { - for (method in c("volume", "count", "len", "clones")) { - for (coding_val in c(TRUE, FALSE)) { - if (method == "len") { - if (column %in% c("nt", "aa")) { - test_name <- paste0("method:", method, ":", column, ".coding:", coding_val) - - compute_res <- apply_DF_DT(frame_data, table_data, - repExplore, - .method = method, .col = column, .coding = coding_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } - } else { - test_name <- paste0("method:", method, ":", column, ".coding:", coding_val) - - compute_res <- apply_DF_DT(frame_data, table_data, - repExplore, - .method = method, .col = column, .coding = coding_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } - } - } -} diff --git a/tests/testthat/test-filter.R b/tests/testthat/test-filter.R deleted file mode 100644 index 01f48ed1..00000000 --- a/tests/testthat/test-filter.R +++ /dev/null @@ -1,299 +0,0 @@ -test_cases <- list() - -data <- immdata$data -meta <- immdata$meta -original_samples_count <- nrow(meta) - -prepare_immdata <- function() { - return(list(data = data, meta = meta)) -} - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - prepare_immdata() %>% - add_mock_sample("S1", list(Status = "N")) - }, - method = "by.meta", query = list(Status = include("N")), - expected_samples = 1 -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - prepare_immdata() %>% - add_mock_sample("S1", list(Lane = "D")) - }, - method = "by.meta", query = list(Lane = exclude("D")), - expected_samples = original_samples_count -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - prepare_immdata() %>% - add_mock_sample("S1", list(Age = 1)) %>% - add_mock_sample("S2", list(Age = 2)) - }, - method = "by.meta", query = list(Age = lessthan(5)), - expected_samples = 2 -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - prepare_immdata() %>% - add_mock_sample("S1", list(Age = 95)) %>% - add_mock_sample("S2", list(Age = 99)) - }, - method = "by.meta", query = list(Age = interval(95, 100)), - expected_samples = 2 -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - prepare_immdata() %>% - add_mock_sample("S1", list(Age = 100)) - }, - method = "by.meta", query = list(Age = interval(95, 100)), - expected_samples = 0, - expect_warnings = TRUE -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - prepare_immdata() %>% - add_mock_sample("S1", list(Lane = "D")) %>% - add_mock_sample("S2", list(Lane = "E")) - }, - method = "by.meta", query = list(Lane = include("D", "E")), - expected_samples = 2 -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - prepare_immdata() %>% - add_mock_sample("S1", list(Lane = "D")) %>% - add_mock_sample("S2", list(Lane = "E")) - }, - method = "by.meta", query = list(Lane = exclude("D", "E")), - expected_samples = original_samples_count -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - prepare_immdata() %>% - add_mock_sample("S1", list(Lane = "D", Age = 95)) %>% - add_mock_sample("S2", list(Lane = "E", Age = 96)) - }, - method = "by.meta", query = list(Lane = include("D", "E"), Age = morethan(95)), - expected_samples = 1 -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - immdata <- prepare_immdata() %>% - add_mock_sample("S1") - immdata$data[["S1"]] %<>% rbind(immdata$data[["S1"]][rep(1, 10000), ]) - return(immdata) - }, - method = "by.repertoire", query = list(n_clonotypes = morethan(10000)), - expected_samples = 1 -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - immdata <- prepare_immdata() - immdata %<>% add_mock_sample("S1") - immdata$data[["S1"]] <- immdata$data[["S1"]][1, ] - immdata$data[["S1"]][["Clones"]] <- 50 - immdata %<>% add_mock_sample("S2") - immdata$data[["S2"]] <- immdata$data[["S2"]][1:2, ] - immdata$data[["S2"]][1, ][["Clones"]] <- 50 - immdata$data[["S2"]][2, ][["Clones"]] <- 50 - return(immdata) - }, - method = "by.repertoire", query = list(n_clones = lessthan(100)), - expected_samples = 1 -) - -# repeat the last 2 test cases, but abbreviate method as "by.rep" -for (i in 1:2) { - test_cases[[length(test_cases) + 1]] <- test_cases[[length(test_cases) - 1]] - test_cases[[length(test_cases)]][["method"]] <- "by.rep" -} - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - immdata <- prepare_immdata() %>% - add_mock_sample("S1", .empty = TRUE) - immdata$data[["S1"]] %<>% - bind_rows(as.data.frame(list(CDR3.aa = "partial"))) %>% - bind_rows(as.data.frame(list(CDR3.aa = "out_of_frame"))) %>% - bind_rows(as.data.frame(list(CDR3.aa = "other"))) - return(immdata) - }, - method = "by.clonotype", query = list(CDR3.aa = exclude("partial", "out_of_frame")), - expected_samples = original_samples_count + 1, - expected_sample_rows = list(S1 = 1) -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - immdata <- prepare_immdata() %>% - add_mock_sample("S1", .empty = TRUE) - immdata$data[["S1"]] %<>% - bind_rows(as.data.frame(list(Clones = 1000))) %>% - bind_rows(as.data.frame(list(Clones = 1500))) %>% - bind_rows(as.data.frame(list(Clones = 2000))) - return(immdata) - }, - method = "by.clonotype", query = list(Clones = interval(1000, 2000)), - expected_samples = 1, - expected_sample_rows = list(S1 = 2), - expect_warnings = TRUE -) - -mock_genes <- function() { - immdata <- prepare_immdata() %>% - add_mock_sample("S1", .empty = TRUE) - # delete all other samples - immdata$data <- immdata$data[names(immdata$data) == "S1"] - immdata$meta %<>% filter(Sample == "S1") - - immdata$data[["S1"]] %<>% - bind_rows(as.data.frame(list(V.name = "TRBV1"))) %>% - bind_rows(as.data.frame(list(V.name = "TRAV1"))) %>% - bind_rows(as.data.frame(list(V.name = "TRAV2"))) %>% - bind_rows(as.data.frame(list(V.name = "TRAV11"))) - return(immdata) -} - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = mock_genes, - method = "by.clonotype", query = list(V.name = exclude("TRBV1", "TRAV1")), - expected_samples = 1, - expected_sample_rows = list(S1 = 2) -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = mock_genes, - method = "by.clonotype", query = list(V.name = exclude("TRBV1", "TRAV1")), match = "exact", - expected_samples = 1, - expected_sample_rows = list(S1 = 2) -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = mock_genes, - method = "by.clonotype", query = list(V.name = exclude("TRBV1", "TRAV1")), match = "startswith", - expected_samples = 1, - expected_sample_rows = list(S1 = 1) -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = mock_genes, - method = "by.clonotype", query = list(V.name = include("TRBV1", "TRAV1")), match = "startswith", - expected_samples = 1, - expected_sample_rows = list(S1 = 3) -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = mock_genes, - method = "by.clonotype", query = list(CDR3.aa = exclude("DUMMY")), match = "startswith", - expected_samples = mock_genes() %>% .$data %>% length(), - expected_sample_rows = list(S1 = 4) -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = mock_genes, - method = "by.clonotype", query = list(V.name = exclude("V1")), match = "substring", - expected_samples = 1, - expected_sample_rows = list(S1 = 1) -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = mock_genes, - method = "by.clonotype", query = list(V.name = include("V1")), match = "substring", - expected_samples = 1, - expected_sample_rows = list(S1 = 3) -) - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = mock_genes, - method = "by.clonotype", query = list(CDR3.aa = exclude("DUMMY")), match = "substring", - expected_samples = mock_genes() %>% .$data %>% length(), - expected_sample_rows = list(S1 = 4) -) - -# repeat the last 10 test cases, but abbreviate method as "by.cl" -for (i in 1:10) { - test_cases[[length(test_cases) + 1]] <- test_cases[[length(test_cases) - 9]] - test_cases[[length(test_cases)]][["method"]] <- "by.cl" -} - -test_cases[[length(test_cases) + 1]] <- list( - data_factory = function() { - immdata <- prepare_immdata() %>% - add_mock_sample("S1", .empty = TRUE) - immdata$data <- immdata$data[names(immdata$data) == "S1"] - immdata$meta %<>% filter(Sample == "S1") - immdata$data[["S1"]] %<>% - bind_rows(as.data.frame(list(V.name = "TRBV1", J.name = "TRAJ1"))) %>% - bind_rows(as.data.frame(list(V.name = "TRAV1", J.name = "TRAJ11"))) %>% - bind_rows(as.data.frame(list(V.name = "TRAV2", J.name = "TRAJ1"))) %>% - bind_rows(as.data.frame(list(V.name = "TRAV11", J.name = "TRBJ2"))) - return(immdata) - }, - method = "by.clonotype", - query = list(V.name = include("AV1"), J.name = include("AJ")), - match = "substring", - expected_samples = 1, - expected_sample_rows = list(S1 = 1) -) - -for (i in seq_along(test_cases)) { - # Arrange - data_factory <- test_cases[[i]][["data_factory"]] - method <- test_cases[[i]][["method"]] - query <- test_cases[[i]][["query"]] - match <- test_cases[[i]][["match"]] - expected_samples <- test_cases[[i]][["expected_samples"]] - expected_sample_rows <- test_cases[[i]][["expected_sample_rows"]] - # expected_sample_rows is named list, contains sample names and expected rows; - # if not specified, don't check sample rows - if (is.null(expected_sample_rows)) { - expected_sample_rows <- list() - } - expect_warnings <- test_cases[[i]][["expect_warnings"]] - if (is.null(expect_warnings)) { - options(warn = 0) - } else { - options(warn = -1) - } - - test_name <- paste0("method:", method, ".case:", i) - immdata <- data_factory() - frame_with_meta <- immdata - table_with_meta <- list(data = lapply(immdata$data, as.data.table), meta = immdata$meta) - - # Act - if (is.null(match)) { - compute_res <- apply_DF_DT(frame_with_meta, table_with_meta, - repFilter, - .method = method, .query = query - ) - } else { - compute_res <- apply_DF_DT(frame_with_meta, table_with_meta, - repFilter, - .method = method, .query = query, .match = match - ) - } - - # Assert - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]]$data %>% length(), expected_samples) - expect_equal(compute_res[[1]]$meta %>% nrow(), expected_samples) - for (j in seq_along(expected_sample_rows)) { - sample_name <- names(expected_sample_rows)[[j]] - expected_rows <- expected_sample_rows[[j]] - expect_equal(compute_res[[1]]$data[[sample_name]] %>% nrow(), expected_rows) - } - expect_equal(lapply(compute_res[[1]]$data, as.data.table), compute_res[[2]]$data) - }) -} diff --git a/tests/testthat/test-geneusage.R b/tests/testthat/test-geneusage.R deleted file mode 100644 index 1ef289cc..00000000 --- a/tests/testthat/test-geneusage.R +++ /dev/null @@ -1,17 +0,0 @@ -for (quant in c(NA, "count")) { - for (type in c("segment", "allele", "family")) { - for (ambig in c("inc", "exc", "maj")) { - for (norm_val in c(TRUE, FALSE)) { - test_name <- paste0("quant:", quant, "_type:", type, "_ambig:", ambig, "_norm:", norm_val) - - compute_res <- apply_DF_DT(frame_data, table_data, - geneUsage, - .quant = quant, .ambig = ambig, .type = type, .norm = norm_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - } - } - } -} diff --git a/tests/testthat/test-germline.R b/tests/testthat/test-germline.R deleted file mode 100644 index 124ddd62..00000000 --- a/tests/testthat/test-germline.R +++ /dev/null @@ -1,76 +0,0 @@ -data(bcrdata) -test_bcr_data <- bcrdata$data %>% top(1000) - -positive_test_cases <- list( - "Not empty result" = list( - args = list( - .data = test_bcr_data, - .threads = 1 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result[["full_clones"]]) > 0, TRUE) - } - ), - "Multiple threads" = list( - args = list( - .data = test_bcr_data - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result[["full_clones"]]) > 0, TRUE) - } - ), - "Dataframe only" = list( - args = list( - .data = test_bcr_data[["full_clones"]], - .threads = 1 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result) > 0, TRUE) - } - ) -) - -for (i in seq_along(positive_test_cases)) { - # Arrange - test_name <- names(positive_test_cases)[i] - args <- positive_test_cases[[i]][["args"]] - assert_function <- positive_test_cases[[i]][["assert_function"]] - - # Act - result <- suppressWarnings(do.call(repGermline, args)) - - # Assert - test_that( - test_name, - assert_function(result) - ) -} - -negative_test_cases <- list( - "List of lists" = list( - args = list( - .data = bcrdata - ) - ), - "Missing column" = list( - args = list( - .data = subset(test_bcr_data[["full_clones"]], select = -c(get("FR1.nt"))), - .threads = 1 - ) - ) -) - -for (i in seq_along(negative_test_cases)) { - # Arrange - test_name <- names(negative_test_cases)[i] - args <- negative_test_cases[[i]][["args"]] - - # Act, Assert - test_that( - test_name, - expect_error(suppressWarnings(do.call(repGermline, args))) - ) -} diff --git a/tests/testthat/test-kmers.R b/tests/testthat/test-kmers.R deleted file mode 100644 index 3c32fd19..00000000 --- a/tests/testthat/test-kmers.R +++ /dev/null @@ -1,36 +0,0 @@ -for (coding_val in c(TRUE, FALSE)) { - for (k_size in c(1, 3, 5, 10)) { - for (column in c("nt", "aa")) { - test_name <- paste0("kmer:", k_size, ":", column, ".coding:", coding_val) - - compute_res <- apply_DF_DT(frame_data[[1]], table_data[[1]], - getKmers, - .k = k_size, .col = column, .coding = coding_val - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - - if (column == "aa") { - for (method in c("freq", "prob", "wei", "self")) { - for (remove_stop in c(TRUE, FALSE)) { - test_name <- paste0("kmer:", k_size, ".method:", method, ".stop:", remove_stop, ".coding:", coding_val) - - profile_res1 <- kmer_profile(compute_res[[1]], .method = method, .remove.stop = remove_stop) - profile_res2 <- kmer_profile(compute_res[[2]], .method = method, .remove.stop = remove_stop) - - test_that(ap(test_name, "compute_"), { - expect_equal(profile_res1, profile_res2) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } - } - } - } - } -} diff --git a/tests/testthat/test-overlap.R b/tests/testthat/test-overlap.R deleted file mode 100644 index a6619953..00000000 --- a/tests/testthat/test-overlap.R +++ /dev/null @@ -1,16 +0,0 @@ -for (column in c("nt", "aa", "nt+v", "aa+v", "aa+v+j")) { - for (method in c("public", "overlap", "jaccard", "tversky", "cosine", "morisita", "inc+public", "inc+jaccard", "inc+morisita")) { - test_name <- paste0("method:", method, ":", column) - - compute_res <- apply_DF_DT(frame_data, table_data, - repOverlap, - .method = method, .col = column, .verbose = F, .verbose.inc = F - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } -} diff --git a/tests/testthat/test-pubrep.R b/tests/testthat/test-pubrep.R deleted file mode 100644 index e2b3bab6..00000000 --- a/tests/testthat/test-pubrep.R +++ /dev/null @@ -1,22 +0,0 @@ -for (column in c("nt", "aa", "nt+v", "aa+v", "nt+j", "aa+j", "aa+v+j")) { - for (quant in c("count", "prop")) { - for (coding_val in c(TRUE, FALSE)) { - for (min_samples in c(1, 3)) { - for (max_samples in c(5, NA)) { - test_name <- paste0("column:", column, ".quant:", quant, ".coding:", coding_val, ".min:", min_samples, ".max:", max_samples) - - compute_res <- apply_DF_DT(frame_data, table_data, - pubRep, - .col = column, .quant = quant, .coding = coding_val, .min.samples = min_samples, .max.samples = max_samples, .verbose = F - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } - } - } - } -} diff --git a/tests/testthat/test-seqCluster.R b/tests/testthat/test-seqCluster.R deleted file mode 100644 index ccdae7a6..00000000 --- a/tests/testthat/test-seqCluster.R +++ /dev/null @@ -1,48 +0,0 @@ -data(immdata) - -dist_test <- seqDist(immdata$data[1]) - - -# Arrange - -negative_test_cases <- list( - "Wrong data" = list( - args = list( - .data = immdata[1:2], - .dist = dist_test - ) - ), - "No matching col" = list( - args = list( - .data = immdata$data[[1]] %>% mutate("CDR3.nt" = NULL), - .dist = dist_test - ) - ), - "Wrong samples" = list( - args = list( - .data = immdata$data[3], - .dist = dist_test - ) - ), - "Multiple thresholds" = list( - args = list( - .data = immdata$data[1], - .dist = dist_test, - .fixed_threshold = 10, - .nt_similarity = 3 - ) - ), - "No thresholds" = list( - args = list( - .data = immdata$data[1], - .dist = dist_test, - .fixed_threshold = NULL - ) - ) -) - -negative_args <- map(negative_test_cases, "args") - -# Act, Assert - -map2(names(negative_test_cases), negative_args, ~ test_that(.x, expect_error(do.call(seqCluster, .y)))) diff --git a/tests/testthat/test-somatic-hypermutation.R b/tests/testthat/test-somatic-hypermutation.R deleted file mode 100644 index 74aac8f5..00000000 --- a/tests/testthat/test-somatic-hypermutation.R +++ /dev/null @@ -1,95 +0,0 @@ -data(bcrdata) -test_bcr_data <- bcrdata$data %>% top(1000) -test_input <- test_bcr_data %>% - seqCluster(seqDist(test_bcr_data), .fixed_threshold = 3) %>% - repGermline(.threads = 1) %>% - repAlignLineage(.min_lineage_sequences = 2, .prepare_threads = 1, .align_threads = 1) %>% - repClonalFamily(.threads = 1) %>% - suppressWarnings() - -positive_test_cases <- list( - "Not empty result" = list( - args = list( - .data = test_input, - .threads = 1 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result[["full_clones"]]) > 0, TRUE) - } - ), - "Multiple threads" = list( - args = list( - .data = test_input, - .threads = 8 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result[["full_clones"]]) > 0, TRUE) - } - ), - "Dataframe only" = list( - args = list( - .data = test_input[["full_clones"]], - .threads = 1 - ), - assert_function = function(result) { - expect_equal(immunarch:::has_no_data(result), FALSE) - expect_equal(nrow(result) > 0, TRUE) - } - ) -) - -for (i in seq_along(positive_test_cases)) { - # Arrange - test_name <- names(positive_test_cases)[i] - args <- positive_test_cases[[i]][["args"]] - assert_function <- positive_test_cases[[i]][["assert_function"]] - - # Act - result <- do.call(repSomaticHypermutation, args) - - # Assert - test_that( - test_name, - assert_function(result) - ) -} - -negative_test_cases <- list( - "List of lists" = list( - args = list( - .data = bcrdata - ) - ), - "Missing columns" = list( - args = list( - .data = test_bcr_data[["full_clones"]], - .threads = 1 - ) - ), - "Missing Sequences column" = list( - args = list( - .data = subset(test_input[["full_clones"]], select = -c(get("Sequences"))), - .threads = 1 - ) - ), - "Missing Germline.Input column" = list( - args = list( - .data = subset(test_input[["full_clones"]], select = -c(get("Germline.Input"))), - .threads = 1 - ) - ) -) - -for (i in seq_along(negative_test_cases)) { - # Arrange - test_name <- names(negative_test_cases)[i] - args <- negative_test_cases[[i]][["args"]] - - # Act, Assert - test_that( - test_name, - expect_error(do.call(repSomaticHypermutation, args)) - ) -} diff --git a/tests/testthat/test-spectr.R b/tests/testthat/test-spectr.R deleted file mode 100644 index ef41c108..00000000 --- a/tests/testthat/test-spectr.R +++ /dev/null @@ -1,16 +0,0 @@ -for (column in c("nt", "aa", "nt+v", "aa+v", "nt+j", "aa+j")) { - for (quant in c("id", "count")) { - test_name <- paste0("quant:", quant, ":", column) - - compute_res <- apply_DF_DT(frame_data[[1]], table_data[[1]], - spectratype, - .quant = quant, .col = column - ) - test_that(ap(test_name, "compute_"), { - expect_equal(compute_res[[1]], compute_res[[2]]) - }) - - # vis_res = vis_results(compute_res) - # test_that(ap(test_name, "vis_"), { expect_equal(vis_res[[1]], vis_res[[2]]) }) - } -} diff --git a/vignettes/.gitignore b/vignettes/.gitignore new file mode 100644 index 00000000..771f764f --- /dev/null +++ b/vignettes/.gitignore @@ -0,0 +1,5 @@ +*_files +drafts* + +/.quarto/ +**/*.quarto_ipynb diff --git a/vignettes/immunarch.Rmd b/vignettes/immunarch.Rmd new file mode 100644 index 00000000..4617b0f2 --- /dev/null +++ b/vignettes/immunarch.Rmd @@ -0,0 +1,234 @@ +--- +title: "immunarch" +output: html_document +--- + + + +# 🧬 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: + +- **Multi-modal immune profiling:** compute receptor- and repertoire-level statistics leveraging single-cell, spatial, immunogenicity or any other receptor annotations; + +- **Immunomics at scale:** work seamlessly with datasets that don't fit in memory; + +- **Immune biomarker discovery:** stratify cohorts and timepoints, derive repertoire signatures (diversity/clonality, V/J usage, similarity), and track antigen-annotated clonotypes; + +- **Feature engineering:** build Machine Learning-ready feature tables (receptor-, ssample- and cohort-level) from core repertoire metrics and annotations, with consistent IDs/metadata for downstream statistics or modeling; + +- **Modular, extendable, adaptable:** add new analyses and metrics via a extension API, and use adapters to interoperate with other AIRR tools and formats. + + +## 🤔 Why `immunarch`? + +As immune repertoire sequencing becomes a mainstream technology, adopted by major platforms and integrated into more translational and clinical workflows, tooling expectations are changing rapidly. +The pace of innovation and data growth sometimes outstrips what even the most dedicated tool developers can deliver. + +That's why it's the perfect moment to step back and rethink **how** and **why** we analyze AIRR data. +Instead of racing to patch each new problem, we need to prepare for the **next epoch** of immunomics. + +**What defines this next epoch?** + +A massive shift in focus: from pure research towards biomarker discovery, personalized immunotherapies, and integration of immune repertoire data into real clinical decision-making. + +Today's AIRR analysis must handle: + +- **Multi-modal data:** bulk and single-cell V(D)J, spatial transcriptomics, gene expression, clinical metadata, and antigen specificity -- all together; + +- **Massive scale:** experiments that move from gigabytes to tens or hundreds of gigabytes, or even terabytes; + +- **Reproducibility and collaboration:** workflows that need to be shared, versioned, and rerun months or years later, sometimes by new teams. + +With this new landscape, the **how** and **why** of AIRR data analysis are evolving: + +- The focus is moving from "can I parse my data?" to "can I robustly extract insights, find biomarkers, and build ML-ready features for discovery or diagnostics?" + +- It's not enough for a toolkit to just work. It needs to scale, interoperate, and empower new kinds of science, including complex Deep Learning and foundation models. + +By taking a step back and rethinking the core "how" and "why" of AIRR analysis, `immunarch` prepares you for the next epoch of immunomics -- so your science is ready, whatever comes next. + +--- + +> [!WARNING] +> `immunarch` is evolving towards `1.0` version and undergoing huge changes. +> Please check the updates here: https://github.com/immunomind/immunarch/issues/432 +> +> To install the latest pre-1.0 version, use `pak::pkg_install("immunomind/immunarch@0.9.1")` +> +> To install the latest 1.0 pre-release version, use `pak::pkg_install("immunomind/immunarch")` + +--- + +- 🤔 [Why `immundata`?](#-why--immundata-) +- 📦 [Installation](#-installation) +- ⚡ [Quick Start](#-quick-start) +- [📄 Documentation](#-documentation) +- [🪲 Bugs and Issues](#-bugs-and-issues) +- 🏷 [About](#-about) + - [Citation](#citation) + - [License](#license) + - [Author and contributors](#author-and-contributors) + - [Commercial usage](#commercial-usage) + +--- + +## 📦 Installation + +### Prerequisites + +Before installing any release or pre-release version of `immunarch`, please install `pak` that will simplify the installation of any package, not just `immunarch`: + +```r +install.packages("pak", repos = sprintf("https://r-lib.github.io/p/pak/stable/%s/%s/%s", .Platform$pkgType, R.Version()$os, R.Version()$arch)) +``` + +More info if needed is available on [pak website](https://pak.r-lib.org/#arrow_down-installation). + +### Install the latest version + +To install the latest release of `immunarch`, simply run: + +```r +pak::pkg_install("immunomind/immunarch") +``` + +Mind that this will install the package from our GitHub instead of CRAN. This method is much preferred due to limitations of CRAN and reliance on other packages, which are distributed via `pak` as well. + +### Other installation options + +We will periodically release `immunarch` on CRAN. To install it from CRAN, run + +```r +pak::pkg_install("immunarch") +``` + +If you are willing to try unstable yet bleeding edge features, or if there are some hot fix for your open GitHub ticket, please install the development version: + +```r +pak::pkg_install("immunomind/immunarch@dev") +``` + + +## ⚡ Quick Start + +```r +# Install `pak` - a blazingly-fast package manager +install.packages("pak", repos = sprintf("https://r-lib.github.io/p/pak/stable/%s/%s/%s", .Platform$pkgType, R.Version()$os, R.Version()$arch)) + +# Install and load immunarch along with the pre-packaged data +pak::pkg_install("immundata/immunarch") +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_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") +immdata <- read_repertoires("", metadata = mdtable) + +# Use your own data by reading sample files directly +mdtable <- read_metadata("data/metadata.csv") +immdata <- read_repertoires("data/*.tsv.gz", metadata = mdtable) +``` + +Oh, and one small thing. Even if you have tens of gigabytes of the data, you won't need to adapt the code to a server. +The code will be exactly the same — `immunarch` got your back thanks to [`immundata`](https://github.com/immunomind/immundata/). + + +## 📄 Documentation + +To get a list of available methods and their descriptions, run the default help command in R on specific functions or on a function family prefix: + +```r +# This is the same +?airr_stats +# as this +?airr_stats_genes + +# Basic statistics - gene usage, length distribution +?airr_stats + +# Public receptor indices - overlap, jaccard, morisita +?airr_public + +# Clonality analysis - clonal lines, occupied space, clonal space homeostasis +?airr_clonality + +# Diversity analysis - pielou, shannon, chao1 +?airr_diversity + +# ... more to come ... +``` + +More detailed documentation, guides and comprehensive tutorials are available on the ecosystem website: [https://immunomind.github.io/docs/](https://immunomind.github.io/docs/). + + +## 🪲 Bugs and Issues + +The mission of `immunarch` is to make bulk and single-cell immune repertoires analysis painless. All bug reports, documentation improvements, enhancements and ideas are appreciated. Just let us know via [GitHub](https://github.com/immunomind/immunarch/issues) (preferably) or [support@immunomind.com](mailto:support@immunomind.com) (in case of private data). + +Bug reports must: + +1. Include a short, self-contained R snippet reproducing the problem. +2. Add a minimal data sample for us to reproduce the problem. In case of sensitive data you can send it to [support@immunomind.com](mailto:support@immunomind.com) instead of GitHub issues. +3. Explain why the current behavior is wrong/not desired and what you expect instead. +4. If the issue is about visualisations, please attach a picture to the issue. In other case we wouldn't be able to reproduce the bug and fix it. + +We are always open to contributions. There are three ways to contribute: + +1. Create an issue [here](https://github.com/immunomind/immunarch/issues) and describe what would you like to improve or discuss. + +2. Create an issue or find one [here](https://github.com/immunomind/immunarch/issues), fork the repository and make a pull request with the bugfix or improvement. + +3. Find an existing issue and help others resolve this. + + +## 🏷 About + +### Citation + +> Temporary citation is below. The main manuscript is in preparation. Preprint on BioArxiv is coming soon as of 2025. + +ImmunoMind Team. (2019). immunarch: An R Package for Painless Bioinformatics Analysis of T-Cell and B-Cell Immune Repertoires. Zenodo. http://doi.org/10.5281/zenodo.3367200 + +BibTex: +``` +@misc{immunomind_team_2019_3367200, + author = {{ImmunoMind Team}}, + title = {{immunarch: An R Package for Painless Bioinformatics Analysis + of T-Cell and B-Cell Immune Repertoires}}, + month = aug, + year = 2019, + doi = {10.5281/zenodo.3367200}, + url = {https://doi.org/10.5281/zenodo.3367200} +} +``` + +For EndNote citation import the [`immunarch-citation.xml`](https://gitlab.com/immunomind/immunarch/raw/master/immunarch-citation.xml?inline=false) file. + + +### License + +The package is freely distributed under the Apache-2.0 license. You can read more about it [here](https://www.tldrlegal.com/license/apache-license-2-0-apache-2-0). + +### Author and contributors + +- **Vadim I. Nazarov – main author and developer** +- Vasily Tsvetkov +- Aleksandr Popov +- Ivan Balashov + +### Commercial usage + +`immunarch` is free to use for commercial usage as per Apache-2.0 license. However, corporate users will not get a prioritized support for `immunarch`- or AIRR-related issues. The priority of open-source tool `immunarch` is open-source science. + +If you are looking for prioritized support and setting up your data pipelines, consider contacting [Vadim Nazarov](https://www.linkedin.com/in/vdnaz/) for commercial consulting / support options / workshops and training sessions / designing data platforms and machine learning systems for multi-omics / or anything related. diff --git a/vignettes/web_only/BCRpipeline.Rmd b/vignettes/web_only_v0/BCRpipeline.Rmd similarity index 94% rename from vignettes/web_only/BCRpipeline.Rmd rename to vignettes/web_only_v0/BCRpipeline.Rmd index 6419869f..d83c742d 100644 --- a/vignettes/web_only/BCRpipeline.Rmd +++ b/vignettes/web_only_v0/BCRpipeline.Rmd @@ -94,7 +94,7 @@ B-cell **clonal lineage** represents a set of B cells that presumably have a com An example of reconstructing clonal lineages using default Immunarch options: -```{r example 2} +```{r example 2, eval=FALSE} #calulate distance matrix distBCR <- seqDist(bcrdata$data %>% top(500)) @@ -108,7 +108,7 @@ Each clonal lineage has its own **germline sequence** that represents the ancest In Immunarch, `repGermline()` function generates germline for each sequence: -```{r example 3, results = 'hide'} +```{r example 3, results = 'hide', eval=FALSE} #generate germline bcrdata$data %>% repGermline(.threads = 1) @@ -116,7 +116,7 @@ bcrdata$data %>% A germline is represented via sequences of V gene - N...N (CDR3 length) - J gene: -```{r example 4} +```{r example 4, eval=FALSE} #germline example bcrdata$data %>% top(1) %>% @@ -151,7 +151,7 @@ sudo apt install clustalw `repAlignLineage` usage example: -```{r example 7, results = 'hide'} +```{r example 7, results = 'hide', eval=FALSE} data(bcrdata) bcr_data <- bcrdata$data %>% top(500) bcr_data %>% @@ -164,7 +164,7 @@ The function has several parameters: - `.min_lineage_sequences` — Filters clusters (clonal lineages) with the number of clonotypes lower than the threshold. Aligning clonal lineages with few sequences is of little use. -```{r example 8, results = 'hide'} +```{r example 8, results = 'hide', eval=FALSE} # take clusters that contain at least 1 sequence bcr_data <- bcrdata$data align_dt <- bcr_data %>% @@ -185,7 +185,7 @@ Requirements for the input table for `repAlignLineage()` Align sequences in a cluster can be visualized using standard functions: -```{r align visualisation} +```{r align visualisation, eval=FALSE} # A name of the first cluster align_dt$full_clones$Cluster[[1]] @@ -217,7 +217,7 @@ sudo apt-get install -y phylip repClonalFamily usage example: -```{r example 10, results = 'hide'} +```{r example 10, results = 'hide', eval=FALSE} bcr <- align_dt %>% repClonalFamily(.threads = 2, .nofail = TRUE) #plot visualization of the first tree @@ -225,14 +225,14 @@ vis(bcr[["full_clones"]][["TreeStats"]][[1]]) ``` For each cluster tree is represented as table (The default number of clones for CommonAncestor, Germline, Presumable is 1): -```{r example 10.1, results = 'hide'} +```{r example 10.1, results = 'hide', eval=FALSE} #example for the first tree bcr[["full_clones"]][["TreeStats"]][[1]] ``` You can recolor leaves. For example, we recolor leaves where number of AA mutations is not 0: -```{r example 10.3, results = 'hide'} +```{r example 10.3, results = 'hide', eval=FALSE} #take sequence where number of AA mutations is not 0 f <- bcr[["full_clones"]][["TreeStats"]][[1]] #rename these leaves @@ -243,7 +243,7 @@ vis(f) Another way to recolor leaves is to use `.vis_groups` parameter for repClonalFamily. It allows to assign group names for specific clone IDs, or lists of clone IDs: -```{r example 10.4, results = 'hide'} +```{r example 10.4, results = 'hide', eval=FALSE} #get all clone IDs from align_dt clone_ids <- unnest(align_dt[["full_clones"]], "Sequences")[["Clone.ID"]] #run repClonalFamily with assigning some of these clones to differently named and colored groups @@ -261,13 +261,13 @@ vis(bcr_with_groups[["full_clones"]][["TreeStats"]][[1]]) We have found 4 clusters: -```{r example 11, warning = FALSE} +```{r example 11, warning = FALSE, eval=FALSE} bcr$full_clones$Cluster %>% unique() ``` We have found mismatches between a germline and an ancestor sequence. Dots represent nucleotides matches between the sequences, letters represent mismatches between the sequences: -```{r example 12} +```{r example 12, eval=FALSE} # the example of common ancestor sequence bcr$full_clones$Common.Ancestor[1] @@ -277,13 +277,13 @@ bcr$full_clones$Germline.Output[1] We have calculated a trunk length for each cluster: -```{r example 13} +```{r example 13, eval=FALSE} bcr$full_clones[ , c('Cluster', 'Trunk.Length') ] ``` Also trunk length specified in "TreeStats" table in column "DistanceNT". -```{r example 10.2, results = 'hide'} +```{r example 10.2, results = 'hide', eval=FALSE} #example fot first tree bcr[["full_clones"]][["TreeStats"]][[1]][1, ] ``` @@ -294,7 +294,7 @@ The rate of somatic hypermutation allows us to estimate repertoire maturation an In Immunarch, `repSomaticHypermutation()` function is designed for hypermutation analysis: -```{r example 14, , warning = FALSE} +```{r example 14, , warning = FALSE, eval=FALSE} bcr_data <- bcrdata$data shm_data <- bcr %>% repSomaticHypermutation(.threads = 2, .nofail = TRUE) @@ -304,7 +304,7 @@ The function repSomaticHypermutation() takes V and J germline sequences and V an Examples of germline and clonotype sequences: -```{r example 15} +```{r example 15, eval=FALSE} full_clones <- shm_data$full_clones v_length <- nchar(paste(full_clones[1, "FR1.nt"], full_clones[1, "CDR1.nt"], full_clones[1, "FR2.nt"], full_clones[1, "CDR2.nt"], full_clones[1, "FR3.nt"], collapse="")) @@ -326,26 +326,26 @@ full_clones$Sequence[1] %>% substr(seq_length - j_length, seq_length) Example: aligning germline and clonotype V sequences: -```{r example 16} +```{r example 16, eval=FALSE} image(shm_data$full_clones$Germline.Alignment.V[[3]], grid = TRUE) ``` Example: aligning germline and clonotype J sequences: -```{r example 17} +```{r example 17, eval=FALSE} image(shm_data$full_clones$Germline.Alignment.J[[3]], grid = TRUE) ``` The number of mutations for each clonotype sequence: -```{r example 18} +```{r example 18, eval=FALSE} cols <- c('Clone.ID', 'Substitutions', 'Insertions', 'Deletions', 'Mutations') shm_data$full_clones[ , cols ] ``` Then you could easily estimate the mutation rate: -```{r example 19} +```{r example 19, eval=FALSE} # estimate mutation rate shm_data$full_clones %>% mutate(Mutation.Rate = Mutations / (nchar(Sequence) - nchar(CDR3.nt))) %>% diff --git a/vignettes/web_only/clustering.Rmd b/vignettes/web_only_v0/clustering.Rmd similarity index 96% rename from vignettes/web_only/clustering.Rmd rename to vignettes/web_only_v0/clustering.Rmd index 39e85fca..38fb3b9f 100644 --- a/vignettes/web_only/clustering.Rmd +++ b/vignettes/web_only_v0/clustering.Rmd @@ -122,7 +122,7 @@ Clustering is commonly used to expand the concept of a clonotype. For example, y Example: -```{r example 7} +```{r example 7, eval=FALSE} #calculate distance distTCR <- seqDist( TCRdata, .col = 'CDR3.aa') @@ -140,7 +140,7 @@ In general, the number of clusters you get depends on threshold you defined prev Requires defining the minimum percentage of similarity for the sequences in your cluster in advance. For example, if you want to find cluster of BCRs that not only have the same V.name, J.name, and CDR3 length — but also have more than 90 percent match in their CDR3. -```{r example 8, warning = FALSE} +```{r example 8, warning = FALSE, eval=FALSE} #clustering TCR clustTCR <- seqCluster(TCRdata, distTCR, .perc_similarity = 0.75) @@ -155,7 +155,7 @@ clustTCR$"A2-i129" %>% .$Cluster %>% unique() %>% length() Requires directly determining the number of mismatched nucleotides. In case of TCR-recognising the same epitope, use 1 amino acid mismatch in CDR3 sequences. -```{r example 9, warning = FALSE} +```{r example 9, warning = FALSE, eval=FALSE} #clustering TCR clustTCR <- seqCluster(TCRdata, distTCR, .fixed_threshold = 2) @@ -170,7 +170,7 @@ clustTCR$"A2-i129" %>% .$Cluster %>% unique() %>% length() If you want to guarantee that the matches in the sequences are at a set proximity, specify a distance threshold -```{r example 10, warning = FALSE} +```{r example 10, warning = FALSE, eval=FALSE} #clustering TCR clustTCR <- seqCluster(TCRdata, distTCR, .nt_similarity = 10) @@ -187,7 +187,7 @@ If you made it to this part, then you have successfully clustered your sequences Comparing cluster size distributions is a good way to analyse quality of clustering process and to choose the best parameters for functions: -```{r } +```{r eval=FALSE } #write small function for the visualization of cluster size destribution mk_hist <- function(clust_dt, graph_name) { return(ggplot(clust_dt, aes(x=cluster_size)) + geom_histogram( binwidth=1, fill="#69b3a2", color="#e9ecef", alpha=0.9) + @@ -209,7 +209,7 @@ There are other packages that provide computational framework for identification `Immunarch` enables users to integrate results from `scoper` package for further analysis: -```{r example 11, warning = FALSE} +```{r example 11, warning = FALSE, eval=FALSE} #load the package into the R environment library(scoper) @@ -221,7 +221,7 @@ bcr <- bcrdata$data$full_clones %>% Add columns ‘sequence_alignment’ required by `scoper` (https://scoper.readthedocs.io/en/stable/vignettes/Scoper-Vignette/): -```{r example 12} +```{r example 12, eval=FALSE} #generate `sequence_alignment` column cols <- c('FR1.nt', 'CDR1.nt', 'FR2.nt', 'CDR2.nt', 'FR3.nt', 'CDR3.nt', 'FR4.nt') bcr$sequence_alignment <- apply( bcr[ , cols ] , 1 , paste , collapse = "" ) @@ -229,20 +229,20 @@ bcr$sequence_alignment <- apply( bcr[ , cols ] , 1 , paste , collapse = "" ) Rename columns in `scoper` format: -```{r example 13} +```{r example 13, eval=FALSE} ExampleDb <- bcr %>% select(J.allele, V.allele, CDR3.nt, Germline.sequence, sequence_alignment) %>% rename(junction = CDR3.nt, v_call = V.allele, j_call = J.allele, germline_alignment_d_mask = Germline.sequence) ``` Cluster using `scoper` method: -```{r example 14} +```{r example 14, eval=FALSE} results <- hierarchicalClones(ExampleDb, threshold=0.15) plot(results, binwidth=0.02) ``` Note that the column ‘clone_id' in `scoper` format has the same meaning as the ‘Cluster’ column in `immunarch`: -```{r example 15} +```{r example 15, eval=FALSE} glimpse(summary(results)) ``` diff --git a/vignettes/web_only/community.Rmd b/vignettes/web_only_v0/community.Rmd similarity index 100% rename from vignettes/web_only/community.Rmd rename to vignettes/web_only_v0/community.Rmd diff --git a/vignettes/v2_data.Rmd b/vignettes/web_only_v0/data.Rmd similarity index 100% rename from vignettes/v2_data.Rmd rename to vignettes/web_only_v0/data.Rmd diff --git a/vignettes/v1_introduction.Rmd b/vignettes/web_only_v0/introduction.Rmd similarity index 90% rename from vignettes/v1_introduction.Rmd rename to vignettes/web_only_v0/introduction.Rmd index 6ac5d90d..5fe598b6 100644 --- a/vignettes/v1_introduction.Rmd +++ b/vignettes/web_only_v0/introduction.Rmd @@ -215,7 +215,7 @@ Sys.setenv(R_REMOTES_NO_ERRORS_FROM_WARNINGS="true") 9. If you cannot install dependencies for `immunarch`, please consider manual installation of all dependencies by executing the following command in R console: ``` -install.packages(c("rematch", "prettyunits", "forcats", "cellranger", "progress", "zip", "backports", "ellipsis", "zeallot", "SparseM", "MatrixModels", "sp", "haven", "curl", "readxl", "openxlsx", "minqa", "nloptr", "RcppEigen", "utf8", "vctrs", "carData", "pbkrtest", "quantreg", "maptools", "rio", "lme4", "labeling", "munsell", "cli", "fansi", "pillar", "viridis", "car", "ellipse", "flashClust", "leaps", "scatterplot3d", "modeltools", "DEoptimR", "digest", "gtable", "lazyeval", "rlang", "scales", "tibble", "viridisLite", "withr", "assertthat", "glue", "magrittr", "pkgconfig", "R6", "tidyselect", "BH", "plogr", "purrr", "ggsci", "cowplot", "ggsignif", "polynom", "fastcluster", "plyr", "abind", "dendextend", "FactoMineR", "mclust", "flexmix", "prabclus", "diptest", "robustbase", "kernlab", "GlobalOptions", "shape", "colorspace", "stringi", "hms", "clipr", "crayon", "httpuv", "mime", "jsonlite", "xtable", "htmltools", "sourcetools", "later", "promises", "gridBase", "RColorBrewer", "yaml", "ggplot2", "dplyr", "dtplyr", "data.table", "gridExtra", "ggpubr", "pheatma3", "ggrepel", "reshape2", "DBI", "factoextra", "fpc", "circlize", "tidyr", "Rtsne", "readr", "readxl", "shiny", "shinythemes", "treemap", "igraph", "airr", "ggseqlogo", "UpSetR", "stringr", "ggalluvial", "Rcpp")) +install.packages(c("rematch", "prettyunits", "forcats", "cellranger", "progress", "zip", "backports", "ellipsis", "zeallot", "SparseM", "MatrixModels", "sp", "haven", "curl", "openxlsx", "minqa", "nloptr", "RcppEigen", "utf8", "vctrs", "carData", "pbkrtest", "quantreg", "maptools", "rio", "lme4", "labeling", "munsell", "cli", "fansi", "pillar", "viridis", "car", "ellipse", "flashClust", "leaps", "scatterplot3d", "modeltools", "DEoptimR", "digest", "gtable", "lazyeval", "rlang", "scales", "tibble", "viridisLite", "withr", "assertthat", "glue", "magrittr", "pkgconfig", "R6", "tidyselect", "BH", "plogr", "purrr", "ggsci", "cowplot", "ggsignif", "polynom", "fastcluster", "plyr", "abind", "dendextend", "FactoMineR", "mclust", "flexmix", "prabclus", "diptest", "robustbase", "kernlab", "GlobalOptions", "shape", "colorspace", "stringi", "hms", "clipr", "crayon", "httpuv", "mime", "jsonlite", "xtable", "htmltools", "sourcetools", "later", "promises", "gridBase", "RColorBrewer", "yaml", "ggplot2", "dplyr", "dtplyr", "data.table", "gridExtra", "ggpubr", "pheatma3", "ggrepel", "reshape2", "DBI", "factoextra", "fpc", "circlize", "tidyr", "Rtsne", "readr", "readxl", "shiny", "shinythemes", "treemap", "igraph", "airr", "ggseqlogo", "UpSetR", "stringr", "ggalluvial", "Rcpp")) ``` 9. If you encounter the following error while running the `devtools::install_local` function: diff --git a/vignettes/web_only/load_10x.Rmd b/vignettes/web_only_v0/load_10x.Rmd similarity index 100% rename from vignettes/web_only/load_10x.Rmd rename to vignettes/web_only_v0/load_10x.Rmd diff --git a/vignettes/web_only/load_mixcr.Rmd b/vignettes/web_only_v0/load_mixcr.Rmd similarity index 100% rename from vignettes/web_only/load_mixcr.Rmd rename to vignettes/web_only_v0/load_mixcr.Rmd diff --git a/vignettes/web_only/repFilter_v3.Rmd b/vignettes/web_only_v0/repFilter_v3.Rmd similarity index 98% rename from vignettes/web_only/repFilter_v3.Rmd rename to vignettes/web_only_v0/repFilter_v3.Rmd index 96038ce3..1d964c51 100644 --- a/vignettes/web_only/repFilter_v3.Rmd +++ b/vignettes/web_only_v0/repFilter_v3.Rmd @@ -256,20 +256,20 @@ repFilter(scdata, .method = "by.clonotype", .query = list(CDR3.aa = exclude("par ``` Create a new dataset with cluster-specific immune repertoires (for more information see *Single-cell* tutorials): -```{r} +```{r eval=FALSE} scdata_cl <- select_clusters(scdata, scdata$bc_cluster, "Cluster") scdata_cl$meta ``` And compare the number of clonotypes between clusters: -```{r clonotypes, warnings = F} +```{r clonotypes, warnings = F, eval=FALSE} vis(repExplore(scdata_cl$data, .method = "volume")) ``` Compare J gene usage between three clusters: -```{r geneUsage, warning=F} +```{r geneUsage, warning=F, eval=FALSE} sc_active <- geneUsage(repFilter(scdata_cl, .method = "by.meta", .query = list(Cluster = include("Activ")))$data, "hs.trbj", .norm = T) p1 <- vis(sc_active) p1 @@ -284,7 +284,7 @@ p3 ``` Compare gene usage of IGHJ4 between three clusters: -```{r IGHV3, warning=F} +```{r IGHV3, warning=F, eval=FALSE} scdata_active <- repFilter(scdata_cl, .method = "by.meta", .query = list(Cluster = include("Activ"))) scdata_active <- repFilter(scdata_active, .method = "by.cl", .query = list(J.name = include("IGHJ4")), .match = "substring") sc_active <- geneUsage(scdata_active$data, "hs.trbj", .norm = T) @@ -304,7 +304,7 @@ p1 + p2 + p3 ``` Look at the coding clonotypes in each cluster. Note that there aren't any noncoding clonotypes in the datasets: -```{r ORF, warning=F} +```{r ORF, warning=F, eval=FALSE} scdata_active <- repFilter(scdata_cl, .method = "by.meta", .query = list(Cluster = include("Activ"))) scdata_active <- repFilter(scdata_active, .method = "by.clonotype", .query = list(CDR3.aa = exclude("partial", "out_of_frame"))) exp_vol <- repExplore(scdata_active$data, .method = "volume") diff --git a/vignettes/web_only/v10_prop.Rmd b/vignettes/web_only_v0/v10_prop.Rmd similarity index 100% rename from vignettes/web_only/v10_prop.Rmd rename to vignettes/web_only_v0/v10_prop.Rmd diff --git a/vignettes/web_only/v11_db.Rmd b/vignettes/web_only_v0/v11_db.Rmd similarity index 100% rename from vignettes/web_only/v11_db.Rmd rename to vignettes/web_only_v0/v11_db.Rmd diff --git a/vignettes/web_only/v21_singlecell.Rmd b/vignettes/web_only_v0/v21_singlecell.Rmd similarity index 98% rename from vignettes/web_only/v21_singlecell.Rmd rename to vignettes/web_only_v0/v21_singlecell.Rmd index f73e8b6c..7f3357c7 100644 --- a/vignettes/web_only/v21_singlecell.Rmd +++ b/vignettes/web_only_v0/v21_singlecell.Rmd @@ -84,7 +84,7 @@ head(igdata$data[[1]][c(1:7, 16, 17)]) To subset the data by barcodes, use the `select_barcodes` function. -```{r} +```{r, eval=FALSE} barcodes <- c("AGTAGTCAGTGTACTC-1", "GGCGACTGTACCGAGA-1", "TTGAACGGTCACCTAA-1") new_df <- select_barcodes(scdata$data[[1]], barcodes) @@ -96,7 +96,7 @@ new_df To create a new dataset with cluster-specific immune repertoires, use the `select_clusters` function: -```{r} +```{r, eval=FALSE} scdata_pat <- select_clusters(scdata, scdata$bc_patient, "Patient") names(scdata_pat$data) @@ -108,7 +108,7 @@ scdata_pat$meta To create a new dataset with cluster-specific immune repertoires, use the `select_clusters` function. You can apply this function after you created patient-specific datasets to get patient-specific cell cluster-specific immune repertoires, e.g., a Memory B Cell repertoire for a specific patient: -```{r} +```{r, eval=FALSE} scdata_cl <- select_clusters(scdata_pat, scdata$bc_cluster, "Cluster") names(scdata_cl$data) @@ -120,7 +120,7 @@ scdata_cl$meta Most functions will work out-of-the-box with paired chain data. -```{r} +```{r, eval=FALSE} p1 <- repOverlap(scdata_cl$data) %>% vis() p2 <- repDiversity(scdata_cl$data) %>% vis() diff --git a/vignettes/web_only/v3_basic_analysis.Rmd b/vignettes/web_only_v0/v3_basic_analysis.Rmd similarity index 100% rename from vignettes/web_only/v3_basic_analysis.Rmd rename to vignettes/web_only_v0/v3_basic_analysis.Rmd diff --git a/vignettes/web_only/v4_overlap.Rmd b/vignettes/web_only_v0/v4_overlap.Rmd similarity index 100% rename from vignettes/web_only/v4_overlap.Rmd rename to vignettes/web_only_v0/v4_overlap.Rmd diff --git a/vignettes/web_only/v5_gene_usage.Rmd b/vignettes/web_only_v0/v5_gene_usage.Rmd similarity index 100% rename from vignettes/web_only/v5_gene_usage.Rmd rename to vignettes/web_only_v0/v5_gene_usage.Rmd diff --git a/vignettes/web_only/v6_diversity.Rmd b/vignettes/web_only_v0/v6_diversity.Rmd similarity index 100% rename from vignettes/web_only/v6_diversity.Rmd rename to vignettes/web_only_v0/v6_diversity.Rmd diff --git a/vignettes/web_only/v7_fixvis.Rmd b/vignettes/web_only_v0/v7_fixvis.Rmd similarity index 100% rename from vignettes/web_only/v7_fixvis.Rmd rename to vignettes/web_only_v0/v7_fixvis.Rmd diff --git a/vignettes/web_only/v8_tracking.Rmd b/vignettes/web_only_v0/v8_tracking.Rmd similarity index 100% rename from vignettes/web_only/v8_tracking.Rmd rename to vignettes/web_only_v0/v8_tracking.Rmd diff --git a/vignettes/web_only/v9_kmers.Rmd b/vignettes/web_only_v0/v9_kmers.Rmd similarity index 100% rename from vignettes/web_only/v9_kmers.Rmd rename to vignettes/web_only_v0/v9_kmers.Rmd