Skip to content

Introduce plotForest#220

Open
RiboRings wants to merge 17 commits intodevelfrom
plotForest
Open

Introduce plotForest#220
RiboRings wants to merge 17 commits intodevelfrom
plotForest

Conversation

@RiboRings
Copy link
Member

@RiboRings RiboRings commented Jan 22, 2026

Hi!

The plotForest viz is ready to be shared! (check vignettes for usage)

It features methods for both (Tree)SE and dataframes containing statistical results. All relevant variables (effects, CI upper and lower boundaries, pvals, id cols) are encoded by arguments for convenience and flexibility.

plotForest can be applied to both rowData and colData, with the option to add tree hierarchy and labels on the side, and also comparing between two groups (paired forest plot).

While minor aesthetic add-ons could be considered for future PRs, I think the main functionality is already there and is quite broad.

Happy to hear your comments,
Giulio

@RiboRings RiboRings linked an issue Jan 22, 2026 that may be closed by this pull request
Copy link
Member

@antagomir antagomir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Just some suggestions.

@RiboRings
Copy link
Member Author

RiboRings commented Jan 26, 2026

Now the vignettes use DAA results from Maaslin3.

While testing, I also added plotForest visualisation to the differential abundance chapter of OMA, for all the different methods. I could open a PR there.

Copy link
Contributor

@TuomasBorman TuomasBorman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments. Looks good!

Comment on lines 262 to 276
# Generate forest plot components
plots <- .plot_forest(
x = x,
effect.var = effect.var,
ci.lower.var = ci.lower.var,
ci.upper.var = ci.upper.var,
err.var = err.var,
pval.var = pval.var,
id.var = id.var,
label.by = label.by,
order.by = order.by,
facet.by = facet.by,
color.by = color.by,
conf.level = conf.level
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function could be splitted. The recommendation of function length is under 50 lines. For instance it can be splitted:

  1. Check input
  2. Do all the data wrangling, the data should be directly ready for plotting
  3. Do the plotting

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit tricky because its parts are quite inter-dependent. I'll check if I can come up with a clever way to split it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did the best I could to break it into parts. How does it look now?

@codecov
Copy link

codecov bot commented Jan 31, 2026

Codecov Report

❌ Patch coverage is 79.68750% with 39 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.39%. Comparing base (5a7c3ae) to head (3cc9f90).
⚠️ Report is 12 commits behind head on devel.

Files with missing lines Patch % Lines
R/plotForest.R 79.47% 39 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            devel     #220      +/-   ##
==========================================
+ Coverage   57.71%   61.39%   +3.68%     
==========================================
  Files          21       22       +1     
  Lines        3493     3865     +372     
==========================================
+ Hits         2016     2373     +357     
- Misses       1477     1492      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@TuomasBorman TuomasBorman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay. Here are couple final comments; most of them are thoughts and can be ignored if justified

"specified with 'pval.var'.", call. = FALSE)
}
# Check aesthetics
aes.list <- list(order.by = order.by, facet.by = facet.by, color.by = color.by)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elswehere normal variables are with underscore

aes_list.

I would change this

Comment on lines +194 to +199
# Check kwargs
kwargs <- list(...)
if( !show.tree && length(kwargs) != 0 ){
warning("Arguments in '...' are ignored when 'show.tree' is FALSE.",
call. = FALSE)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might also drop this check, because this is already told here

@param ... additional parameters passed to \code{\link{plotRowTree}}.

Also I feel that this is easily forgotten, if support for optional arguments is added in the future (for instance tweaking line sizes etc)

#' colour.by = "association"
#' )
#'
#' @author Giulio Benedetti
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be removed (can you also remove plotAbundanceDensity.R line 96). Functionas are collectively maintained and GH shows exact contributions already

tree.FUN <- switch(by, rowTree, colTree)
treename.FUN <- switch(by, rowTreeNames, colTreeNames)
treeplot.FUN <- switch(by, plotRowTree, plotColTree)
# Extract side information from SE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a first step, you could run

.get_object_and_trimmed_tree()

TreeSE can include multiple trees. It seems that this is not fully taken into account yet. E.g., it can be that the rows in TreeSE do not match with nodes in plotted tree (because the rows are included in the second tree)

}

#' @importFrom patchwork wrap_plots
.combine_forest_components <- function(x, effect.var, ci.lower.var, ci.upper.var,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run BiocCheck::BiocCheck(). I guess this line is too wide

Comment on lines +63 to +64
p <- plotForest(df2, id.var = "ID")
expect_s3_class(p, "ggplot")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to add test that checks that the values are correct?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce plotForest

3 participants