---
title: "Using ggpicrust2"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Using ggpicrust2}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5
)
```

## Introduction

`ggpicrust2` provides a practical workflow for PICRUSt2 downstream analysis:

- convert KO profiles to pathway-level abundance when needed
- run differential abundance analysis with multiple methods
- annotate and visualize pathway-level results
- inspect taxa-level contribution using PICRUSt2 per-sequence outputs
- perform GSEA when pathway-set analysis is more appropriate than single-feature testing

This vignette focuses on the general package workflow. For a deeper GSEA walkthrough, see the dedicated `gsea_analysis` vignette.

## Installation and example data

Install the package and the optional backends used by this tutorial:

```{r installation, eval = FALSE}
install.packages(c("ggpicrust2", "MicrobiomeStat", "BiocManager"))
BiocManager::install(c("KEGGREST", "limma"))
```

```{r example-data, eval = FALSE}
library(ggpicrust2)
library(tibble)
data("ko_abundance")
data("metadata")
alpha <- 0.05
```

Both workflows below use the same data, LinDA method, and adjusted p-value
threshold. LinDA accepts the continuous abundance estimates produced by
`ko2kegg_abundance()`, but its default count-data winsorization rounds values
inside MicrobiomeStat. In a direct `pathway_daa()` call, set
`linda_winsor = FALSE` to preserve fractional values and
`linda_adaptive = FALSE` for fixed pseudo-count handling. A fixed pseudo-count
still depends on the units of the input when zeros are present.
Count-based methods such as ALDEx2 require integer input and the package
rounds non-integer input with a warning. Choose the
method for its assumptions and your study design, not to obtain significance.
KEGG pathway annotation requires internet access and `KEGGREST`.

## One-command workflow

```{r one-command, eval = FALSE}
results <- ggpicrust2(
  data = ko_abundance,
  metadata = metadata,
  group = "Environment",
  pathway = "KO",
  daa_method = "LinDA",
  ko_to_kegg = TRUE,
  order = "pathway_class",
  p_values_bar = TRUE,
  p_values_threshold = alpha,
  x_lab = "pathway_name"
)

# A method's plot is NULL when no pathways can be plotted.
results[[1]]$plot
head(results[[1]]$results)
```

## Stepwise pathway workflow

Run the installation and example-data setup above first. This workflow uses
the same analysis settings as the one-command workflow.

### Convert KO abundance to KEGG pathway abundance

```{r ko-to-kegg, eval = FALSE}
kegg_pathway_abundance <- ko2kegg_abundance(data = ko_abundance)
head(kegg_pathway_abundance[, 1:3])
```

### Match group labels to sample identifiers

`pathway_daa()`, `pathway_heatmap()`, and `pathway_pca()` accept `metadata`
and a column name, such as `group = "Environment"`. In contrast,
`pathway_errorbar()` has no metadata argument: its capitalized `Group`
parameter requires one group label per abundance column, not a column name.

The bundled metadata and abundance table have different sample orders.
Name the group vector with sample IDs so that plotting aligns labels to the
correct samples. For your own data, replace `sample_name` and `Environment`
with your sample-ID and grouping columns. Do not pass an unnamed metadata
column unless you have already verified its order against the abundance columns.

```{r sample-groups, eval = FALSE}
stopifnot(
  !anyNA(metadata$sample_name),
  !anyDuplicated(metadata$sample_name),
  setequal(colnames(kegg_pathway_abundance), metadata$sample_name)
)
sample_groups <- setNames(metadata$Environment, metadata$sample_name)
```

### Run differential abundance analysis

```{r daa, eval = FALSE}
daa_results <- pathway_daa(
  abundance = kegg_pathway_abundance,
  metadata = metadata,
  group = "Environment",
  daa_method = "LinDA"
)

head(daa_results)
```

### Annotate pathway results

```{r annotation, eval = FALSE}
annotated_daa <- pathway_annotation(
  pathway = "KO",
  daa_results_df = daa_results,
  ko_to_kegg = TRUE,
  p_adjust_threshold = alpha
)

head(annotated_daa)
```

### Visualize pathway-level results

`ko_to_kegg = TRUE` is required here too: the rows are KEGG pathways and
use `pathway_name` annotations. This flag does not reconvert the abundance
matrix in the plotting function.

```{r errorbar, eval = FALSE}
sig_pathways <- unique(annotated_daa$feature[
  !is.na(annotated_daa$p_adjust) & annotated_daa$p_adjust < alpha
])

p <- NULL
if (length(sig_pathways) > 0) {
  p <- pathway_errorbar(
    abundance = kegg_pathway_abundance,
    daa_results_df = annotated_daa,
    Group = sample_groups,
    ko_to_kegg = TRUE,
    p_values_threshold = alpha,
    order = "pathway_class",
    x_lab = "pathway_name"
  )
} else {
  message("No pathways pass the adjusted p-value threshold; skipping the error bar plot.")
}
p
```

No significant pathways is a valid analysis outcome. Keep the results table;
do not increase the threshold or change methods just to produce a plot.
Missing KEGG annotations can also prevent plotting even when significant
results exist; check the annotation warnings separately.

```{r heatmap-pca, eval = FALSE}
if (length(sig_pathways) > 0) {
  pathway_heatmap(
    abundance = kegg_pathway_abundance[sig_pathways, , drop = FALSE],
    metadata = metadata,
    group = "Environment"
  )
}

