Skip to content

Commit 168b4de

Browse files
Refactor NewInterface.R to unified API design
Rewrote NewInterface.R to provide a simplified, unified API for microbiome data analysis, consolidating multiple plotting and testing functions into core unified functions (plot_taxa, plot_alpha, plot_beta, test_taxa, test_beta, test_alpha). The new interface automatically detects study design and routes to the appropriate underlying function, improving usability and maintainability. Added detailed documentation and parameter validation, and removed legacy and redundant code.
1 parent 29ea9e0 commit 168b4de

18 files changed

Lines changed: 1343 additions & 2516 deletions

R/NewInterface.R

Lines changed: 642 additions & 2343 deletions
Large diffs are not rendered by default.

R/generate_alpha_boxplot_single.R

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#' @param alpha.name The alpha diversity index to be plotted. Supported indices include "shannon", "simpson", "observed_species", "chao1", "ace", "pielou", and "faith_pd".
88
#' @param depth An integer specifying the sequencing depth for the "Rarefy" and "Rarefy-TSS" methods.
99
#' If NULL, no rarefaction is performed.
10-
#' @param subject.var The variable in the metadata table that represents the subject.
1110
#' @param time.var The variable in the metadata table that represents the time.
1211
#' @param t.level Character string specifying the time level/value to subset data to,
1312
#' if a time variable is provided. Default NULL does not subset data.
@@ -76,7 +75,6 @@
7675
#' data.obj = peerj32.obj,
7776
#' alpha.obj = NULL,
7877
#' alpha.name = c("simpson"),
79-
#' subject.var = "subject",
8078
#' time.var = "time",
8179
#' t.level = "2",
8280
#' group.var = "group",
@@ -96,7 +94,6 @@
9694
#' data.obj = peerj32.obj,
9795
#' alpha.obj = alpha.obj,
9896
#' alpha.name = c("simpson"),
99-
#' subject.var = "subject",
10097
#' time.var = "time",
10198
#' t.level = "2",
10299
#' group.var = "group",
@@ -119,7 +116,6 @@
119116
#' data.obj = subset_T2D.obj,
120117
#' alpha.obj = NULL,
121118
#' alpha.name = c("shannon"),
122-
#' subject.var = "subject_id",
123119
#' time.var = "visit_number",
124120
#' t.level = " 3",
125121
#' group.var = "subject_race",
@@ -146,7 +142,6 @@
146142
#' data.obj = peerj32.obj,
147143
#' alpha.obj = NULL,
148144
#' alpha.name = c("simpson"),
149-
#' subject.var = "subject",
150145
#' time.var = "time",
151146
#' t.level = "2",
152147
#' group.var = "group",
@@ -167,7 +162,6 @@ generate_alpha_boxplot_single <- function (data.obj,
167162
alpha.name = c("shannon",
168163
"observed_species"),
169164
depth = NULL,
170-
subject.var = NULL,
171165
time.var = NULL,
172166
t.level = NULL,
173167
group.var = NULL,

R/generate_alpha_change_test_pair.R

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
#' @param alpha.name The alpha diversity index to be plotted. Supported indices include "shannon", "simpson", "observed_species", "chao1", "ace", "pielou", and "faith_pd". Previously named as `alpha.index`.
2424
#' @param depth An integer specifying the sequencing depth for the "Rarefy" and "Rarefy-TSS" methods.
2525
#' If NULL, no rarefaction is performed.
26-
#' @param time.var Character string specifying the column name in metadata containing
27-
#' time values for each sample. Required to identify pairs of time
28-
#' points to calculate changes between.
2926
#' @param subject.var Character string specifying the column name in metadata containing
3027
#' unique subject IDs. Required to pair samples from the same subject
3128
#' across time points.
29+
#' @param time.var Character string specifying the column name in metadata containing
30+
#' time values for each sample. Required to identify pairs of time
31+
#' points to calculate changes between.
3232
#' @param group.var Character string specifying the column name in metadata containing
3333
#' grouping categories. Used as a predictor in the models to test for
3434
#' differences in changes between groups. Optional, can be NULL.
@@ -83,9 +83,9 @@
8383
#' generate_alpha_change_test_pair(
8484
#' data.obj = peerj32.obj,
8585
#' alpha.obj = NULL,
86-
#' time.var = "time",
8786
#' alpha.name = c("shannon"),
8887
#' subject.var = "subject",
88+
#' time.var = "time",
8989
#' group.var = "sex",
9090
#' adj.vars = NULL,
9191
#' change.base = "2",
@@ -100,9 +100,9 @@
100100
#' generate_alpha_change_test_pair(
101101
#' data.obj = peerj32.obj,
102102
#' alpha.obj = NULL,
103-
#' time.var = "Day",
104103
#' alpha.name = c("shannon"),
105104
#' subject.var = "subject",
105+
#' time.var = "Day",
106106
#' group.var = "sex",
107107
#' adj.vars = c("group"),
108108
#' change.base = "2",
@@ -115,9 +115,9 @@
115115
#' generate_alpha_change_test_pair(
116116
#' data.obj = subset_pairs.obj,
117117
#' alpha.obj = NULL,
118-
#' time.var = "Antibiotic",
119118
#' alpha.name = c("shannon"),
120119
#' subject.var = "MouseID",
120+
#' time.var = "Antibiotic",
121121
#' group.var = "Sex",
122122
#' adj.vars = NULL,
123123
#' change.base = "Baseline",
@@ -131,8 +131,8 @@ generate_alpha_change_test_pair <-
131131
alpha.obj = NULL,
132132
alpha.name = NULL,
133133
depth = NULL,
134-
time.var,
135134
subject.var,
135+
time.var,
136136
group.var,
137137
adj.vars = NULL,
138138
change.base,

R/generate_alpha_test_pair.R

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ extract_coef <- function(model) {
6868
#' "observed_species", "chao1", "ace", "pielou", and "faith_pd".
6969
#' @param depth An integer specifying the sequencing depth for the "Rarefy" and "Rarefy-TSS" methods.
7070
#' If NULL, no rarefaction is performed.
71-
#' @param group.var A string representing the group variable's name in the
72-
#' metadata.
71+
#' @param subject.var A string specifying the subject variable column in the metadata.
7372
#' @param time.var A string representing the time variable's name in the
7473
#' metadata. The default is NULL.
75-
#' @param subject.var A string specifying the subject variable column in the metadata.
74+
#' @param group.var A string representing the group variable's name in the
75+
#' metadata.
7676
#' @param adj.vars A character vector with the names of adjustment variables in
7777
#' the metadata.
7878
#' @param change.base A value indicating the base level for the time variable.
@@ -87,37 +87,37 @@ extract_coef <- function(model) {
8787
#' generate_alpha_test_pair(
8888
#' data.obj = peerj32.obj,
8989
#' alpha.obj = NULL,
90-
#' time.var = "time",
9190
#' alpha.name = c("shannon", "simpson", "ace"),
9291
#' subject.var = "subject",
92+
#' time.var = "time",
9393
#' group.var = NULL
9494
#' )
9595
#'
9696
#' generate_alpha_test_pair(
9797
#' data.obj = peerj32.obj,
9898
#' alpha.obj = NULL,
99-
#' time.var = "time",
10099
#' alpha.name = c("shannon", "simpson", "ace"),
101100
#' subject.var = "subject",
101+
#' time.var = "time",
102102
#' group.var = NULL,
103103
#' change.base = "2"
104104
#' )
105105
#'
106106
#' generate_alpha_test_pair(
107107
#' data.obj = peerj32.obj,
108108
#' alpha.obj = NULL,
109-
#' time.var = "time",
110109
#' alpha.name = c("shannon", "simpson", "ace"),
111110
#' subject.var = "subject",
111+
#' time.var = "time",
112112
#' group.var = "group"
113113
#' )
114114
#'
115115
#' generate_alpha_test_pair(
116116
#' data.obj = peerj32.obj,
117117
#' alpha.obj = NULL,
118-
#' time.var = "time",
119118
#' alpha.name = c("shannon", "simpson", "ace"),
120119
#' subject.var = "subject",
120+
#' time.var = "time",
121121
#' group.var = "group",
122122
#' adj.vars = "sex"
123123
#' )
@@ -126,17 +126,17 @@ extract_coef <- function(model) {
126126
#' generate_alpha_test_pair(
127127
#' data.obj = subset_pairs.obj,
128128
#' alpha.obj = NULL,
129-
#' time.var = "Antibiotic",
130129
#' alpha.name = c("shannon", "simpson", "ace"),
131130
#' subject.var = "MouseID",
131+
#' time.var = "Antibiotic",
132132
#' group.var = "Sex"
133133
#' )
134134
#' generate_alpha_test_pair(
135135
#' data.obj = subset_pairs.obj,
136136
#' alpha.obj = NULL,
137-
#' time.var = "Antibiotic",
138137
#' alpha.name = c("shannon", "simpson", "ace"),
139138
#' subject.var = "MouseID",
139+
#' time.var = "Antibiotic",
140140
#' group.var = "Sex",
141141
#' change.base = "Week 2"
142142
#' )
@@ -146,8 +146,8 @@ generate_alpha_test_pair <-
146146
alpha.obj = NULL,
147147
alpha.name = NULL,
148148
depth = NULL,
149-
time.var,
150149
subject.var,
150+
time.var,
151151
group.var,
152152
adj.vars = NULL,
153153
change.base = NULL) {

R/generate_beta_change_test_pair.R

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
#' \code{\link[MicrobiomeStat]{mStat_calculate_beta_diversity}} function.
1616
#' If NULL, beta diversity will be automatically computed from \code{data.obj}
1717
#' using \code{mStat_calculate_beta_diversity}.
18-
#' @param time.var The name of the column in metadata containing the time variable.
19-
#' This should be a column with time points for each sample. Required
20-
#' to identify pairs of samples for the same subject across time.
2118
#' @param subject.var The name of the column in metadata containing the subject IDs.
2219
#' This should uniquely identify each subject in the study. Required
2320
#' to identify samples that belong to the same subject.
21+
#' @param time.var The name of the column in metadata containing the time variable.
22+
#' This should be a column with time points for each sample. Required
23+
#' to identify pairs of samples for the same subject across time.
2424
#' @param group.var The name of the column in metadata containing the grouping variable
2525
#' to use in linear modeling. This grouping variable will be used as a
2626
#' predictor in the linear models for beta diversity change. Optional.
@@ -43,8 +43,8 @@
4343
#' generate_beta_change_test_pair(
4444
#' data.obj = peerj32.obj,
4545
#' dist.obj = NULL,
46-
#' time.var = "time",
4746
#' subject.var = "subject",
47+
#' time.var = "time",
4848
#' group.var = "group",
4949
#' adj.vars = NULL,
5050
#' change.base = "1",
@@ -53,8 +53,8 @@
5353
#' generate_beta_change_test_pair(
5454
#' data.obj = peerj32.obj,
5555
#' dist.obj = NULL,
56-
#' time.var = "time",
5756
#' subject.var = "subject",
57+
#' time.var = "time",
5858
#' group.var = "group",
5959
#' adj.vars = "sex",
6060
#' change.base = "1",
@@ -65,8 +65,8 @@
6565
#' generate_beta_change_test_pair(
6666
#' data.obj = subset_pairs.obj,
6767
#' dist.obj = NULL,
68-
#' time.var = "Antibiotic",
6968
#' subject.var = "MouseID",
69+
#' time.var = "Antibiotic",
7070
#' group.var = "Sex",
7171
#' adj.vars = NULL,
7272
#' change.base = "Baseline",
@@ -89,8 +89,8 @@
8989
generate_beta_change_test_pair <-
9090
function(data.obj,
9191
dist.obj = NULL,
92-
time.var = NULL,
9392
subject.var,
93+
time.var = NULL,
9494
group.var,
9595
adj.vars = NULL,
9696
change.base = NULL,

R/generate_beta_ordination_single.R

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#' \item{Other metadata}{like method, dist.name, etc.}
2222
#' }
2323
#' See \code{\link[MicrobiomeStat]{mStat_calculate_PC}} function for details on output format.
24-
#' @param subject.var String. Variable to be used as subject.
2524
#' @param time.var String. Variable to be used for time. Default is NULL.
2625
#' @param t.level Character string specifying the time level/value to subset data to,
2726
#' if a time variable is provided. Default NULL does not subset data.
@@ -95,7 +94,6 @@
9594
#' data.obj = peerj32.obj,
9695
#' dist.obj = NULL,
9796
#' pc.obj = NULL,
98-
#' subject.var = "subject",
9997
#' time.var = "time",
10098
#' t.level = "2",
10199
#' group.var = "group",
@@ -120,7 +118,6 @@
120118
#' data.obj = subset_T2D.obj,
121119
#' dist.obj = dist.obj,
122120
#' pc.obj = pc.obj,
123-
#' subject.var = "subject_id",
124121
#' time.var = "visit_number_num",
125122
#' t.level = NULL,
126123
#' group.var = "subject_race",
@@ -141,7 +138,6 @@
141138
#' @export
142139
generate_beta_ordination_single <-
143140
function(data.obj,
144-
subject.var,
145141
time.var = NULL,
146142
t.level = NULL,
147143
group.var = NULL,
@@ -174,12 +170,12 @@ generate_beta_ordination_single <-
174170
# Subset data to specific time point if t.level is provided
175171
condition <- paste(time.var, "== '", t.level, "'", sep = "")
176172
data.obj <- mStat_subset_data(data.obj, condition = condition)
177-
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(subject.var,group.var,strata.var,time.var)))
173+
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(group.var,strata.var,time.var)))
178174
dist.obj <-
179175
mStat_calculate_beta_diversity(data.obj = data.obj, dist.name = dist.name)
180176
} else {
181177
# If no specific time point is provided, use all time points but warn if multiple exist
182-
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(subject.var,group.var,strata.var,time.var)))
178+
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(group.var,strata.var,time.var)))
183179
if (length(levels(as.factor(meta_tab[,time.var]))) != 1){
184180
message("Multiple time points detected in your dataset. It is recommended to either set t.level or utilize functions for longitudinal data analysis.")
185181
}
@@ -188,7 +184,7 @@ generate_beta_ordination_single <-
188184
}
189185
} else {
190186
# If no time variable is provided, proceed with all data
191-
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(subject.var,group.var,strata.var,time.var)))
187+
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(group.var,strata.var,time.var)))
192188
dist.obj <-
193189
mStat_calculate_beta_diversity(data.obj = data.obj, dist.name = dist.name)
194190
}
@@ -203,19 +199,19 @@ generate_beta_ordination_single <-
203199
if (!is.null(t.level)){
204200
condition <- paste(time.var, "== '", t.level, "'", sep = "")
205201
data.obj <- mStat_subset_data(data.obj, condition = condition)
206-
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(subject.var,group.var,strata.var,time.var)))
202+
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(group.var,strata.var,time.var)))
207203
} else {
208-
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(subject.var,group.var,strata.var,time.var)))
204+
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(group.var,strata.var,time.var)))
209205
if (length(levels(as.factor(meta_tab[,time.var]))) != 1){
210206
message("Multiple time points detected in your dataset. It is recommended to either set t.level or utilize functions for longitudinal data analysis.")
211207
}
212208
}
213209
} else {
214-
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(subject.var,group.var,strata.var,time.var)))
210+
meta_tab <- data.obj$meta.dat %>% dplyr::select(all_of(c(group.var,strata.var,time.var)))
215211
}
216212
}
217213
if (!is.null(attr(dist.obj[[dist.name[1]]], "labels"))){
218-
meta_tab <- attr(dist.obj[[dist.name[1]]], "labels") %>% dplyr::select(all_of(c(subject.var,group.var,strata.var,time.var)))
214+
meta_tab <- attr(dist.obj[[dist.name[1]]], "labels") %>% dplyr::select(all_of(c(group.var,strata.var,time.var)))
219215
}
220216
}
221217

