Skip to content

Commit 4f0d7d1

Browse files
authored
Merge pull request #442 from immunomind/dev
Dev
2 parents 5a2ae26 + b45c240 commit 4f0d7d1

68 files changed

Lines changed: 1129 additions & 309 deletions

Some content is hidden

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

.Rbuildignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@
2828
^vignettes/articles$
2929
^vignettes/.quarto$
3030
^CRAN-SUBMISSION$
31+
^immdata-.*$
32+
^immdata*$

.github/workflows/pkgdown.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
needs: website
3838

3939
- name: Build site
40-
run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
40+
run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE, run_dont_run = FALSE)
4141
shell: Rscript {0}
4242

4343
- name: Deploy to GitHub pages 🚀

DESCRIPTION

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: immunarch
22
Type: Package
33
Title: Multi-Modal Immune Repertoire Analytics for Immunotherapy and Vaccine Design in R
4-
Version: 0.10.0
4+
Version: 0.10.2
55
Authors@R: c(
66
person("Vadim I.", "Nazarov", , "support@immunomind.com", role = c("aut", "cre"),
77
comment = c(ORCID = "0000-0003-3659-2709")),
@@ -19,10 +19,10 @@ Description: A comprehensive analytics framework for building reproducible pipel
1919
Think Scanpy or Seurat, but for AIRR data, a.k.a. Adaptive Immune Receptor Repertoire, VDJ-seq, RepSeq, or
2020
VDJ sequencing data. A successor to our previously published "tcR" R package (Nazarov 2015).
2121
License: Apache License (>= 2.0)
22-
URL: https://immunomind.github.io/docs/, https://github.com/immunomind/immunarch
22+
URL: https://immunomind.github.io/docs/, https://github.com/immunomind/immunarch/, https://immunarch.com/
2323
BugReports: https://github.com/immunomind/immunarch/issues
2424
Depends:
25-
R (>= 4.1.0),
25+
R (>= 4.2.0),
2626
ggplot2 (>= 3.1.0),
2727
immundata (>= 0.0.5),
2828
patchwork
@@ -53,16 +53,19 @@ Imports:
5353
utils,
5454
glue,
5555
checkmate,
56-
duckplyr (>= 1.1.0),
56+
duckplyr (>= 1.1.2),
5757
dbplyr,
5858
lifecycle,
5959
purrr,
60-
stats
60+
stats,
61+
vctrs,
62+
ggthemes,
63+
ggsci
6164
LinkingTo: Rcpp
6265
Suggests:
6366
knitr (>= 1.8),
6467
roxygen2 (>= 3.0.0),
65-
testthat (>= 2.1.0),
68+
testthat (>= 3.0.0),
6669
pkgdown (>= 0.1.0),
6770
assertthat,
6871
rmarkdown,
@@ -90,3 +93,4 @@ LazyData: true
9093
LazyDataCompression: xz
9194
Roxygen: list(markdown = TRUE)
9295
Config/Needs/website: rmarkdown
96+
Config/testthat/edition: 3

NAMESPACE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,11 @@ importFrom(checkmate,assert_character)
145145
importFrom(checkmate,assert_choice)
146146
importFrom(checkmate,assert_data_frame)
147147
importFrom(checkmate,assert_logical)
148+
importFrom(checkmate,assert_matrix)
148149
importFrom(checkmate,assert_numeric)
149150
importFrom(checkmate,assert_r6)
151+
importFrom(checkmate,assert_string)
152+
importFrom(checkmate,assert_subset)
150153
importFrom(circlize,chordDiagram)
151154
importFrom(cli,cli_alert_info)
152155
importFrom(cli,cli_alert_success)
@@ -189,6 +192,7 @@ importFrom(dplyr,group_by)
189192
importFrom(dplyr,group_by_at)
190193
importFrom(dplyr,group_keys)
191194
importFrom(dplyr,group_map)
195+
importFrom(dplyr,inner_join)
192196
importFrom(dplyr,intersect)
193197
importFrom(dplyr,left_join)
194198
importFrom(dplyr,mutate)
@@ -213,6 +217,8 @@ importFrom(dplyr,union_all)
213217
importFrom(dtplyr,lazy_dt)
214218
importFrom(duckplyr,as_duckdb_tibble)
215219
importFrom(duckplyr,as_tbl)
220+
importFrom(ggsci,scale_fill_locuszoom)
221+
importFrom(ggthemes,theme_few)
216222
importFrom(glue,glue)
217223
importFrom(grDevices,colorRampPalette)
218224
importFrom(graphics,plot)
@@ -310,4 +316,5 @@ importFrom(utils,read.table)
310316
importFrom(utils,setTxtProgressBar)
311317
importFrom(utils,tail)
312318
importFrom(utils,txtProgressBar)
319+
importFrom(vctrs,s3_register)
313320
useDynLib(immunarch, .registration = TRUE)

R/aaa-registry.R

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
IMMUNARCH_METHOD_REGISTRY <- new.env(parent = emptyenv())
22

3+
IMMUNARCH_VIS_REGISTRY <- new.env(parent = emptyenv())
34

4-
#' Common arguments for immundata helpers
5+
IMMUNARCH_CLASS_PREFIX <- "immunarch_res"
6+
7+
8+
# ---------------------------------------------------------------------------- #
9+
# --- Common arguments
10+
# ---------------------------------------------------------------------------- #
11+
12+
13+
#' Common arguments for immunarch helpers
514
#' @keywords internal
615
#' @param autojoin Logical. If TRUE, join repertoire metadata by the schema repertoire id.
716
#' Change the default behaviour by calling `options(immunarch.autojoin = FALSE)`.
@@ -13,6 +22,42 @@ im_common_args <- function(
1322
format = c("long", "wide")) {} # nocov
1423

1524

25+
# ---------------------------------------------------------------------------- #
26+
# --- Immunarch results attributes
27+
# ---------------------------------------------------------------------------- #
28+
29+
30+
im_norm <- function(x) {
31+
x <- tolower(x)
32+
gsub("[^a-z0-9]+", "_", x)
33+
}
34+
35+
36+
im_result_class <- function(family, name = NULL) {
37+
fam <- im_norm(family)
38+
if (is.null(name)) {
39+
paste0(IMMUNARCH_CLASS_PREFIX, "_", fam)
40+
} else {
41+
nm <- im_norm(name)
42+
paste0(IMMUNARCH_CLASS_PREFIX, "_", fam, "_", nm)
43+
}
44+
}
45+
46+
47+
im_as_result <- function(x, family, name) {
48+
# Wrap any object as an Immunarch result, preserving original classes
49+
cls_full <- im_result_class(family, name)
50+
cls_fam <- im_result_class(family, NULL)
51+
# TODO: maybe I need the "airr" or "receptor" instead of IMMUNARCH_CLASS_PREFIX?
52+
structure(x, class = c(cls_full, cls_fam, IMMUNARCH_CLASS_PREFIX, class(x)))
53+
}
54+
55+
56+
# ---------------------------------------------------------------------------- #
57+
# --- Immunarch methods
58+
# ---------------------------------------------------------------------------- #
59+
60+
1661
im_method <- function(core, family, name, required_cols = NULL, need_repertoires = TRUE) {
1762
checkmate::assert_function(core, args = c("idata"))
1863
checkmate::assert_string(family)
@@ -96,6 +141,9 @@ im_method <- function(core, family, name, required_cols = NULL, need_repertoires
96141
}
97142
}
98143

144+
# Wrap the output to assign correct classes
145+
out <- im_as_result(out, family, name)
146+
99147
out
100148
},
101149
list(core = core, core_fmls = core_fmls, required_cols = required_cols)
@@ -180,5 +228,58 @@ register_immunarch_method <- function(core, family, name, register_family = TRUE
180228
), silent = TRUE)
181229
}
182230

