diff --git a/DESCRIPTION b/DESCRIPTION index bfa52d17..b35ed487 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: miaViz Title: Microbiome Analysis Plotting and Visualization -Version: 1.21.5 +Version: 1.21.6 Authors@R: c(person(given = "Tuomas", family = "Borman", role = c("aut", "cre"), email = "tuomas.v.borman@utu.fi", @@ -82,7 +82,7 @@ Suggests: vegan, vipor Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.3 VignetteBuilder: knitr URL: https://github.com/microbiome/miaViz BugReports: https://github.com/microbiome/miaViz/issues +Config/roxygen2/version: 8.1.0 diff --git a/NAMESPACE b/NAMESPACE index 30ac17e9..537fd9bc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -63,147 +63,195 @@ import(ggplot2) import(ggraph) import(methods) import(mia) -importFrom(BiocGenerics,ncol) -importFrom(BiocGenerics,nrow) -importFrom(BiocParallel,SerialParam) -importFrom(BiocParallel,bpisup) -importFrom(BiocParallel,bplapply) -importFrom(BiocParallel,bpmapply) -importFrom(BiocParallel,bpstart) -importFrom(BiocParallel,bpstop) -importFrom(DelayedArray,rowMeans) -importFrom(DelayedArray,rowSums) +importFrom(BiocGenerics, + ncol, + nrow +) +importFrom(BiocParallel, + SerialParam, + bpisup, + bplapply, + bpmapply, + bpstart, + bpstop +) +importFrom(DelayedArray, + rowMeans, + rowSums +) importFrom(DirichletMultinomial,mixture) -importFrom(S4Vectors,metadata) -importFrom(S4Vectors,unfactor) -importFrom(SingleCellExperiment,reducedDim) -importFrom(SingleCellExperiment,reducedDimNames) -importFrom(SingleCellExperiment,reducedDims) -importFrom(SummarizedExperiment,"rowData<-") -importFrom(SummarizedExperiment,assay) -importFrom(SummarizedExperiment,colData) -importFrom(SummarizedExperiment,rowData) -importFrom(TreeSummarizedExperiment,colTree) -importFrom(TreeSummarizedExperiment,colTreeNames) -importFrom(TreeSummarizedExperiment,rowLinks) -importFrom(TreeSummarizedExperiment,rowTree) -importFrom(TreeSummarizedExperiment,rowTreeNames) -importFrom(ape,as.phylo) -importFrom(ape,drop.tip) -importFrom(ape,keep.tip) -importFrom(ape,rotateConstr) -importFrom(dplyr,"%>%") -importFrom(dplyr,across) -importFrom(dplyr,all_of) -importFrom(dplyr,arrange) -importFrom(dplyr,case_when) -importFrom(dplyr,desc) -importFrom(dplyr,distinct) -importFrom(dplyr,filter) -importFrom(dplyr,group_by) -importFrom(dplyr,group_modify) -importFrom(dplyr,last_col) -importFrom(dplyr,mutate) -importFrom(dplyr,n) -importFrom(dplyr,n_distinct) -importFrom(dplyr,pull) -importFrom(dplyr,relocate) -importFrom(dplyr,rename) -importFrom(dplyr,rename_with) -importFrom(dplyr,row_number) -importFrom(dplyr,select) -importFrom(dplyr,slice_max) -importFrom(dplyr,summarise) -importFrom(dplyr,summarize) -importFrom(dplyr,ungroup) -importFrom(ggnewscale,new_scale) -importFrom(ggnewscale,new_scale_colour) -importFrom(ggnewscale,new_scale_fill) -importFrom(ggplot2,aes) -importFrom(ggplot2,annotate) -importFrom(ggplot2,coord_cartesian) -importFrom(ggplot2,coord_flip) -importFrom(ggplot2,element_blank) -importFrom(ggplot2,element_rect) -importFrom(ggplot2,element_text) -importFrom(ggplot2,expansion) -importFrom(ggplot2,facet_grid) -importFrom(ggplot2,facet_wrap) -importFrom(ggplot2,geom_bar) -importFrom(ggplot2,geom_errorbar) -importFrom(ggplot2,geom_line) -importFrom(ggplot2,geom_point) -importFrom(ggplot2,geom_raster) -importFrom(ggplot2,geom_segment) -importFrom(ggplot2,geom_text) -importFrom(ggplot2,geom_tile) -importFrom(ggplot2,geom_vline) -importFrom(ggplot2,ggplot) -importFrom(ggplot2,ggplot_build) -importFrom(ggplot2,labs) -importFrom(ggplot2,position_dodge) -importFrom(ggplot2,position_dodge2) -importFrom(ggplot2,scale_colour_manual) -importFrom(ggplot2,scale_fill_distiller) -importFrom(ggplot2,scale_fill_gradient2) -importFrom(ggplot2,scale_fill_manual) -importFrom(ggplot2,scale_fill_viridis_d) -importFrom(ggplot2,scale_size_identity) -importFrom(ggplot2,scale_x_continuous) -importFrom(ggplot2,scale_x_discrete) -importFrom(ggplot2,scale_y_continuous) -importFrom(ggplot2,scale_y_discrete) -importFrom(ggplot2,theme) -importFrom(ggplot2,theme_bw) -importFrom(ggplot2,theme_classic) -importFrom(ggplot2,theme_minimal) -importFrom(ggrepel,geom_label_repel) -importFrom(ggrepel,geom_text_repel) -importFrom(ggtree,geom_cladelab) -importFrom(ggtree,geom_highlight) -importFrom(ggtree,geom_nodelab) -importFrom(ggtree,geom_nodepoint) -importFrom(ggtree,geom_tiplab) -importFrom(ggtree,geom_tippoint) -importFrom(ggtree,geom_tree) -importFrom(ggtree,ggtree) -importFrom(ggtree,gheatmap) -importFrom(ggtree,groupOTU) -importFrom(ggtree,theme_tree) -importFrom(grid,arrow) -importFrom(grid,unit) +importFrom(S4Vectors, + metadata, + unfactor +) +importFrom(SingleCellExperiment, + reducedDim, + reducedDimNames, + reducedDims +) +importFrom(SummarizedExperiment, + "rowData<-", + assay, + colData, + rowData +) +importFrom(TreeSummarizedExperiment, + colTree, + colTreeNames, + rowLinks, + rowTree, + rowTreeNames +) +importFrom(ape, + as.phylo, + drop.tip, + keep.tip, + rotateConstr +) +importFrom(dplyr, + "%>%", + across, + all_of, + arrange, + case_when, + desc, + distinct, + filter, + group_by, + group_modify, + last_col, + mutate, + n, + n_distinct, + pull, + relocate, + rename, + rename_with, + row_number, + select, + slice_max, + summarise, + summarize, + ungroup +) +importFrom(ggnewscale, + new_scale, + new_scale_colour, + new_scale_fill +) +importFrom(ggplot2, + aes, + annotate, + coord_cartesian, + coord_flip, + element_blank, + element_rect, + element_text, + expansion, + facet_grid, + facet_wrap, + geom_bar, + geom_errorbar, + geom_line, + geom_point, + geom_raster, + geom_segment, + geom_text, + geom_tile, + geom_vline, + ggplot, + ggplot_build, + labs, + position_dodge, + position_dodge2, + scale_colour_manual, + scale_fill_distiller, + scale_fill_gradient2, + scale_fill_manual, + scale_fill_viridis_d, + scale_size_identity, + scale_x_continuous, + scale_x_discrete, + scale_y_continuous, + scale_y_discrete, + theme, + theme_bw, + theme_classic, + theme_minimal +) +importFrom(ggrepel, + geom_label_repel, + geom_text_repel +) +importFrom(ggtree, + geom_cladelab, + geom_highlight, + geom_nodelab, + geom_nodepoint, + geom_tiplab, + geom_tippoint, + geom_tree, + ggtree, + gheatmap, + groupOTU, + theme_tree +) +importFrom(grid, + arrow, + unit +) importFrom(mia,meltSE) -importFrom(patchwork,plot_layout) -importFrom(patchwork,wrap_plots) -importFrom(rlang,"!!") -importFrom(rlang,":=") -importFrom(rlang,sym) -importFrom(scales,pretty_breaks) -importFrom(scales,rescale) -importFrom(scater,retrieveCellInfo) -importFrom(scater,retrieveFeatureInfo) -importFrom(stats,formula) -importFrom(stats,median) -importFrom(stats,qt) -importFrom(stats,runif) -importFrom(stats,sd) +importFrom(patchwork, + plot_layout, + wrap_plots +) +importFrom(rlang, + "!!", + ":=", + sym +) +importFrom(scales, + pretty_breaks, + rescale +) +importFrom(scater, + retrieveCellInfo, + retrieveFeatureInfo +) +importFrom(stats, + formula, + median, + qt, + runif, + sd +) importFrom(tibble,rownames_to_column) -importFrom(tidygraph,activate) -importFrom(tidygraph,as_tbl_graph) -importFrom(tidygraph,as_tibble) -importFrom(tidyr,complete) -importFrom(tidyr,drop_na) -importFrom(tidyr,pivot_longer) -importFrom(tidyr,pivot_wider) -importFrom(tidytext,reorder_within) -importFrom(tidytext,scale_y_reordered) -importFrom(tidytree,as.phylo) -importFrom(tidytree,as.treedata) -importFrom(tidytree,as_tibble) -importFrom(tidytree,child) -importFrom(tidytree,groupOTU) -importFrom(tidytree,isTip) -importFrom(tidytree,rootnode) +importFrom(tidygraph, + activate, + as_tbl_graph, + as_tibble +) +importFrom(tidyr, + complete, + drop_na, + pivot_longer, + pivot_wider +) +importFrom(tidytext, + reorder_within, + scale_y_reordered +) +importFrom(tidytree, + as.phylo, + as.treedata, + as_tibble, + child, + groupOTU, + isTip, + rootnode +) importFrom(utils,getFromNamespace) -importFrom(viridis,scale_colour_viridis) -importFrom(viridis,scale_fill_viridis) +importFrom(viridis, + scale_colour_viridis, + scale_fill_viridis +) diff --git a/NEWS b/NEWS index 260f5963..52fc8959 100644 --- a/NEWS +++ b/NEWS @@ -55,3 +55,4 @@ Changes in version 1.19.x Changes in version 1.21.x + Added plotOrdination and plotJointRPCA (2026-08-04) + Added plotHeatmap (2026-08-10) ++ Added multimedia_data_demo example datasets (se_relative, tse_relative, tse_pathway) (2026-09-01) diff --git a/R/miaViz.R b/R/miaViz.R index e77dc22f..546195c6 100644 --- a/R/miaViz.R +++ b/R/miaViz.R @@ -1,6 +1,6 @@ #' miaViz - Microbiome Analysis Plotting and Visualization #' -#' The scope of this package is the plotting and visualization of microbiome +#' The scope of this package is the plotting and visualization of microbiome #' data. The main class for interfacing is the \code{TreeSummarizedExperiment} #' class. #' @@ -23,26 +23,26 @@ NULL #' @title miaViz example data #' #' @description -#' These example data objects were prepared to serve as examples. See the +#' These example data objects were prepared to serve as examples. See the #' details for more information. -#' +#' #' @details #' For \code{*_graph} data: -#' -#' 1. \dQuote{Jaccard} distances were calculated via -#' \code{calculateDistance(genus, FUN = vegan::vegdist, method = "jaccard", -#' exprs_values = "relabundance")}, either using transposed assay data or not +#' +#' 1. \dQuote{Jaccard} distances were calculated via +#' \code{getDissimilarity(genus, FUN = vegan::vegdist, method = "jaccard", +#' assay.type = "relabundance")}, either using transposed assay data or not #' to calculate distances for samples or features. NOTE: the function #' mia::calculateDistance is now deprecated. -#' +#' #' 2. \dQuote{Jaccard} dissimilarites were converted to similarities and values -#' above a threshold were used to construct a graph via +#' above a threshold were used to construct a graph via #' \code{graph.adjacency(mode = "lower", weighted = TRUE)}. -#' -#' 3. The \code{igraph} object was converted to \code{tbl_graph} via +#' +#' 3. The \code{igraph} object was converted to \code{tbl_graph} via #' \code{as_tbl_graph} from the \code{tidygraph} package. -#' -#' +#' +#' #' @name mia-datasets #' @docType data #' @keywords datasets @@ -54,3 +54,42 @@ NULL #' @name mia-datasets #' @usage data(row_graph_order) "row_graph_order" + +#' HMP_2019_ibdmdb: IBDMDB TreeSummarizedExperiment data +#' +#' An example gut microbiome dataset derived from the +#' \pkg{curatedMetagenomicData} \code{HMP_2019_ibdmdb} resource (iHMP/HMP2 IBD +#' cohort; Lloyd-Price et al., 2019). +#' +#' The object is provided as a \code{TreeSummarizedExperiment}. +#' +#' @format A \code{TreeSummarizedExperiment} with 585 microbial species (rows) +#' and 44 stool samples (columns) from 22 subjects with inflammatory bowel +#' disease (two time points per subject: baseline \code{T0} and follow-up +#' \code{T1}). +#' +#' Assays include relative abundance (\code{relabundance}) and a scaled version +#' of the same data (\code{scaled}). Taxonomic annotation is stored in +#' \code{rowData}, and a phylogenetic tree is available via \code{rowTree}. +#' Sample metadata (\code{colData}) includes subject identifiers, time point, +#' IBD subtype (CD/UC), and additional technical and demographic variables. +#' +#' @source +#' Derived from \code{curatedMetagenomicData} (Lloyd-Price et al., 2019). +#' +#' @references +#' Lloyd-Price J, Arze C, Ananthakrishnan AN, et al. (2019). +#' Multi-omics of the gut microbial ecosystem in inflammatory bowel diseases. +#' \emph{Nature} 569, 655--662. \doi{10.1038/s41586-019-1237-9} +#' +#' @name HMP_2019_ibdmdb +#' @docType data +#' @keywords datasets +#' @usage data(HMP_2019_ibdmdb) +#' +#' @examples +#' data("HMP_2019_ibdmdb", package = "miaViz") +#' HMP_2019_ibdmdb +#' SummarizedExperiment::assayNames(HMP_2019_ibdmdb) +#' TreeSummarizedExperiment::rowTree(HMP_2019_ibdmdb) +"HMP_2019_ibdmdb" diff --git a/data/HMP_2019_ibdmdb.rda b/data/HMP_2019_ibdmdb.rda new file mode 100644 index 00000000..ca146155 Binary files /dev/null and b/data/HMP_2019_ibdmdb.rda differ diff --git a/inst/scripts/HMP_2019_ibdmdb_data_prep.R b/inst/scripts/HMP_2019_ibdmdb_data_prep.R new file mode 100644 index 00000000..f1ce4127 --- /dev/null +++ b/inst/scripts/HMP_2019_ibdmdb_data_prep.R @@ -0,0 +1,126 @@ +# ----------------------------------------------------------------------------- +# multimedia_relative_data_prep.R +# +# Preparation script for the miaViz example datasets `se_relative` and +# `tse_relative` (see `?miaViz::multimedia-datasets`). +# +# Source: curatedMetagenomicData -> HMP_2019_ibdmdb.relative_abundance +# (Lloyd-Price et al., 2019, Nature 569:655-662). +# +# Pipeline: +# 1. Load the iHMP IBDMDB relative-abundance TreeSummarizedExperiment. +# 2. Convert the raw assay to relative abundances in [0, 1]. +# 3. Compute a per-sample dysbiosis score as the median Bray-Curtis +# distance to the healthy reference set (excluding self). +# 4. Subset to IBD subjects with paired baseline (visit 1) and +# post-treatment (visit 21) samples. +# 5. Define a `treatment` factor (T0 = baseline, T1 = post-treatment). +# 6. Standardize the relative-abundance assay as `scaled`. +# 7. Save `tse_relative` (TreeSummarizedExperiment) and `se_relative` +# (SummarizedExperiment) as separate .rda files under `data/`. +# +# Run this script from the package root, or set the destination path +# in the save() calls at the end accordingly. +# ----------------------------------------------------------------------------- + +remove(list = ls()) +invisible(gc()) + +################## +# Load libraries # +################## + +library(curatedMetagenomicData) +library(SummarizedExperiment) +library(dplyr) +library(vegan) +library(tidyverse) +library(stringr) +library(ggplot2) +library(mia) + +################## +# Load iHMP data # +################## + +# Load data +tse <- curatedMetagenomicData( + "HMP_2019_ibdmdb.relative_abundance", + rownames = "short", + dryrun = FALSE +)[[1]] + +# Assign SampleID for matching +tse$SampleID <- colnames(tse) + +# Convert relative_abundance assay to relabundance (which is in [0,1] interval) +tse <- transformAssay( + tse, assay.type = "relative_abundance", method = "relabundance" +) + +######################## +# Reference nonIBD set # +######################## + +# Reference set: healthy +tse$disease_binary <- tse$disease == "healthy" + +######################################## +# Calculate Bray-Curtis dissimilarity # +######################################## + +diss <- as.matrix(getDissimilarity( + tse, method = "bray", na.rm = TRUE, assay.type = "relabundance" +)) + +################################# +# Calculate the dysbiosis score # +################################# + +# For each sample i, compute the median distance to all healthy reference +# samples (excluding sample i itself). +sample_ids <- tse$SampleID + +tse$dysbiosis <- sapply(seq_along(tse$disease_binary), function(i) { + ref_others <- tse$disease_binary & (sample_ids != sample_ids[i]) + median(diss[i, ref_others], na.rm = TRUE) +}) + +############################################################# +# Subset to IBD only and only one post-baseline time point # +############################################################# + +# Keep IBD only +tse <- tse[, tse$disease != "healthy"] + +# Visit 1 (baseline) or 21 (post-treatment) +tse <- tse[, tse$visit_number %in% c(1, 21)] + +# Keep subjects with both visits +keep_subjects <- names(which(table(tse$subject_id) == 2)) +tse <- tse[, tse$subject_id %in% keep_subjects] + +# Define time point label +tse$time_point <- ifelse(tse$visit_number == 1, "T0", "T1") + +# Define treatment: Pre and Post (Baseline vs. Post-baseline) +tse$treatment <- factor(tse$time_point, levels = c("T0", "T1")) + +############################# +# Standardize the mediators # +############################# + +tse <- transformAssay( + tse, assay.type = "relabundance", method = "standardize", name = "scaled" +) + +# Remove additional assay and columns from colData +assays(tse) <- assays(tse)[2:3] +tse$disease_binary <- NULL +tse$SampleID <- NULL + +################ +# Save as .rda # +################ +HMP_2019_ibdmdb <- tse +save(HMP_2019_ibdmdb, file = "data/HMP_2019_ibdmdb.rda", compress = "xz") diff --git a/man/HMP_2019_ibdmdb.Rd b/man/HMP_2019_ibdmdb.Rd new file mode 100644 index 00000000..9da9ea02 --- /dev/null +++ b/man/HMP_2019_ibdmdb.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/miaViz.R +\docType{data} +\name{HMP_2019_ibdmdb} +\alias{HMP_2019_ibdmdb} +\title{HMP_2019_ibdmdb: IBDMDB TreeSummarizedExperiment data} +\format{ +A \code{TreeSummarizedExperiment} with 585 microbial species (rows) +and 44 stool samples (columns) from 22 subjects with inflammatory bowel +disease (two time points per subject: baseline \code{T0} and follow-up +\code{T1}). + +Assays include relative abundance (\code{relabundance}) and a scaled version +of the same data (\code{scaled}). Taxonomic annotation is stored in +\code{rowData}, and a phylogenetic tree is available via \code{rowTree}. +Sample metadata (\code{colData}) includes subject identifiers, time point, +IBD subtype (CD/UC), and additional technical and demographic variables. +} +\source{ +Derived from \code{curatedMetagenomicData} (Lloyd-Price et al., 2019). +} +\usage{ +data(HMP_2019_ibdmdb) +} +\description{ +An example gut microbiome dataset derived from the +\pkg{curatedMetagenomicData} \code{HMP_2019_ibdmdb} resource (iHMP/HMP2 IBD +cohort; Lloyd-Price et al., 2019). +} +\details{ +The object is provided as a \code{TreeSummarizedExperiment}. +} +\examples{ +data("HMP_2019_ibdmdb", package = "miaViz") +HMP_2019_ibdmdb +SummarizedExperiment::assayNames(HMP_2019_ibdmdb) +TreeSummarizedExperiment::rowTree(HMP_2019_ibdmdb) +} +\references{ +Lloyd-Price J, Arze C, Ananthakrishnan AN, et al. (2019). +Multi-omics of the gut microbial ecosystem in inflammatory bowel diseases. +\emph{Nature} 569, 655--662. \doi{10.1038/s41586-019-1237-9} +} +\keyword{datasets} diff --git a/man/mia-datasets.Rd b/man/mia-datasets.Rd index cff88f36..32f54c29 100644 --- a/man/mia-datasets.Rd +++ b/man/mia-datasets.Rd @@ -29,8 +29,8 @@ details for more information. For \code{*_graph} data: \enumerate{ \item \dQuote{Jaccard} distances were calculated via -\code{calculateDistance(genus, FUN = vegan::vegdist, method = "jaccard", -exprs_values = "relabundance")}, either using transposed assay data or not +\code{getDissimilarity(genus, FUN = vegan::vegdist, method = "jaccard", +assay.type = "relabundance")}, either using transposed assay data or not to calculate distances for samples or features. NOTE: the function mia::calculateDistance is now deprecated. \item \dQuote{Jaccard} dissimilarites were converted to similarities and values diff --git a/man/miaViz-package.Rd b/man/miaViz-package.Rd index 78c969c5..4f095d06 100644 --- a/man/miaViz-package.Rd +++ b/man/miaViz-package.Rd @@ -18,6 +18,7 @@ class. Authors: \itemize{ + \item Tuomas Borman \email{tuomas.v.borman@utu.fi} (\href{https://orcid.org/0000-0002-8563-8884}{ORCID}) \item Felix G.M. Ernst (\href{https://orcid.org/0000-0001-5064-0928}{ORCID}) \item Leo Lahti \email{leo.lahti@iki.fi} (\href{https://orcid.org/0000-0001-5537-637X}{ORCID}) }