@@ -263,7 +259,7 @@ generate_beta_ordination_single <-
263259
as.data.frame() %>%
264260
rownames_to_column("sample") %>%
265261
dplyr::left_join(meta_tab %>%
266-
dplyr::select(all_of(c(subject.var, time.var, group.var, strata.var))) %>%
262+
dplyr::select(all_of(c(time.var, group.var, strata.var))) %>%
267263
rownames_to_column("sample"), by = "sample")
268264

269265
# Filter out NA values in time variable if it exists
@@ -362,17 +358,10 @@ generate_beta_ordination_single <-
362358

363359
# Save the plot as a PDF file if requested
364360
if (pdf) {
365-
pdf_name <- paste0(
366-
"beta_ordination_single_",
367-
"subject_",
368-
subject.var,
369-
"_",
370-
"time_",
371-
time.var,
372-
"_",
373-
"dist.name_",
374-
dist.name
375-
)
361+
pdf_name <- paste0("beta_ordination_single_", "dist.name_", dist.name)
362+
if (!is.null(time.var)) {
363+
pdf_name <- paste0(pdf_name, "_", "time_", time.var)
364+
}
376365
if (!is.null(group.var)) {
377366
pdf_name <- paste0(pdf_name, "_", "group_", group.var)
378367
}

R/generate_beta_test_single.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ generate_beta_test_single <- function(data.obj,
163163

164164
formula <- as.formula(formula_str)
165165

166+
# Ensure .Random.seed exists (PermanovaG2 requires it)
167+
# This initializes the RNG state if it hasn't been used yet
168+
if (!exists(".Random.seed", envir = globalenv())) {
169+
set.seed(NULL) # Initialize RNG with system seed
170+
}
171+
166172
# Run PermanovaG2 for all distance matrices
167173
# PERMANOVA is a non-parametric multivariate statistical test used to assess the significance of compositional differences among groups
168174
message("Running PermanovaG2 for all distances...")

R/generate_taxa_areaplot_long.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,9 @@ generate_taxa_areaplot_long <-
298298
otu_tax_agg <- data.obj$feature.tab
299299
}
300300

301-
# Subset features if specified
301+
# Subset features if specified (using %in% for robustness against NA or non-existent features)
302302
if (!is.null(features.plot)){
303-
otu_tax_agg <- otu_tax_agg[na.omit(features.plot),]
303+
otu_tax_agg <- otu_tax_agg[rownames(otu_tax_agg) %in% features.plot,]
304304
}
305305

306306
# Prepare the feature table for analysis

R/generate_taxa_barplot_long.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,9 @@ generate_taxa_barplot_long <-
317317
otu_tax_agg <- data.obj$feature.tab
318318
}
319319

320-
# Subset features if specified
320+
# Subset features if specified (using %in% for robustness against NA or non-existent features)
321321
if (!is.null(features.plot)){
322-
otu_tax_agg <- otu_tax_agg[na.omit(features.plot),]
322+
otu_tax_agg <- otu_tax_agg[rownames(otu_tax_agg) %in% features.plot,]
323323
}
324324

325325
# Prepare the feature table for analysis

0 commit comments

Comments
 (0)