Introduction to Metabolomics Data
The Danish Project Project studies metabolic changes during human pregnancy and if these altered metabolites could be used to predict preterm.
Referenced research
Introduction to tidyMass
project
TidyMass is an ecosystem of R packages that share an underlying design philosophy, grammar, and data structure, which provides a comprehensive, reproducible, and object-oriented computational framework. The modular architecture makes tidyMass a highly flexible and extensible tool, which other users can improve and integrate with other tools to customize their own pipeline.
More information about tidyMass could be found here: tidymass.org.
Hopefully, at the end of this module, you will have a better sense of the metabolomics data analysis procedure and how to use R for reproducible data processing and analysis
Data preparation
Download the demo data and uncompress it.
-
If you can use Google drive, download here. (code 2022)
The demo data contains RPLC positive mode, with 7 participants, and two samples for each participant (Trimester 1 (< 10 weeks) and trimester 3 (> 30 weeks)). So there are 14 samples in total.
-
MS1
: MS1 is the folder contains the mzXML for 14 samples. -
MS2
: MS2 is the folder contains the mgf for QC samples (MS2 spectra). -
sample_info.xlsx
: it is the metadata for samples.
![](/docs/chapter10/figures/Screen-Shot 1.png)
Raw data processing
library(tidymass)
#> Registered S3 method overwritten by 'Hmisc':
#> method from
#> vcov.default fit.models
#> ── Attaching packages ──────────────────────────────────────── tidymass 1.0.8 ──
#> ✔ massdataset 1.0.25 ✔ metid 1.2.28
#> ✔ massprocesser 1.0.10 ✔ masstools 1.0.10
#> ✔ masscleaner 1.0.11 ✔ dplyr 1.1.2
#> ✔ massqc 1.0.6 ✔ ggplot2 3.4.2
#> ✔ massstat 1.0.5 ✔ magrittr 2.0.3
#> ✔ metpath 1.0.8
library(tidyverse)
#> ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
#> ✔ forcats 1.0.0 ✔ readr 2.1.4
#> ✔ lubridate 1.9.2 ✔ stringr 1.5.0
#> ✔ purrr 1.0.1 ✔ tibble 3.2.1
#> ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
#> ✖ xcms::collect() masks dplyr::collect()
#> ✖ MSnbase::combine() masks Biobase::combine(), BiocGenerics::combine(), dplyr::combine()
#> ✖ tidyr::expand() masks S4Vectors::expand()
#> ✖ tidyr::extract() masks magrittr::extract()
#> ✖ metid::filter() masks metpath::filter(), dplyr::filter(), massdataset::filter(), stats::filter()
#> ✖ S4Vectors::first() masks dplyr::first()
#> ✖ xcms::groups() masks dplyr::groups()
#> ✖ dplyr::lag() masks stats::lag()
#> ✖ purrr::map() masks mixOmics::map()
#> ✖ BiocGenerics::Position() masks ggplot2::Position(), base::Position()
#> ✖ purrr::reduce() masks MSnbase::reduce()
#> ✖ S4Vectors::rename() masks dplyr::rename(), massdataset::rename()
#> ✖ lubridate::second() masks S4Vectors::second()
#> ✖ lubridate::second<-() masks S4Vectors::second<-()
#> ✖ MASS::select() masks dplyr::select(), massdataset::select()
#> ✖ purrr::set_names() masks magrittr::set_names()
#> ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
massprocesser
package in tidymass
is used to do the raw data processing. Please refer this website.
The code used to do raw data processing (peak picking, peak grouping).
massprocesser::process_data(
path = "cell_liang_2020/MS1/",
polarity = "positive",
ppm = 10,
peakwidth = c(5, 30),
threads = 4,
output_tic = TRUE,
output_bpc = TRUE,
output_rt_correction_plot = FALSE,
min_fraction = 0.5
)
All the results will be placed in the folder named MS1/Result
. More information about that can be found here.
![](/docs/chapter10/figures/Screen-Shot 2.png)
-
BPC.pdf: BPC plot.
-
TIC.pdf: TIC plot.
-
RT correction plot.pdf: Retention time correction plot.
-
Peak_table.csv: Peak table.
-
Peak_table_for_cleaning.csv: Peak table which can be used for data cleaning.
-
object:
mass_dataset
class object which can be used for subsequent analysis using tidymass. -
intermediate_data: intermediate data.
You can just load the object
, which is a mass_dataset
class object.
load("cell_liang_2020/MS1/Result/object")
object
#> --------------------
#> massdataset version: 1.0.12
#> --------------------
#> 1.expression_data:[ 9164 x 14 data.frame]
#> 2.sample_info:[ 14 x 4 data.frame]
#> 14 samples:184 214 289 ... 528 739
#> 3.variable_info:[ 9164 x 3 data.frame]
#> 9164 variables:M71T823_POS M72T34_POS M72T822_POS ... M994T593_POS M995T593_POS
#> 4.sample_info_note:[ 4 x 2 data.frame]
#> 5.variable_info_note:[ 3 x 2 data.frame]
#> 6.ms2_data:[ 0 variables x 0 MS2 spectra]
#> --------------------
#> Processing information
#> 2 processings in total
#> create_mass_dataset ----------
#> Package Function.used Time
#> 1 massdataset create_mass_dataset() 2022-08-07 16:44:32
#> process_data ----------
#> Package Function.used Time
#> 1 massprocesser process_data 2022-08-07 16:44:28
dim(object)
#> variables samples
#> 9164 14
We can get basic information from the object.
We have 9164 variables, 14 samples.
You can use the plot_adjusted_rt()
function to get the interactive plot.
load("cell_liang_2020/MS1/Result/intermediate_data/xdata2")
####set the group_for_figure if you want to show specific groups.
####And set it as "all" if you want to show all samples.
plot <-
plot_adjusted_rt(object = xdata2,
group_for_figure = "Subject",
interactive = TRUE)
plot
Explore data
After the raw data processing
, peak tables will be generated.
load("cell_liang_2020/MS1/Result/object")
dim(object)
#> variables samples
#> 9164 14
We neet to update the sample_info in object.
Read sample information.
sample_info <-
readxl::read_xlsx("cell_liang_2020/sample_info.xlsx")
sample_info$sample_id <-
as.character(sample_info$sample_id)
Add sample_info
to object
object %>%
extract_sample_info() %>%
head()
#> sample_id group class injection.order
#> 1 184 Subject Subject 1
#> 2 214 Subject Subject 2
#> 3 289 Subject Subject 3
#> 4 317 Subject Subject 4
#> 5 320 Subject Subject 5
#> 6 327 Subject Subject 6
object <-
object %>%
activate_mass_dataset(what = "sample_info") %>%
left_join(sample_info,
by = "sample_id")
object %>%
extract_sample_info()
#> sample_id group class injection.order subject_id trimester
#> 1 184 Subject Subject 1 aaf >35
#> 2 214 Subject Subject 2 aaf <10
#> 3 289 Subject Subject 3 ace >35
#> 4 317 Subject Subject 4 acb <10
#> 5 320 Subject Subject 5 abb <10
#> 6 327 Subject Subject 6 aci <10
#> 7 348 Subject Subject 7 abi >35
#> 8 353 Subject Subject 8 abg >35
#> 9 373 Subject Subject 9 aci >35
#> 10 387 Subject Subject 10 abg <10
#> 11 408 Subject Subject 11 abi <10
#> 12 461 Subject Subject 12 acb >35
#> 13 528 Subject Subject 13 abb >35
#> 14 739 Subject Subject 14 ace <10
object %>%
activate_mass_dataset(what = "sample_info") %>%
dplyr::count(class)
#> class n
#> 1 Subject 14
object %>%
activate_mass_dataset(what = "sample_info") %>%
dplyr::count(group)
#> group n
#> 1 Subject 14
object %>%
activate_mass_dataset(what = "sample_info") %>%
dplyr::count(trimester)
#> trimester n
#> 1 <10 7
#> 2 >35 7
So for the data, we have 7 subjects and 14 samples. One subject has two samples.
Next, we can get the peak distributation plot.
object %>%
`+`(1) %>%
log(10) %>%
show_mz_rt_plot() +
scale_size_continuous(range = c(0.01, 2))
We can explore the missing values in the data.
get_mv_number(object = object)
#> [1] 26696
sum(is.na(object))
#> [1] 26696
26,696 mvs in total.
Missing value number in each sample.
get_mv_number(object = object, by = "variable") %>%
head()
#> M71T823_POS M72T34_POS M72T822_POS M73T36_POS M74T584_POS M75T47_POS
#> 0 6 0 0 5 7
Missing value number in each variable.
We can use the figure to show the missing value information.
show_missing_values(object = object,
show_column_names = FALSE, percentage = TRUE)
Show the mvs in samples
show_sample_missing_values(object = object, percentage = TRUE)
Show the mvs in variables
show_variable_missing_values(object = object,
percentage = TRUE,
show_x_text = FALSE,
show_x_ticks = FALSE) +
scale_size_continuous(range = c(0.01, 1))
Data cleaning
Data quality assessment before data cleaning
Here, we can use the massqc
package to assess the data quality.
We can just use the massqc_report()
function to get a html format quality assessment report.
massqc::massqc_report(object = object,
path = "cell_liang_2020/data_cleaning/data_quality_before_data_cleaning")
A html format report and pdf figures will be placed in the folder cell_liang_2020/data_cleaning/data_quality_before_data_cleaning/Report
.
![](/docs/chapter10/figures/Screen-Shot 5.png)
The html report is below:
![](/docs/chapter10/figures/Screen-Shot 6.png)
Remove noisy metabolic features
Remove variables which have MVs in more than 20% samples.
show_variable_missing_values(object = object,
percentage = TRUE) +
scale_size_continuous(range = c(0.01, 2))
object =
object %>%
mutate_variable_na_freq()
head(extract_variable_info(object))
#> variable_id mz rt na_freq
#> 1 M71T823_POS 70.98037 823.24475 0.0000000
#> 2 M72T34_POS 71.90757 33.84428 0.4285714
#> 3 M72T822_POS 71.98733 822.28662 0.0000000
#> 4 M73T36_POS 73.02834 36.06493 0.0000000
#> 5 M74T584_POS 73.70056 584.35419 0.3571429
#> 6 M75T47_POS 74.81906 46.72005 0.5000000
Remove variables.
object <-
object %>%
activate_mass_dataset(what = "variable_info") %>%
filter(na_freq < 0.2)
dim(object)
#> variables samples
#> 4537 14
Only 4,537 variables left.
Filter outlier samples
We can use the detect_outlier()
to find the outlier samples.
More information about how to detect outlier samples can be found here.
massdataset::show_sample_missing_values(object = object,
order_by = "injection.order",
percentage = TRUE) +
theme(axis.text.x = element_text(size = 2)) +
scale_size_continuous(range = c(0.1, 2)) +
ggsci::scale_color_aaas()
Detect outlier samples.
outlier_samples <-
object %>%
`+`(1) %>%
log(2) %>%
scale() %>%
detect_outlier()
outlier_samples
#> --------------------
#> masscleaner
#> --------------------
#> 1 according_to_na : 0 outlier samples.
#> 2 according_to_pc_sd : 0 outlier samples.
#> 3 according_to_pc_mad : 1 outlier samples.
#> 184 .
#> 4 accordint_to_distance : 2 outlier samples.
#> 184,214 .
#> extract all outlier table using extract_outlier_table()
outlier_table <-
extract_outlier_table(outlier_samples)
outlier_table %>%
head()
#> according_to_na pc_sd pc_mad accordint_to_distance
#> 184 FALSE FALSE TRUE TRUE
#> 214 FALSE FALSE FALSE TRUE
#> 289 FALSE FALSE FALSE FALSE
#> 317 FALSE FALSE FALSE FALSE
#> 320 FALSE FALSE FALSE FALSE
#> 327 FALSE FALSE FALSE FALSE
No outlier samples according to NA.
Missing value imputation
get_mv_number(object)
#> [1] 3224
sum(is.na(object))
#> [1] 3224
object <-
impute_mv(object = object, method = "knn")
#> Cluster size 4537 broken into 86 4451
#> Done cluster 86
#> Cluster size 4451 broken into 4168 283
#> Cluster size 4168 broken into 541 3627
#> Done cluster 541
#> Cluster size 3627 broken into 719 2908
#> Done cluster 719
#> Cluster size 2908 broken into 22 2886
#> Done cluster 22
#> Cluster size 2886 broken into 2097 789
#> Cluster size 2097 broken into 1365 732
#> Done cluster 1365
#> Done cluster 732
#> Done cluster 2097
#> Done cluster 789
#> Done cluster 2886
#> Done cluster 2908
#> Done cluster 3627
#> Done cluster 4168
#> Done cluster 283
#> Done cluster 4451
get_mv_number(object)
#> [1] 0
Data normalization and integration
object <-
normalize_data(object, method = "median")
object %>%
`+`(1) %>%
log(2) %>%
massqc::massqc_pca(line = FALSE)
Data quality assessment after data cleaning
Here, we can use the massqc
package to assess the data quality.
We can just use the massqc_report()
function to get a html format quality assessment report.
massqc::massqc_report(object = object,
path = "cell_liang_2020/data_cleaning/data_quality_after_data_cleaning")
Metabolite annotation
Add MS2 spectra to object
object <-
mutate_ms2(
object = object,
column = "rp",
polarity = "positive",
ms1.ms2.match.mz.tol = 15,
ms1.ms2.match.rt.tol = 30,
path = "cell_liang_2020/MS2/"
)
Metabolite annotation using metid
Metabolite annotation is based on the metid
package.
Download database
We need to download MS2 database from metid
website.
Here we download the Michael Snyder RPLC databases
, Orbitrap database
and MoNA database
. And place them in a new folder named as metabolite_annotation
.
Annotate features using snyder_database_rplc0.0.3
.
load("cell_liang_2020/metabolite_annotation/snyder_database_rplc0.0.3.rda")
object <-
annotate_metabolites_mass_dataset(object = object,
ms1.match.ppm = 15,
rt.match.tol = 30,
polarity = "positive",
database = snyder_database_rplc0.0.3)
Annotate features using orbitrap_database0.0.3
.
load("cell_liang_2020/metabolite_annotation/orbitrap_database0.0.3.rda")
object <-
annotate_metabolites_mass_dataset(object = object,
ms1.match.ppm = 15,
polarity = "positive",
database = orbitrap_database0.0.3)
Annotate features using mona_database0.0.3
.
load("cell_liang_2020/metabolite_annotation/mona_database0.0.3.rda")
object <-
annotate_metabolites_mass_dataset(object = object,
ms1.match.ppm = 15,
polarity = "positive",
database = mona_database0.0.3)
Annotation result
head(extract_annotation_table(object = object))
#> data frame with 0 columns and 0 rows
variable_info <-
extract_variable_info(object = object)
head(variable_info)
#> variable_id mz rt na_freq
#> 1 M71T823_POS 70.98037 823.24475 0.00000000
#> 2 M72T822_POS 71.98733 822.28662 0.00000000
#> 3 M73T36_POS 73.02834 36.06493 0.00000000
#> 4 M76T812_POS 76.10571 812.14087 0.14285714
#> 5 M77T33_POS 77.03845 32.64994 0.00000000
#> 6 M78T47_POS 77.96823 47.00970 0.07142857
table(variable_info$Level)
#> < table of extent 0 >
table(variable_info$Database)
#> < table of extent 0 >
ms2_plot_mass_dataset(object = object,
variable_id = "M123T56_POS",
database = snyder_database_rplc0.0.3)
Statistical analysis
Remove the features without annotations
object <-
object %>%
activate_mass_dataset(what = "annotation_table") %>%
filter(!is.na(Level)) %>%
filter(Level == 1 | Level == 2)
object
#> --------------------
#> massdataset version: 1.0.12
#> --------------------
#> 1.expression_data:[ 4537 x 14 data.frame]
#> 2.sample_info:[ 14 x 6 data.frame]
#> 14 samples:184 214 289 ... 528 739
#> 3.variable_info:[ 4537 x 4 data.frame]
#> 4537 variables:M71T823_POS M72T822_POS M73T36_POS ... M993T593_POS M994T593_POS
#> 4.sample_info_note:[ 6 x 2 data.frame]
#> 5.variable_info_note:[ 4 x 2 data.frame]
#> 6.ms2_data:[ 0 variables x 0 MS2 spectra]
#> --------------------
#> Processing information
#> 6 processings in total
#> Latest 3 processings show
#> filter ----------
#> Package Function.used Time
#> 1 massdataset filter() 2023-08-31 00:20:28
#> impute_mv ----------
#> Package Function.used Time
#> 1 masscleaner impute_mv() 2023-08-31 00:20:29
#> normalize_data ----------
#> Package Function.used Time
#> 1 masscleaner normalize_data() 2023-08-31 00:20:29
Trace processing information of object
Then we can use the report_parameters()
function to trace processing information of object.
All the analysis results will be placed in a folder named as statistical_analysis
.
dir.create(path = "cell_liang_2020/statistical_analysis", showWarnings = FALSE)
report_parameters(object = object, path = "cell_liang_2020/statistical_analysis/")
A html format file named as parameter_report.html
will be generated.
Remove redundant metabolites
Remove the redundant annotated metabolites bases on Level
and score.
object <-
object %>%
activate_mass_dataset(what = "annotation_table") %>%
group_by(Compound.name) %>%
filter(Level == min(Level)) %>%
filter(SS == max(SS)) %>%
slice_head(n = 1)
Differential expression metabolites
Calculate the fold changes.
object <-
object %>%
activate_mass_dataset(what = "sample_info") %>%
dplyr::arrange(subject_id, trimester)
control_sample_id <-
object %>%
activate_mass_dataset(what = "sample_info") %>%
filter(trimester == "<10") %>%
pull(sample_id)
case_sample_id <-
object %>%
activate_mass_dataset(what = "sample_info") %>%
filter(trimester == ">35") %>%
pull(sample_id)
object <-
mutate_fc(object = object,
control_sample_id = control_sample_id,
case_sample_id = case_sample_id,
mean_median = "mean")
Calculate p values.
object <-
mutate_p_value(
object = object,
control_sample_id = control_sample_id,
case_sample_id = case_sample_id,
method = "wilcox.test",
p_adjust_methods = "BH",
paired = TRUE
)
Volcano plot.
volcano_plot(object = object,
add_text = TRUE,
text_from = "Compound.name",
point_size_scale = "p_value") +
scale_size_continuous(range = c(0.5, 5))
Output result
Output the differential expression metabolites.
differential_metabolites <-
extract_variable_info(object = object) %>%
filter(fc > 2 | fc < 0.5) %>%
filter(p_value_adjust < 0.05)
readr::write_csv(differential_metabolites,
file = "cell_liang_2020/statistical_analysis/differential_metabolites.csv")
Pathway enrichment analysis
All the results will be placed in a folder named as pathway_enrichment
.
dir.create(path = "cell_liang_2020/pathway_enrichment", showWarnings = FALSE)
diff_metabolites <-
object %>%
activate_mass_dataset(what = "variable_info") %>%
filter(p_value_adjust < 0.05) %>%
extract_variable_info()
head(diff_metabolites)
Load KEGG
human pathway database
data("kegg_hsa_pathway", package = "metpath")
kegg_hsa_pathway
get_pathway_class(kegg_hsa_pathway)
Remove the disease pathways:
#get the class of pathways
pathway_class <-
metpath::pathway_class(kegg_hsa_pathway)
head(pathway_class)
remain_idx <-
pathway_class %>%
unlist() %>%
stringr::str_detect("Disease") %>%
`!`() %>%
which()
remain_idx
pathway_database <-
kegg_hsa_pathway[remain_idx]
pathway_database
Pathway enrichment
kegg_id <-
diff_metabolites$KEGG.ID
kegg_id <-
kegg_id[!is.na(kegg_id)]
kegg_id
result <-
enrich_kegg(query_id = kegg_id,
query_type = "compound",
id_type = "KEGG",
pathway_database = pathway_database,
p_cutoff = 0.05,
p_adjust_method = "BH",
threads = 3)
Check the result:
result
Plot to show pathway enrichment result
enrich_bar_plot(object = result,
x_axis = "p_value",
cutoff = 0.05)
enrich_scatter_plot(object = result, y_axis = "p_value", y_axis_cutoff = 0.05)
enrich_network(
object = result,
point_size = "p_value",
p_cutoff = 0.05,
only_significant_pathway = TRUE
)
Session information
sessionInfo()
#> R version 4.3.0 (2023-04-21)
#> Platform: x86_64-apple-darwin20 (64-bit)
#> Running under: macOS Ventura 13.5.1
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: America/Los_Angeles
#> tzcode source: internal
#>
#> attached base packages:
#> [1] grid stats4 stats graphics grDevices utils datasets
#> [8] methods base
#>
#> other attached packages:
#> [1] lubridate_1.9.2 forcats_1.0.0 stringr_1.5.0
#> [4] purrr_1.0.1 readr_2.1.4 tibble_3.2.1
#> [7] tidyverse_2.0.0 metid_1.2.28 metpath_1.0.8
#> [10] ComplexHeatmap_2.16.0 mixOmics_6.24.0 lattice_0.21-8
#> [13] MASS_7.3-58.4 massstat_1.0.5 tidyr_1.3.0
#> [16] ggfortify_0.4.16 massqc_1.0.6 masscleaner_1.0.11
#> [19] xcms_3.22.0 MSnbase_2.26.0 ProtGenerics_1.32.0
#> [22] S4Vectors_0.38.1 mzR_2.34.0 Rcpp_1.0.10
#> [25] Biobase_2.60.0 BiocGenerics_0.46.0 BiocParallel_1.34.2
#> [28] massprocesser_1.0.10 ggplot2_3.4.2 dplyr_1.1.2
#> [31] magrittr_2.0.3 masstools_1.0.10 massdataset_1.0.25
#> [34] tidymass_1.0.8
#>
#> loaded via a namespace (and not attached):
#> [1] splines_4.3.0 bitops_1.0-7
#> [3] cellranger_1.1.0 polyclip_1.10-4
#> [5] preprocessCore_1.62.1 XML_3.99-0.14
#> [7] rpart_4.1.19 fastDummies_1.6.3
#> [9] lifecycle_1.0.3 doParallel_1.0.17
#> [11] rprojroot_2.0.3 globals_0.16.2
#> [13] backports_1.4.1 plotly_4.10.2
#> [15] openxlsx_4.2.5.2 limma_3.56.2
#> [17] Hmisc_5.1-0 sass_0.4.6
#> [19] rmarkdown_2.22 jquerylib_0.1.4
#> [21] yaml_2.3.7 remotes_2.4.2
#> [23] doRNG_1.8.6 zip_2.3.0
#> [25] MsCoreUtils_1.12.0 pbapply_1.7-0
#> [27] RColorBrewer_1.1-3 zlibbioc_1.46.0
#> [29] GenomicRanges_1.52.0 ggraph_2.1.0
#> [31] itertools_0.1-3 RCurl_1.98-1.12
#> [33] nnet_7.3-18 tweenr_2.0.2
#> [35] circlize_0.4.15 GenomeInfoDbData_1.2.10
#> [37] IRanges_2.34.0 ggrepel_0.9.3
#> [39] listenv_0.9.0 ellipse_0.4.5
#> [41] RSpectra_0.16-1 missForest_1.5
#> [43] parallelly_1.36.0 ncdf4_1.21
#> [45] codetools_0.2-19 DelayedArray_0.26.3
#> [47] ggforce_0.4.1 tidyselect_1.2.0
#> [49] shape_1.4.6 farver_2.1.1
#> [51] viridis_0.6.3 matrixStats_1.0.0
#> [53] base64enc_0.1-3 jsonlite_1.8.5
#> [55] GetoptLong_1.0.5 multtest_2.56.0
#> [57] e1071_1.7-13 tidygraph_1.2.3
#> [59] Formula_1.2-5 survival_3.5-5
#> [61] iterators_1.0.14 foreach_1.5.2
#> [63] progress_1.2.2 tools_4.3.0
#> [65] glue_1.6.2 rARPACK_0.11-0
#> [67] gridExtra_2.3 xfun_0.39
#> [69] here_1.0.1 MatrixGenerics_1.12.2
#> [71] GenomeInfoDb_1.36.0 withr_2.5.0
#> [73] BiocManager_1.30.21 fastmap_1.1.1
#> [75] fansi_1.0.4 blogdown_1.18.1
#> [77] digest_0.6.31 timechange_0.2.0
#> [79] R6_2.5.1 colorspace_2.1-0
#> [81] utf8_1.2.3 generics_0.1.3
#> [83] data.table_1.14.8 corpcor_1.6.10
#> [85] robustbase_0.95-1 class_7.3-21
#> [87] graphlayouts_1.0.0 prettyunits_1.1.1
#> [89] httr_1.4.6 htmlwidgets_1.6.2
#> [91] S4Arrays_1.0.4 pkgconfig_2.0.3
#> [93] gtable_0.3.3 robust_0.7-1
#> [95] impute_1.74.1 MassSpecWavelet_1.66.0
#> [97] XVector_0.40.0 furrr_0.3.1
#> [99] pcaPP_2.0-3 htmltools_0.5.5
#> [101] bookdown_0.34 MALDIquant_1.22.1
#> [103] clue_0.3-64 scales_1.2.1
#> [105] png_0.1-8 knitr_1.43
#> [107] rstudioapi_0.14 reshape2_1.4.4
#> [109] tzdb_0.4.0 rjson_0.2.21
#> [111] checkmate_2.2.0 ggcorrplot_0.1.4
#> [113] proxy_0.4-27 cachem_1.0.8
#> [115] GlobalOptions_0.1.2 parallel_4.3.0
#> [117] foreign_0.8-84 mzID_1.38.0
#> [119] vsn_3.68.0 pillar_1.9.0
#> [121] vctrs_0.6.2 MsFeatures_1.8.0
#> [123] RANN_2.6.1 pcaMethods_1.92.0
#> [125] randomForest_4.7-1.1 cluster_2.1.4
#> [127] htmlTable_2.4.1 evaluate_0.21
#> [129] mvtnorm_1.2-2 cli_3.6.1
#> [131] compiler_4.3.0 rlang_1.1.1
#> [133] crayon_1.5.2 rngtools_1.5.2
#> [135] Rdisop_1.60.0 rrcov_1.7-3
#> [137] affy_1.78.0 plyr_1.8.8
#> [139] stringi_1.7.12 viridisLite_0.4.2
#> [141] Biostrings_2.68.1 munsell_0.5.0
#> [143] lazyeval_0.2.2 fit.models_0.64
#> [145] Matrix_1.5-4 hms_1.1.3
#> [147] patchwork_1.1.2 future_1.32.0
#> [149] KEGGREST_1.40.0 SummarizedExperiment_1.30.2
#> [151] igraph_1.4.3 affyio_1.70.0
#> [153] bslib_0.5.0 DEoptimR_1.0-14
#> [155] readxl_1.4.2