pathway_pca(
  abundance = kegg_pathway_abundance,
  metadata = metadata,
  group = "Environment"
)
```

### Using ALDEx2 instead

ALDEx2 is an optional Bioconductor dependency. For two groups it returns
both Welch and Wilcoxon results, so select one test before annotation and
plotting. Otherwise a pathway can occur twice with different p-values.
Specify the test in advance. ALDEx2 uses Monte Carlo sampling, so set a seed
for reproducibility; results can still differ across package versions.

```{r aldex2-alternative, eval = FALSE}
# Install once with BiocManager::install("ALDEx2").
set.seed(207)
aldex_results <- pathway_daa(
  abundance = kegg_pathway_abundance,
  metadata = metadata,
  group = "Environment",
  daa_method = "ALDEx2"
)
daa_results <- aldex_results[
  aldex_results$method == "ALDEx2_Welch's t test", , drop = FALSE
]
```

Then rerun the annotation and visualization steps with this `daa_results`.
For more than two groups or multiple contrasts, inspect `method`, `group1`,
and `group2` and select the supported test/contrast explicitly. An ALDEx2
run can have no adjusted p-values below 0.05 even when LinDA finds some;
these are different statistical procedures, not equivalent plotting modes.

## Taxa contribution workflow

PICRUSt2 contribution files attribute predicted functional abundance to taxa. `ggpicrust2` supports both gene-family-level and pathway-level contribution workflows.

### Run a synthetic contribution example

This small example illustrates input schemas and aggregation. It is not a
biological result, and its sample IDs are separate from the bundled KO dataset.

```{r contrib-example, eval = FALSE}
contrib_input <- expand.grid(
  sample = paste0("S", 1:4),
  function_id = c("K00001", "K00002"),
  taxon = c("ASV1", "ASV2"),
  stringsAsFactors = FALSE
)
contrib_input$taxon_function_abun <- seq_len(nrow(contrib_input))
contrib_data <- read_contrib_file(data = contrib_input)
contrib_metadata <- data.frame(
  sample_name = paste0("S", 1:4),
  Environment = rep(c("Control", "Treatment"), each = 2)
)
taxonomy <- data.frame(
  ASV = c("ASV1", "ASV2"),
  Genus = c("ExampleGenusA", "ExampleGenusB")
)
taxa_contrib <- aggregate_taxa_contributions(
  contrib_data, taxonomy = taxonomy, tax_level = "Genus", top_n = 2
)
head(taxa_contrib)
```

The aggregation sums the selected contribution column. By default it prefers
`norm_taxon_function_contrib` when supplied; this example supplies raw
`taxon_function_abun` only. A percentage bar subsequently normalizes within
each sample/function, so its heights describe the taxonomic composition of
that function, not a between-function abundance comparison.

```{r contrib-plots, eval = FALSE}
taxa_contribution_bar(
  contrib_agg = taxa_contrib,
  metadata = contrib_metadata,
  group = "Environment",
  facet_by = "function"
)
taxa_contribution_heatmap(contrib_agg = taxa_contrib, n_functions = 2)
```

### Read your own PICRUSt2 files

For real data, replace the synthetic input with one of the readers below and
use metadata and taxonomy for those same samples and taxa:

```r
# KO/gene-family contributions:
# contrib_data <- read_contrib_file("pred_metagenome_contrib.tsv")
# Pathway contributions (often MetaCyc):
# contrib_data <- read_pathway_contrib_file("path_abun_contrib.tsv.gz")
# Wide stratified abundance:
# contrib_data <- read_strat_file("pred_metagenome_strat.tsv")
```

When optional `daa_results_df` or `pathway_ids` filters contain KEGG pathway IDs
and the contribution table is KO-level, the function expands those pathway IDs
to KO members and retains matching KO rows. It does not turn KO contributions
into pathway contributions. The output `function_id` remains a KO identifier.
For pathway-level MetaCyc contributions, matching MetaCyc IDs are filtered
directly. Do not interpret a member-KO filter as independent evidence that a
taxon drives a reconstructed pathway's activity.

For pathway-level data, use matching pathway annotations. For example:

```{r pathway-contrib-example, eval = FALSE}
path_input <- contrib_input
path_input$function_id <- ifelse(path_input$function_id == "K00001",
                                  "GLYCOLYSIS", "PWY-5484")
path_data <- read_pathway_contrib_file(data = path_input)
path_taxa_contrib <- aggregate_taxa_contributions(
  path_data, taxonomy = taxonomy, tax_level = "Genus", top_n = 2
)
pathway_annotation_df <- pathway_annotation(
  data = data.frame(function_id = unique(path_taxa_contrib$function_id)),
  pathway = "MetaCyc"
)
```

## GSEA workflow

Use GSEA when you want pathway-set level inference from KO or EC abundance rather than testing each pathway independently.

```{r gsea, eval = FALSE}
gsea_results <- pathway_gsea(
  abundance = ko_abundance %>% column_to_rownames("#NAME"),
  metadata = metadata,
  group = "Environment",
  pathway_type = "KEGG",
  method = "camera"
)

annotated_gsea <- gsea_pathway_annotation(
  gsea_results = gsea_results,
  pathway_type = "KEGG"
)

visualize_gsea(
  gsea_results = annotated_gsea,
  plot_type = "barplot",
  n_pathways = 15
)
```

For a method-by-method GSEA explanation, covariate adjustment, and comparison with DAA, see the `gsea_analysis` vignette.

## Summary

The package is easiest to use when you choose the shortest path that matches your question:

- use `ggpicrust2()` for a fast default pathway workflow
- use the stepwise DAA functions when you need more control
- use the taxa contribution workflow when you need taxon-level attribution
- use `pathway_gsea()` when pathway-set enrichment is the primary question
