This vignette demonstrates the same build_contrast_analysis() facade workflow
on a dataset with two factors (e.g. treatment and genotype), yielding four
subgroups: C_WT, T_WT, C_KO, T_KO. We define contrasts:
T_C_gv_WT = T_WT - C_WTT_C_gv_KO = T_KO - C_KOWT_KO_comp = T_C_gv_WT - T_C_gv_KOWe start from simulated two-factor peptide data, derive a single subgroup factor,
and run both protein-input and peptide-input facades with the same contrast
specification. See ContrastFacades.Rmd for the one-factor introduction.
dd <- sim_lfq_data_2factor_config(
Nprot = 80,
with_missing = TRUE,
weight_missing = 1,
PEPTIDE = TRUE,
seed = 7
)
cfg_subgroup <- dd$config$clone(deep = TRUE)
data_subgroup <- dd$data |>
dplyr::mutate(
Condition = dplyr::recode(Treatment, A = "C", B = "T"),
Genotype = dplyr::recode(Background, Z = "WT", X = "KO"),
Subgroup = paste(Condition, Genotype, sep = "_")
)
cfg_subgroup$factors <- c(Subgroup = "Subgroup")
cfg_subgroup$factor_depth <- 1
lfq_peptide_2f <- LFQData$new(data_subgroup, cfg_subgroup)
lfq_peptide_2f <- lfq_peptide_2f$get_Transformer()$log2()$lfq
lfq_protein_2f <- lfq_peptide_2f$get_Aggregator()$aggregate()
lfq_peptide_2f$hierarchy_keys()
## [1] "protein_Id" "peptide_Id"
lfq_protein_2f$hierarchy_keys()
## [1] "protein_Id"
lfq_protein_2f$nr_children_col()
## [1] "nr_children_protein_Id"
contrasts_2f <- c(
T_C_gv_WT = "SubgroupT_WT - SubgroupC_WT",
T_C_gv_KO = "SubgroupT_KO - SubgroupC_KO",
WT_KO_comp = "T_C_gv_WT - T_C_gv_KO"
)
Three contrasts: two within-genotype treatment effects and their difference (interaction-like comparison).
The following facades require aggregated input. firth is included here
because it can be fitted directly on aggregated protein input.
fa_lm_2f <- build_contrast_analysis(
lfq_protein_2f,
"~ Subgroup",
contrasts_2f,
method = "lm"
)
fa_limma_2f <- build_contrast_analysis(
lfq_protein_2f,
"~ Subgroup",
contrasts_2f,
method = "limma"
)
fa_limma_impute_2f <- build_contrast_analysis(
lfq_protein_2f,
"~ Subgroup",
contrasts_2f,
method = "limma_impute"
)
fa_deqms_2f <- build_contrast_analysis(
lfq_protein_2f,
"~ Subgroup",
contrasts_2f,
method = "deqms"
)
fa_lm_impute_2f <- build_contrast_analysis(
lfq_protein_2f,
"~ Subgroup",
contrasts_2f,
method = "lm_impute"
)
fa_firth_protein_2f <- build_contrast_analysis(
lfq_protein_2f,
"~ Subgroup",
contrasts_2f,
method = "firth"
)
Because all protein-input facades share the same interface and report protein-level contrasts, their outputs can be combined directly.
# Proteins missing in the baseline lm facade (used to flag rescued proteins)
lm_missing_ids_2f <- fa_lm_2f$get_missing() |>
dplyr::select(protein_Id, contrast) |>
dplyr::mutate(rescued = TRUE)
results_protein_2f <- bind_rows(
fa_lm_2f$get_contrasts(),
fa_limma_2f$get_contrasts(),
fa_limma_impute_2f$get_contrasts(),
fa_lm_impute_2f$get_contrasts(),
fa_deqms_2f$get_contrasts(),
fa_firth_protein_2f$get_contrasts()
) |>
dplyr::select(dplyr::any_of(c(
"modelName", "estimate_type", "protein_Id", "contrast", "avgAbd", "diff", "FDR",
"statistic", "std.error", "df", "p.value", "conf.low", "conf.high",
"sigma"
))) |>
dplyr::left_join(lm_missing_ids_2f, by = c("protein_Id", "contrast")) |>
dplyr::mutate(
rescued = dplyr::coalesce(rescued, FALSE),
significant = FDR < 0.1 & abs(diff) > 0.5
)
results_protein_2f |>
dplyr::count(modelName, name = "n_results")
## # A tibble: 6 × 2
## modelName n_results
## <chr> <int>
## 1 deqms 232
## 2 firth 240
## 3 limma 232
## 4 limma_impute 240
## 5 lm 232
## 6 lm_impute 240
The modelName column is the facade key. For facades that combine several
underlying result types, such as lm_impute, the estimate_type column tells
you how each row was produced (observed or lod_imputed).
results_protein_2f |>
dplyr::count(modelName, contrast, estimate_type, name = "n_results")
## # A tibble: 24 × 4
## modelName contrast estimate_type n_results
## <chr> <chr> <chr> <int>
## 1 deqms T_C_gv_KO observed 79
## 2 deqms T_C_gv_WT observed 77
## 3 deqms WT_KO_comp observed 76
## 4 firth T_C_gv_KO observed 80
## 5 firth T_C_gv_WT observed 80
## 6 firth WT_KO_comp observed 80
## 7 limma T_C_gv_KO observed 79
## 8 limma T_C_gv_WT observed 77
## 9 limma WT_KO_comp observed 76
## 10 limma_impute T_C_gv_KO lod_imputed 4
## # ℹ 14 more rows
standard_facades_2f <- c("lm", "limma", "deqms")
results_standard_2f <- results_protein_2f |>
dplyr::filter(modelName %in% standard_facades_2f)
ggplot(results_standard_2f, aes(x = diff, y = -log10(p.value), color = significant)) +
geom_point(alpha = 0.6, size = 1.5) +
facet_grid(contrast ~ modelName, scales = "free_y") +
geom_vline(xintercept = c(-0.5, 0.5), linetype = "dashed", color = "grey60") +
geom_hline(yintercept = -log10(0.1), linetype = "dashed", color = "grey60") +
scale_color_manual(values = c(`TRUE` = "firebrick", `FALSE` = "grey70")) +
labs(x = "log2 fold change", y = "-log10(p.value)", color = "FDR < 0.1\nand |diff| > 0.5") +
theme_minimal(base_size = 12)
(#fig:volcano_standard_2f)Volcano plots for the standard protein-level facades (lm, limma, deqms).
Rescued proteins (missing in plain lm) are shown as large red diamonds
so they stand out clearly. This group includes the LOD imputation facades
(lm_impute, limma_impute) and the firth logistic
regression facade which models missingness directly.
impute_facades_2f <- c("lm_impute", "limma_impute", "firth")
results_impute_2f <- results_protein_2f |>
dplyr::filter(modelName %in% impute_facades_2f) |>
dplyr::mutate(modelName = factor(modelName, levels = impute_facades_2f))
ggplot(results_impute_2f, aes(x = diff, y = -log10(p.value))) +
geom_point(data = dplyr::filter(results_impute_2f, !rescued),
aes(color = significant), alpha = 0.5, size = 1.2) +
geom_point(data = dplyr::filter(results_impute_2f, rescued),
color = "red", shape = 18, size = 5, alpha = 1) +
facet_grid(contrast ~ modelName, scales = "free_y") +
geom_vline(xintercept = c(-0.5, 0.5), linetype = "dashed", color = "grey60") +
geom_hline(yintercept = -log10(0.1), linetype = "dashed", color = "grey60") +
scale_color_manual(values = c(`TRUE` = "firebrick", `FALSE` = "grey70")) +
labs(x = "log2 fold change", y = "-log10(p.value)", color = "FDR < 0.1\nand |diff| > 0.5") +
theme_minimal(base_size = 12)
(#fig:volcano_impute_2f)Volcano plots for the imputation and missingness facades. Large red diamonds mark proteins rescued (missing in plain lm).
results_protein_2f |>
dplyr::group_by(modelName, contrast) |>
dplyr::slice_min(order_by = p.value, n = 5, with_ties = FALSE) |>
dplyr::ungroup() |>
dplyr::select(modelName, estimate_type, contrast, protein_Id, diff, p.value, FDR)
## # A tibble: 90 × 7
## modelName estimate_type contrast protein_Id diff p.value FDR
## <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 deqms observed T_C_gv_KO qc8ZRR~4628 0.628 2.16e-13 1.71e-11
## 2 deqms observed T_C_gv_KO H7jUye~2322 0.493 2.01e-10 7.94e- 9
## 3 deqms observed T_C_gv_KO zO74Fn~0389 -0.342 4.69e-10 1.01e- 8
## 4 deqms observed T_C_gv_KO lRuJ5o~6058 0.542 5.11e-10 1.01e- 8
## 5 deqms observed T_C_gv_KO uLYRH7~7195 0.588 1.51e- 9 2.35e- 8
## 6 deqms observed T_C_gv_WT uLYRH7~7195 -0.904 5.36e-11 4.12e- 9
## 7 deqms observed T_C_gv_WT qc8ZRR~4628 0.420 1.88e-10 7.24e- 9
## 8 deqms observed T_C_gv_WT HnBvvB~5903 0.335 1.20e- 9 3.07e- 8
## 9 deqms observed T_C_gv_WT IPV3OT~3010 0.467 2.42e- 9 4.66e- 8
## 10 deqms observed T_C_gv_WT lCgO3j~8152 0.402 4.22e- 9 6.41e- 8
## # ℹ 80 more rows
Every facade has a get_missing() method that returns the protein x contrast
pairs present in the input data but absent from get_contrasts(). This makes
it easy to see which proteins each method fails on and to compare coverage.
missing_all_2f <- dplyr::bind_rows(
fa_lm_2f$get_missing() |> dplyr::mutate(facade = "lm"),
fa_limma_2f$get_missing() |> dplyr::mutate(facade = "limma"),
fa_limma_impute_2f$get_missing() |> dplyr::mutate(facade = "limma_impute"),
fa_lm_impute_2f$get_missing() |> dplyr::mutate(facade = "lm_impute"),
fa_deqms_2f$get_missing() |> dplyr::mutate(facade = "deqms"),
fa_firth_protein_2f$get_missing() |> dplyr::mutate(facade = "firth")
)
missing_all_2f |>
dplyr::count(facade, contrast, name = "n_missing") |>
knitr::kable(caption = "Number of missing protein x contrast pairs per facade")
| facade | contrast | n_missing |
|---|---|---|
| deqms | T_C_gv_KO | 1 |
| deqms | T_C_gv_WT | 3 |
| deqms | WT_KO_comp | 4 |
| limma | T_C_gv_KO | 1 |
| limma | T_C_gv_WT | 3 |
| limma | WT_KO_comp | 4 |
| lm | T_C_gv_KO | 1 |
| lm | T_C_gv_WT | 3 |
| lm | WT_KO_comp | 4 |
missing_proteins_2f <- unique(missing_all_2f$protein_Id)
if (length(missing_proteins_2f) > 0) {
lfq_protein_2f$data_long() |>
dplyr::filter(protein_Id %in% missing_proteins_2f) |>
dplyr::select(protein_Id, sampleName,
!!rlang::sym(lfq_protein_2f$response())) |>
tidyr::pivot_wider(names_from = sampleName,
values_from = !!rlang::sym(lfq_protein_2f$response())) |>
knitr::kable(digits = 2, caption = "Per-sample intensities of proteins that could not be estimated")
}
| protein_Id | A_V1 | A_V2 | A_V3 | A_V4 | B_V1 | B_V2 | B_V3 | B_V4 | C_V1 | C_V2 | C_V3 | C_V4 | Ctrl_V1 | Ctrl_V2 | Ctrl_V3 | Ctrl_V4 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| QQg7IC~3558 | 3.98 | NA | NA | 3.83 | 4.34 | 4.31 | 4.36 | 4.31 | 4.38 | 4.31 | NA | 4.41 | NA | NA | NA | NA |
| hjVK4f~9433 | NA | NA | 3.88 | NA | 4.42 | 4.35 | 4.28 | 4.29 | NA | NA | NA | NA | NA | 3.68 | NA | 3.86 |
| mVseto~9392 | 4.40 | 4.50 | 4.47 | NA | 4.67 | 4.63 | 4.66 | 4.69 | 4.62 | 4.72 | 4.54 | 4.64 | NA | NA | NA | NA |
| zvzYsk~2881 | NA | 3.79 | 3.92 | NA | NA | NA | NA | NA | NA | 3.83 | NA | 3.92 | 4.18 | 4.17 | NA | NA |
The missing cells (NA) explain why these proteins cannot be estimated — they
lack observations in one or more groups. The lm_impute and limma_impute facades
re-fit after imputing individual values with the LOD and borrowing covariance
from successful fits. These should have fewer missing proteins than plain
lm or limma.
lm_impute and limma_imputeFor proteins that plain lm could not estimate, the imputation-based facades
can still produce contrast results. The table below shows these rescued
estimates side by side.
lm_missing_proteins_2f <- fa_lm_2f$get_missing()$protein_Id |> unique()
if (length(lm_missing_proteins_2f) > 0) {
rescued_2f <- results_protein_2f |>
dplyr::filter(
protein_Id %in% lm_missing_proteins_2f,
modelName %in% c("lm_impute", "limma_impute")
) |>
dplyr::arrange(protein_Id, contrast, modelName)
rescued_2f |>
knitr::kable(
digits = 3,
caption = "Contrast estimates from lm_impute and limma_impute for proteins that plain lm could not estimate"
)
} else {
cat("All proteins were estimable by plain lm — no rescued estimates to show.")
}
| modelName | estimate_type | protein_Id | contrast | avgAbd | diff | FDR | statistic | std.error | df | p.value | conf.low | conf.high | sigma | rescued | significant |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| limma_impute | lod_imputed | QQg7IC~3558 | T_C_gv_KO | 4.125 | 0.411 | 0.002 | 5.353 | 0.077 | 8.398 | 0.001 | 0.235 | 0.587 | 0.109 | FALSE | FALSE |
| lm_impute | lod_imputed | QQg7IC~3558 | T_C_gv_KO | 4.125 | 0.411 | 0.001 | 5.648 | 0.073 | 8.380 | 0.000 | 0.245 | 0.578 | 0.103 | FALSE | FALSE |
| limma_impute | lod_imputed | QQg7IC~3558 | T_C_gv_WT | 4.075 | 0.351 | 0.005 | 4.568 | 0.077 | 8.398 | 0.002 | 0.175 | 0.526 | 0.109 | TRUE | FALSE |
| lm_impute | lod_imputed | QQg7IC~3558 | T_C_gv_WT | 4.075 | 0.351 | 0.003 | 4.819 | 0.073 | 8.380 | 0.001 | 0.184 | 0.517 | 0.103 | TRUE | FALSE |
| limma_impute | lod_imputed | QQg7IC~3558 | WT_KO_comp | 0.381 | -0.060 | 0.688 | -0.556 | 0.109 | 8.398 | 0.593 | -0.309 | 0.188 | 0.109 | TRUE | FALSE |
| lm_impute | lod_imputed | QQg7IC~3558 | WT_KO_comp | 0.381 | -0.060 | 0.665 | -0.586 | 0.103 | 8.380 | 0.573 | -0.296 | 0.175 | 0.103 | TRUE | FALSE |
| limma_impute | lod_imputed | hjVK4f~9433 | T_C_gv_KO | 4.118 | 0.435 | 0.003 | 5.705 | 0.076 | 6.398 | 0.001 | 0.251 | 0.620 | 0.108 | FALSE | FALSE |
| lm_impute | lod_imputed | hjVK4f~9433 | T_C_gv_KO | 4.118 | 0.435 | 0.002 | 5.954 | 0.073 | 6.380 | 0.001 | 0.259 | 0.612 | 0.103 | FALSE | FALSE |
| limma_impute | lod_imputed | hjVK4f~9433 | T_C_gv_WT | 3.900 | 0.000 | 1.000 | 0.000 | 0.076 | 6.398 | 1.000 | -0.184 | 0.184 | 0.108 | TRUE | FALSE |
| lm_impute | lod_imputed | hjVK4f~9433 | T_C_gv_WT | 3.900 | 0.000 | 1.000 | 0.000 | 0.073 | 6.380 | 1.000 | -0.176 | 0.176 | 0.103 | TRUE | FALSE |
| limma_impute | lod_imputed | hjVK4f~9433 | WT_KO_comp | 0.218 | -0.435 | 0.015 | -4.034 | 0.108 | 6.398 | 0.006 | -0.696 | -0.175 | 0.108 | TRUE | FALSE |
| lm_impute | lod_imputed | hjVK4f~9433 | WT_KO_comp | 0.218 | -0.435 | 0.013 | -4.210 | 0.103 | 6.380 | 0.005 | -0.685 | -0.186 | 0.103 | TRUE | FALSE |
| limma_impute | lod_imputed | mVseto~9392 | T_C_gv_KO | 4.519 | 0.280 | 0.002 | 4.803 | 0.058 | 10.398 | 0.001 | 0.151 | 0.409 | 0.109 | FALSE | FALSE |
| lm_impute | lod_imputed | mVseto~9392 | T_C_gv_KO | 4.519 | 0.280 | 0.001 | 5.101 | 0.055 | 10.380 | 0.000 | 0.158 | 0.402 | 0.103 | FALSE | FALSE |
| limma_impute | lod_imputed | mVseto~9392 | T_C_gv_WT | 4.271 | 0.742 | 0.000 | 11.611 | 0.064 | 10.398 | 0.000 | 0.600 | 0.883 | 0.109 | TRUE | TRUE |
| lm_impute | lod_imputed | mVseto~9392 | T_C_gv_WT | 4.271 | 0.742 | 0.000 | 11.531 | 0.064 | 10.380 | 0.000 | 0.599 | 0.884 | 0.103 | TRUE | TRUE |
| limma_impute | lod_imputed | mVseto~9392 | WT_KO_comp | 0.511 | 0.462 | 0.002 | 5.145 | 0.090 | 10.398 | 0.000 | 0.263 | 0.661 | 0.109 | TRUE | FALSE |
| lm_impute | lod_imputed | mVseto~9392 | WT_KO_comp | 0.511 | 0.462 | 0.001 | 5.463 | 0.085 | 10.380 | 0.000 | 0.274 | 0.649 | 0.103 | TRUE | FALSE |
| limma_impute | lod_imputed | zvzYsk~2881 | T_C_gv_KO | 3.902 | -0.004 | 0.982 | -0.054 | 0.072 | 5.398 | 0.959 | -0.185 | 0.177 | 0.107 | TRUE | FALSE |
| lm_impute | lod_imputed | zvzYsk~2881 | T_C_gv_KO | 3.902 | -0.004 | 0.982 | -0.056 | 0.070 | 5.380 | 0.957 | -0.179 | 0.171 | 0.104 | TRUE | FALSE |
| limma_impute | lod_imputed | zvzYsk~2881 | T_C_gv_WT | 3.971 | -0.133 | 0.178 | -1.902 | 0.070 | 5.398 | 0.111 | -0.310 | 0.043 | 0.107 | FALSE | FALSE |
| lm_impute | lod_imputed | zvzYsk~2881 | T_C_gv_WT | 3.971 | -0.133 | 0.172 | -1.915 | 0.070 | 5.380 | 0.110 | -0.309 | 0.042 | 0.104 | FALSE | FALSE |
| limma_impute | lod_imputed | zvzYsk~2881 | WT_KO_comp | -0.069 | -0.129 | 0.360 | -1.269 | 0.102 | 5.398 | 0.256 | -0.386 | 0.127 | 0.107 | TRUE | FALSE |
| lm_impute | lod_imputed | zvzYsk~2881 | WT_KO_comp | -0.069 | -0.129 | 0.339 | -1.315 | 0.098 | 5.380 | 0.242 | -0.377 | 0.118 | 0.104 | TRUE | FALSE |
The mixed-effects lmer_nested facade and ropeca_nested require lower-level
measurements below the analysis subject. The firth_nested facade is the
peptide-input variant of firth shown above. All three still return
protein-level contrasts.
fa_lmer_2f <- build_contrast_analysis(
lfq_peptide_2f,
"~ Subgroup + (1 | peptide_Id) + (1 | sampleName)",
contrasts_2f,
method = "lmer_nested"
)
fa_ropeca_2f <- build_contrast_analysis(
lfq_peptide_2f,
"~ Subgroup",
contrasts_2f,
method = "ropeca_nested"
)
fa_firth_peptide_2f <- build_contrast_analysis(
lfq_peptide_2f,
"~ Subgroup",
contrasts_2f,
method = "firth_nested"
)
results_peptide_2f <- bind_rows(
fa_lmer_2f$get_contrasts(),
fa_ropeca_2f$get_contrasts(),
fa_firth_peptide_2f$get_contrasts()
) |>
dplyr::select(dplyr::any_of(c(
"modelName", "estimate_type", "protein_Id", "contrast", "avgAbd", "diff", "FDR",
"statistic", "std.error", "df", "p.value", "conf.low", "conf.high",
"sigma"
))) |>
dplyr::mutate(
significant = FDR < 0.1 & abs(diff) > 0.5
)
results_peptide_2f |>
dplyr::count(modelName, name = "n_results")
## # A tibble: 3 × 2
## modelName n_results
## <chr> <int>
## 1 firth_nested 240
## 2 lmer_nested 179
## 3 ropeca_nested 231
ggplot(results_peptide_2f, aes(x = diff, y = -log10(p.value), color = significant)) +
geom_point(alpha = 0.6, size = 1.2) +
facet_grid(contrast ~ modelName, scales = "free_y") +
geom_vline(xintercept = c(-0.5, 0.5), linetype = "dashed", color = "grey60") +
geom_hline(yintercept = -log10(0.1), linetype = "dashed", color = "grey60") +
scale_color_manual(values = c(`TRUE` = "firebrick", `FALSE` = "grey70")) +
labs(
x = "log2 fold change",
y = "-log10(p.value)",
color = "FDR < 0.1\nand |diff| > 0.5"
) +
theme_minimal(base_size = 12)
(#fig:volcano_peptide_2f)Volcano plots for the peptide-level facades. Rows are contrasts, columns are backends.
The facades make it easy to benchmark alternative contrast backends without rewriting the analysis pipeline:
The results are comparable at the API level, but the comparison is only meaningful when methods using the same biological unit are plotted together.
sessionInfo()
## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.5 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.24-bioc/R/lib/libRblas.so
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0 LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_GB LC_COLLATE=C
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: America/New_York
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggplot2_4.0.3 prolfqua_0.99.8 dplyr_1.2.1 BiocStyle_2.41.0
##
## loaded via a namespace (and not attached):
## [1] RColorBrewer_1.1-3 jsonlite_2.0.0 shape_1.4.6.1
## [4] magrittr_2.0.5 TH.data_1.1-5 estimability_2.0.0
## [7] jomo_2.7-6 magick_2.9.1 farver_2.1.2
## [10] logistf_1.26.1 nloptr_2.2.1 rmarkdown_2.32
## [13] GlobalOptions_0.1.4 vctrs_0.7.3 Cairo_1.7-0
## [16] minqa_1.2.8 tinytex_0.61 htmltools_0.5.9
## [19] forcats_1.0.1 progress_1.2.3 broom_1.0.13
## [22] mitml_0.4-5 sass_0.4.10 KernSmooth_2.23-27
## [25] bslib_0.12.0 htmlwidgets_1.6.4 plyr_1.8.9
## [28] sandwich_3.1-3 emmeans_2.0.4 plotly_4.12.1
## [31] zoo_1.9-1 cachem_1.1.0 mime_0.13
## [34] lifecycle_1.0.5 iterators_1.0.14 pkgconfig_2.0.3
## [37] Matrix_1.7-6 R6_2.6.1 fastmap_1.2.0
## [40] rbibutils_2.4.1 shiny_1.14.0 clue_0.3-68
## [43] digest_0.6.39 numDeriv_2016.8-1.1 colorspace_2.1-4
## [46] S4Vectors_0.51.10 crosstalk_1.2.2 labeling_0.4.3
## [49] httr_1.4.9 mgcv_1.9-5 compiler_4.6.1
## [52] withr_3.0.3 doParallel_1.0.17 S7_0.2.2
## [55] backports_1.5.1 UpSetR_1.4.1 pan_2.0
## [58] MASS_7.3-66 rjson_0.2.23 tools_4.6.1
## [61] otel_0.2.0 httpuv_1.6.17 nnet_7.3-21
## [64] glue_1.8.1 nlme_3.1-172 promises_1.5.0
## [67] grid_4.6.1 cluster_2.1.8.3 generics_0.1.4
## [70] operator.tools_1.6.3.1 gtable_0.3.6 formula.tools_1.7.1
## [73] tidyr_1.3.2 data.table_1.18.6.1 hms_1.1.4
## [76] utf8_1.2.6 BiocGenerics_0.59.12 ggrepel_0.9.8
## [79] foreach_1.5.2 pillar_1.11.1 limma_3.99.4
## [82] later_1.4.8 circlize_0.4.18 splines_4.6.1
## [85] lattice_0.23-1 survival_3.8-12 tidyselect_1.2.1
## [88] ComplexHeatmap_2.29.0 knitr_1.52 reformulas_0.4.4
## [91] gridExtra_2.3.1 bookdown_0.48 IRanges_2.47.5
## [94] stats4_4.6.1 xfun_0.62 statmod_1.5.2
## [97] matrixStats_1.5.0 stringi_1.8.9 yaml_2.3.12
## [100] boot_1.3-32 evaluate_1.0.5 codetools_0.2-20
## [103] Rfit_0.27.0 tibble_3.3.1 BiocManager_1.30.27
## [106] cli_3.6.6 rpart_4.1.27 xtable_1.8-8
## [109] Rdpack_2.6.6 jquerylib_0.1.4 dichromat_2.0-1
## [112] Rcpp_1.1.2 coda_0.19-4.1 png_0.1-9
## [115] parallel_4.6.1 prettyunits_1.2.0 lme4_2.1-0
## [118] glmnet_5.2 viridisLite_0.4.3 limpa_1.5.2
## [121] mvtnorm_1.4-2 lmerTest_3.2-1 scales_1.4.0
## [124] purrr_1.2.2 crayon_1.5.3 GetoptLong_1.1.1
## [127] rlang_1.3.0 multcomp_1.4-32 mice_3.19.0