231+
# Link visualisation to a method if visualisation was already created
232+
im_ensure_vis_s3_for(family, name)
233+
183234
fn
184235
}
236+
237+
238+
# ---------------------------------------------------------------------------- #
239+
# --- Immunarch visualisations
240+
# ---------------------------------------------------------------------------- #
241+
242+
243+
IMMUNARCH_VIS_REGISTRY <- new.env(parent = emptyenv())
244+
245+
.im_ns <- function() asNamespace("immunarch")
246+
247+
im_vis_s3_exists <- function(class) {
248+
!is.null(utils::getS3method("vis", class, optional = TRUE))
249+
}
250+
251+
im_ensure_vis_s3_for <- function(family, name) {
252+
cls <- im_result_class(family, name)
253+
fn <- IMMUNARCH_VIS_REGISTRY[[cls]]
254+
if (!is.function(fn)) {
255+
return(invisible(FALSE))
256+
}
257+
if (im_vis_s3_exists(cls)) {
258+
return(invisible(FALSE))
259+
}
260+
261+
method <- function(.data, ...) {
262+
f <- IMMUNARCH_VIS_REGISTRY[[cls]]
263+
if (!is.function(f)) cli::cli_abort("Visualization for {.code {cls}} not found.")
264+
f(.data, ...)
265+
}
266+
267+
base::registerS3method("vis", cls, method, envir = .im_ns())
268+
invisible(TRUE)
269+
}
270+
271+
register_immunarch_visualisation <- function(fn, family, name) {
272+
checkmate::assert_function(fn, args = c(".data"))
273+
checkmate::assert_string(family)
274+
checkmate::assert_string(name)
275+
276+
cls <- im_result_class(family, name)
277+
assign(cls, fn, envir = IMMUNARCH_VIS_REGISTRY)
278+
279+
# immediate S3 registration (errors if vis generic not yet defined)
280+
if (!exists("vis", envir = .im_ns(), inherits = FALSE)) {
281+
stop("vis() generic must be defined before registering visualisations.")
282+
}
283+
im_ensure_vis_s3_for(family, name)
284+
invisible(cls)
285+
}

R/globals.R

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ utils::globalVariables(c(
88
"ch",
99
"clonal_prop_bin",
1010
"clonal_rank_bin",
11-
"prop"
11+
"prop",
12+
".val",
13+
"size"
1214
))
1315

