Skip to content

Commit b6de96d

Browse files
committed
adapted autoflow to new changes
1 parent f524e75 commit b6de96d

6 files changed

Lines changed: 137 additions & 127 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
44
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
55

6-
## v1.5.2 - [2026-05-]
6+
## v1.6.0 - [2026-05-19]
77

88
### `Added`
99
- [#34](https://github.com/agusinac/OmicFlow/issues/34) Extra argument `group_by` in `foldchange`.
1010

1111
### `Changed`
12-
- [#33](https://github.com/agusinac/OmicFlow/issues/33) Combined two methods into a single `omics$scale()`, added euclidean method and aitchison
12+
- [#33](https://github.com/agusinac/OmicFlow/issues/33) Combined two methods into a single `omics$scale()`, added euclidean method and aitchison. Improved all dissimilarity metrics (except for UniFrac) by 2x speed & 7x less memory, UniFrac is 4x faster.
1313
- [#36](https://github.com/agusinac/OmicFlow/issues/36) Created `foldchange` method in `omics` abstract class and in `metagenomics` subclass
14+
- Adapted & tested `autoFlow` with new changes
1415

1516
### `Fixed`
1617
- [#35](https://github.com/agusinac/OmicFlow/issues/35) changed removezeros by using `@p` of `CsparseMatrix`

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: OmicFlow
22
Title: Fast and Efficient (Automated) Analysis of Sparse Omics Data
3-
Version: 1.5.1
4-
Date: 2026-02-27
3+
Version: 1.6.0
4+
Date: 2026-05-19
55
Authors@R: c(
66
person(
77
"Alem", "Gusinac",

R/omics-class.R

Lines changed: 107 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#' Abstract omics class
22
#'
33
#' @description This is the abstract class 'omics', contains a variety of methods that are inherited and applied in the omics classes:
4-
#' \link{metagenomics}, proteomics and metabolomics.
4+
#' \link{metagenomics} and \link{proteomics}.
55
#'
66
#' @details
77
#' Every class is created with the \link[R6]{R6Class} method. Methods are either public or private, and only the public components are inherited by other omic classes.
@@ -608,9 +608,9 @@ omics <- R6::R6Class(
608608
},
609609
#' @description
610610
#' Feature scaling on the `countData`. The `scale` function is able to apply transformations element-wise on the positive values, (optional: add pseudocounts) and perform normalisation or standardisation methods.
611-
#' @param method A character to choose a standardisation/normalisation method, options: `tss`, `clr`, `binary`, `hellinger` (default: \code{"tss"}).
612-
#' @param transform A function to apply on the positive values of `countData` (default: \code{NULL}).
613-
#' @param base Input for \link[base]{log} to use natural logarithmic scale, log2, log10 or other (default: \code{exp(1)}).
611+
#' @param method A character to choose a standardisation/normalisation method, options: `tss`, `clr`, `binary`, `hellinger`, `none` (default: \code{"tss"}).
612+
#' @param transform A function to apply on the positive values of `countData`, skip standardisation/normalisation with \code{method = "none"} (default: \code{NULL}).
613+
#' @param base Input for \link[base]{log} to use natural logarithmic scale, log2, log10 or other (default: \code{exp(1)}) in CLR.
614614
#' @param pseudocount A numeric value to replace zero's (default: \code{NULL}).
615615
#' @examples
616616
#' library("OmicFlow")
@@ -631,6 +631,10 @@ omics <- R6::R6Class(
631631
#' obj$reset()
632632
#' obj$scale(method = "clr")
633633
#'
634+
#' # transform
635+
#' obj$reset()
636+
#' obj$scale(method = "none", transform = log2)
637+
#'
634638
#' @return object in place
635639
scale = function(method = "tss", transform = NULL, base = exp(1), pseudocount = NULL) {
636640

@@ -643,7 +647,7 @@ omics <- R6::R6Class(
643647

644648
## Error handling
645649
#--------------------------------------------------------------------#
646-
OPTIONS <- c("tss", "clr", "binary", "hellinger")
650+
OPTIONS <- c("tss", "clr", "binary", "hellinger", "none")
647651
if (!is.null(method) && !is.character(method) && length(method) != 1) {
648652
cli::cli_abort("{.val {method}} needs to contain characters with length of 1.")
649653
} else if (!method %in% OPTIONS) {
@@ -684,7 +688,8 @@ omics <- R6::R6Class(
684688
ref <- tss(private$.countData)
685689
ref@x <- sqrt(ref@x)
686690
ref
687-
}
691+
},
692+
"none" = private$.countData
688693
)
689694

690695
invisible(self)
@@ -1318,7 +1323,7 @@ omics <- R6::R6Class(
13181323
#' @description
13191324
#' Differential feature expression (DFE) on log-transformed values for both paired and non-paired test.
13201325
#'
1321-
#' The function performs feature agglomeration, subsetting to remove NAs in `condition.group` and finding samplepairs.
1326+
#' The function performs feature agglomeration, subsetting to remove NAs in `condition.group` and finding samplepairs. It expects that the data is already log-transformed, this can be accomplished via [`scale()`](#method-scale)
13221327
#'
13231328
#' @param feature_rank A character or vector of characters in the `featureData` to aggregate via [`feature_merge()`](#method-feature_merge) (default: \code{"FEATURE_ID"}).
13241329
#' @param feature_filter A character or vector of characters to remove features via regex pattern (default: \code{NULL}).
@@ -1549,29 +1554,27 @@ omics <- R6::R6Class(
15491554
},
15501555
#' @description
15511556
#' Automated Omics Analysis based on the `metaData`, see [`validate()`](#method-validate).
1552-
#' For now only works with headers that start with prefix `CONTRAST_`. If the data is from the class `omics` or `proteomics` than FDR adjusted p-values are computed for the volcano plots.
1557+
#' For now only works with headers that start with prefix `CONTRAST_`. If the data is from the class `omics` or `proteomics` than FDR adjusted p-values are computed for the volcano plots. Log-transformed values will lead to the skipping of [`composition()`](#method-composition) and [`alpha_diversity()`](#method-alpha_diversity) methods.
15531558
#' @param feature_contrast A character vector of feature columns in the `featureData` to aggregate via [`feature_merge()`](#method-feature_merge) (default: \code{"FEATURE_ID"}).
15541559
#' @param feature_filter A character vector to filter unwanted features, (default: \code{NULL}).
15551560
#' @param feature_ranks A character vector as input to [`rankstat()`](#method-rankstat) (default: \code{NULL}).
1556-
#' @param distance_metrics A character vector specifying what (dis)similarity metrics to use (default: \code{c("unifrac")}).
1557-
#' @param beta_div_table A path to an existing file or a dense/sparse \link[Matrix]{Matrix} format (default: \code{NULL}).
1558-
#' @param alpha_div_table A path to pre-computed alpha diversity table, with columns: `alpha_div` (containing diversity values) and the same CONTRAST columns from `metaData` (default: \code{NULL}).
1561+
#' @param distance_metrics A character vector specifying what (dis)similarity metrics to use (default: \code{c("bray")}) When you are working with log-transformed data it is advised to use the `euclidean`.
1562+
#' @param distmat A path to an existing file or a dense/sparse \link[Matrix]{Matrix} format (default: \code{NULL}).
15591563
#' @param weighted A boolean value, whether to compute weighted or unweighted dissimilarities (default: \code{TRUE}).
15601564
#' @param pvalue.threshold A numeric value, the p-value is used to include/exclude composition and foldchanges plots coming from alpha- and beta diversity analysis (default: 0.05).
15611565
#' @param logfold.threshold A numeric value used as a fold-change threshold to label and color significantly expressed features, see [`foldchange()`](#method-foldchange) (Default: 1).
15621566
#' @param abundance.threshold A numeric value used as an abundance threshold to size the scatter dots based on their mean abundance, see [`foldchange()`](#method-foldchange) (default: 0.01).
15631567
#' @param perm A wholenumber, number of permutations to compare against the null hypothesis of \link[vegan]{adonis2} or \link[vegan]{anosim} (default: 999).
1564-
#' @param threads Number of threads to use, only used in [`distance()`](#method-distance) when beta_div_table is not supplied (default: 1).
1568+
#' @param threads Number of threads to use, only used in [`distance()`](#method-distance) when distmat is not supplied (default: 1).
15651569
#' @param report A boolean value to create a HTML markdown report (default: \code{FALSE}). If \code{FALSE} a nested list of the plots and data is returned.
15661570
#' @param filename A character to name the HTML report to be saved in the current working directory (default: \code{paste0(getwd(), "/report.html")}). The \code{getwd()} is required for rmarkdown to save it in the right path.
15671571
#' @importFrom patchwork plot_layout wrap_plots
15681572
#' @return List of plots/data or rendered HTML report
15691573
autoFlow = function(feature_contrast = "FEATURE_ID",
15701574
feature_filter = NULL,
15711575
feature_ranks = NULL,
1572-
distance_metrics = c("unifrac"),
1573-
beta_div_table = NULL,
1574-
alpha_div_table = NULL,
1576+
distance_metrics = c("bray"),
1577+
distmat = NULL,
15751578
weighted = TRUE,
15761579
pvalue.threshold = 0.05,
15771580
logfold.threshold = 1,
@@ -1593,27 +1596,24 @@ omics <- R6::R6Class(
15931596
cli::cli_abort("{.val {feature_contrast}} does not exist in {.field featureData}!")
15941597
}
15951598

1596-
if (!is.null(beta_div_table) && !is.character(beta_div_table) && length(beta_div_table) != 1) {
1597-
cli::cli_abort("{.arg beta_div_table} needs to be a character with a length of 1")
1599+
if (!is.null(distmat) && !is.character(distmat) && length(distmat) != 1) {
1600+
cli::cli_abort("{.arg distmat} needs to be a character with a length of 1")
15981601

1599-
if (!file.exists(beta_div_table))
1600-
cli::cli_abort("{.arg beta_div_table} does not exists!")
1601-
}
1602-
1603-
if (!is.null(alpha_div_table) && !is.character(alpha_div_table) && length(alpha_div_table) != 1) {
1604-
cli::cli_abort("{.arg alpha_div_table} needs to be a character with a length of 1")
1605-
1606-
if (!file.exists(alpha_div_table))
1607-
cli::cli_abort("{.arg alpha_div_table} does not exists!")
1602+
if (!file.exists(distmat))
1603+
cli::cli_abort("{.arg distmat} does not exists!")
16081604
}
16091605

16101606
## MAIN
16111607
#--------------------------------------------------------------------#
16121608
is_empty = function(obj) {
16131609
if (length(obj) == 0) {
16141610
return(NULL)
1615-
} else {
1616-
return(obj)
1611+
} else if (length(obj) > 0) {
1612+
keep_cells <- sapply(obj, function(x) is.null(x))
1613+
obj <- obj[!keep_cells]
1614+
if (length(obj) == 0) {
1615+
return(NULL)
1616+
} else return(obj)
16171617
}
16181618
}
16191619

@@ -1666,14 +1666,9 @@ omics <- R6::R6Class(
16661666
if (CONTRAST_ncol > 0) {
16671667

16681668
# Load custom distance matrix if supplied
1669-
if (!is.null(beta_div_table)) {
1670-
beta_div_table <- private$check_matrix(filepath = beta_div_table)
1671-
beta_div_table <- beta_div_table[private$.metaData[[private$.sample_id]], private$.metaData[[private$.sample_id]]]
1672-
}
1673-
1674-
# Load custom rarefraction alpha diversity table if supplied
1675-
if (!is.null(alpha_div_table)) {
1676-
alpha_div_table <- private$check_table(alpha_div_table)
1669+
if (!is.null(distmat)) {
1670+
distmat <- private$check_matrix(filepath = distmat)
1671+
distmat <- distmat[private$.metaData[[private$.sample_id]], private$.metaData[[private$.sample_id]]]
16771672
}
16781673

16791674
# Initialize plot containers
@@ -1697,52 +1692,53 @@ omics <- R6::R6Class(
16971692
#--------------------------------------------------------------------#
16981693
## Alpha diversity
16991694
#--------------------------------------------------------------------#
1700-
if (inherits(alpha_div_table, "data.table")) {
1701-
res <- diversity_plot(
1702-
data = alpha_div_table,
1703-
values = "alpha_div",
1704-
col_name = col_name,
1705-
palette = colormap(dt_final, col_name, "Set2"),
1706-
method = "custom"
1695+
res <- tryCatch(
1696+
{
1697+
# Default attempt
1698+
self$alpha_diversity(
1699+
col_name = col_name,
1700+
metric = "shannon",
1701+
paired = ifelse(!is.null(private$.samplepair_id), TRUE, FALSE)
17071702
)
1708-
} else {
1709-
res <- tryCatch(
1710-
{
1711-
# Default attempt
1712-
self$alpha_diversity(
1713-
col_name = col_name,
1714-
metric = "shannon",
1715-
paired = ifelse(!is.null(private$.samplepair_id), TRUE, FALSE)
1716-
)
1717-
},
1718-
error = function(e) {
1719-
cli::cli_alert_warning("alpha_diversity with paired=TRUE failed. Retrying with paired=FALSE.")
1720-
self$alpha_diversity(
1721-
col_name = col_name,
1722-
metric = "shannon",
1723-
paired = FALSE
1724-
)
1725-
}
1726-
)
1727-
}
1728-
1729-
## Save plots & data
1730-
alpha_div_plots[[i]] <- res$plot
1731-
alpha_div_data[[i]] <- list(data = res$data, stats = res$stats)
1732-
1733-
### Identify significant groups for composition plots & volcano plots
1734-
signif_pairs <- res$stats[res$stats$p.adj < pvalue.threshold, ][c("group1", "group2")]
1735-
if (nrow(signif_pairs) > 0)
1736-
conditions <- signif_pairs
1703+
},
1704+
error = function(e) {
1705+
cli::cli_alert_warning("{.arg alpha_diversity} with {.val paired=TRUE} failed. Retrying with {.val paired=FALSE}.")
1706+
1707+
# Retry with paired = FALSE
1708+
res2 <- tryCatch(
1709+
self$alpha_diversity(
1710+
col_name = col_name,
1711+
metric = "shannon",
1712+
paired = FALSE
1713+
),
1714+
error = function(e2) {
1715+
cli::cli_alert_info("Skipping {.arg alpha_diversity}, which failed due to an error: {.val {e2}}.")
1716+
NULL
1717+
}
1718+
)
1719+
res2
1720+
}
1721+
)
1722+
1723+
if (!is.null(res)) {
1724+
## Save plots & data
1725+
alpha_div_plots[[i]] <- res$plot
1726+
alpha_div_data[[i]] <- list(data = res$data, stats = res$stats)
17371727

1728+
### Identify significant groups for composition plots & volcano plots
1729+
signif_pairs <- res$stats[res$stats$p.adj < pvalue.threshold, ][c("group1", "group2")]
1730+
if (nrow(signif_pairs) > 0)
1731+
conditions <- signif_pairs
1732+
}
1733+
17381734
#--------------------------------------------------------------------#
17391735
## Beta diversity
17401736
#--------------------------------------------------------------------#
1741-
1737+
17421738
for (j in 1:metrics_nrow) {
1743-
if (inherits(beta_div_table, "Matrix")) {
1739+
if (inherits(distmat, "Matrix")) {
17441740
res <- self$ordination(
1745-
distmat = beta_div_table,
1741+
distmat = distmat,
17461742
method = "pcoa",
17471743
perm = perm,
17481744
group_by = col_name
@@ -1784,9 +1780,9 @@ omics <- R6::R6Class(
17841780
)
17851781

17861782
# Creates temporary plot results for NMDS
1787-
if (inherits(beta_div_table, "Matrix")) {
1783+
if (inherits(distmat, "Matrix")) {
17881784
res <- self$ordination(
1789-
distmat = beta_div_table,
1785+
distmat = distmat,
17901786
method = "nmds",
17911787
group_by = col_name,
17921788
perm = perm
@@ -1822,21 +1818,25 @@ omics <- R6::R6Class(
18221818
#--------------------------------------------------------------------#
18231819

18241820
for (j in 1:feature_nrow) {
1825-
# Creates composition long table
1826-
res <- self$composition(
1827-
feature_rank = feature_contrast[j],
1828-
feature_filter = feature_filter,
1829-
feature_top = 15,
1830-
col_name = col_name
1831-
)
1832-
# Creates composition ggplot and stores plot with data
1833-
composition_plots[[i, j]] <- composition_plot(
1834-
data = res$data,
1835-
palette = res$palette,
1836-
feature_rank = feature_contrast[j],
1837-
group_by = col_name
1838-
)
1839-
composition_data[[i, j]] <- list(data = res$data)
1821+
if (!any(private$.countData@x < 0, na.rm = TRUE)) {
1822+
# Creates composition long table
1823+
res <- self$composition(
1824+
feature_rank = feature_contrast[j],
1825+
feature_filter = feature_filter,
1826+
feature_top = 15,
1827+
col_name = col_name
1828+
)
1829+
# Creates composition ggplot and stores plot with data
1830+
composition_plots[[i, j]] <- composition_plot(
1831+
data = res$data,
1832+
palette = res$palette,
1833+
feature_rank = feature_contrast[j],
1834+
group_by = col_name
1835+
)
1836+
composition_data[[i, j]] <- list(data = res$data)
1837+
} else {
1838+
cli::cli_alert_info("Skipping {.arg composition} method due to the detection of negative values.")
1839+
}
18401840

18411841
if (!is.null(conditions) && nrow(conditions) > 0) {
18421842

@@ -1870,21 +1870,21 @@ omics <- R6::R6Class(
18701870
)
18711871
}
18721872
)
1873-
if (class(self)[1] %in% c("omics", "proteomics")) {
1874-
dfe$data$p.adj <- p.adjust(p = dfe$data$pvalue_1, method = "fdr")
1875-
dfe$volcano_plot <- volcano_plot(
1876-
data = dfe$data,
1877-
logfold_col = "Log2FC_1",
1878-
pvalue_col = "p.adj",
1879-
feature_rank = feature_contrast[j],
1880-
abundance_col = "abun",
1881-
label_A = conditions$group1,
1882-
label_B = conditions$group2,
1883-
pvalue.threshold = pvalue.threshold,
1884-
abundance.threshold = abundance.threshold,
1885-
logfold.threshold = logfold.threshold
1886-
)
1887-
}
1873+
# if (class(self)[1] %in% c("omics", "proteomics")) {
1874+
# dfe$data$p.adj <- p.adjust(p = dfe$data$pvalue_1, method = "fdr")
1875+
# dfe$volcano_plot <- volcano_plot(
1876+
# data = dfe$data,
1877+
# logfold_col = "Log2FC_1",
1878+
# pvalue_col = "p.adj",
1879+
# feature_rank = feature_contrast[j],
1880+
# abundance_col = "abun",
1881+
# label_A = conditions$group1,
1882+
# label_B = conditions$group2,
1883+
# pvalue.threshold = pvalue.threshold,
1884+
# abundance.threshold = abundance.threshold,
1885+
# logfold.threshold = logfold.threshold
1886+
# )
1887+
# }
18881888
Log2FC_plots[[i, j]] <- patchwork::wrap_plots(dfe$volcano_plot, nrow=1)
18891889
Log2FC_data[[i, j]] <- list(data = dfe$data)
18901890
}

R/volcano_plot.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ volcano_plot <- function(data,
168168
}
169169
plt <- plt +
170170
scale_size_continuous(name = "Mean Abundance (%)") +
171-
labs(x = paste0("Fold Change log2( ", label_A," / ", label_B," )"),
171+
labs(x = paste0("Fold Change ( ", label_A," / ", label_B," )"),
172172
y = paste0("-log10( ", pvalue_col ," )"))
173173

174174
return(plt)

0 commit comments

Comments
 (0)