1416
#' @keywords internal

R/immunarch-package.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
#' @importFrom checkmate assert_choice
44
#' @importFrom checkmate assert_data_frame
55
#' @importFrom checkmate assert_logical
6+
#' @importFrom checkmate assert_matrix
67
#' @importFrom checkmate assert_numeric
78
#' @importFrom checkmate assert_r6
9+
#' @importFrom checkmate assert_string
10+
#' @importFrom checkmate assert_subset
811
#' @importFrom cli cli_alert_info
912
#' @importFrom cli cli_alert_success
1013
#' @importFrom cli cli_alert_warning
@@ -23,6 +26,7 @@
2326
#' @importFrom dplyr count
2427
#' @importFrom dplyr distinct
2528
#' @importFrom dplyr filter
29+
#' @importFrom dplyr inner_join
2630
#' @importFrom dplyr intersect
2731
#' @importFrom dplyr left_join
2832
#' @importFrom dplyr mutate
@@ -37,6 +41,8 @@
3741
#' @importFrom dplyr union_all
3842
#' @importFrom duckplyr as_duckdb_tibble
3943
#' @importFrom duckplyr as_tbl
44+
#' @importFrom ggsci scale_fill_locuszoom
45+
#' @importFrom ggthemes theme_few
4046
#' @importFrom immundata imd_schema
4147
#' @importFrom immundata ImmunData
4248
#' @importFrom lifecycle deprecated
@@ -57,6 +63,7 @@
5763
#' @importFrom tidyr as_tibble
5864
#' @importFrom utils adist
5965
#' @importFrom utils globalVariables
66+
#' @importFrom vctrs s3_register
6067
#' @useDynLib immunarch, .registration = TRUE
6168
## usethis namespace: end
6269
NULL

R/v0_data_docs.R

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,3 @@ AA_TABLE_REVERSED <- AA_TABLE_REVERSED[order(names(AA_TABLE_REVERSED))]
9393
#' ...
9494
#' }
9595
"bcrdata"
96-
97-
98-
#' Paired chain immune repertoire dataset
99-
#'
100-
#' @concept data
101-
#'
102-
#' @description A dataset with paired chain IG data for testing and examplatory purposes.
103-
#'
104-
#' @format A list of four elements:
105-
#' "data" is a list with data frames with clonotype tables.
106-
#' "meta" is a metadata table.
107-
#' "bc_patients" is a list of barcodes corresponding to specific patients.
108-
#' "bc_clusters" is a list of barcodes corresponding to specific cell clusters.
109-
#' \describe{
110-
#' \item{data}{List of immune repertoire data frames.}
111-
#' \item{meta}{Metadata}
112-
#' ...
113-
#' }
114-
"scdata"

R/v0_filters.R

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,29 +45,6 @@
4545
#' - substring: matches all strings containing the specified substring.
4646
#' Default value: 'exact'.
4747
#'
48-
#' @examples
49-
#' data(immdata)
50-
#'
51-
#' # Select samples with status "MS"
52-
#' repFilter(immdata, "by.meta", list(Status = include("MS")))
53-
#'
54-
#' # Select samples without status "MS"
55-
#' repFilter(immdata, "by.meta", list(Status = exclude("MS")))
56-
#'
57-
#' # Select samples from lanes "A" and "B" with age > 15
58-
#' repFilter(immdata, "by.meta", list(Lane = include("A", "B"), Age = morethan(15)))
59-
#'
60-
#' # Select samples that are not from lanes "A" and "B"
61-
#' repFilter(immdata, "by.meta", list(Lane = exclude("A", "B")))
62-
#'
63-
#' # Select samples with a number of clonotypes from 1000 to 5000
64-
#' repFilter(immdata, "by.repertoire", list(n_clonotypes = interval(1000, 5000)))
65-
#'
66-
#' # Select clonotypes in all samples with alpha chains
67-
#' repFilter(immdata, "by.clonotype",
68-
#' list(V.name = include("AV"), J.name = include("AJ")),
69-
#' .match = "substring"
70-
#' )
7148
#' @export repFilter include exclude lessthan morethan interval
7249
repFilter <- function(.data, .method = "by.clonotype",
7350
.query = list(CDR3.aa = exclude("partial", "out_of_frame")),

R/v0_overlap.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,11 @@ horn_index <- function(.x, .y) {
378378
#' List with overlap matrices.
379379
#'
380380
#' @examples
381+
#' \dontrun{
381382
#' data(immdata)
382383
#' ov <- repOverlap(immdata$data, "inc+overlap", .step = 100, .verbose.inc = FALSE, .verbose = FALSE)
383384
#' vis(ov)
385+
#' }
384386
#' @export inc_overlap
385387
inc_overlap <- function(.data, .fun, .step = 1000, .n.steps = 10, .downsample = FALSE, .bootstrap = NA, .verbose.inc = TRUE, ...) {
386388
.n.steps <- as.integer(.n.steps)

0 commit comments

Comments
 (0)