---
output: github_document
---

<!-- README.md is generated from README.Rmd. Please edit that file -->

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%"
)
```

# ggNetView <img src="man/figures/logo.png" align="right" width="240" hight="240" />

<!-- badges: start -->
<!-- badges: end -->

ggNetView: An R Package for Reproducible Biological Network Analysis and Visualization. It provides flexible and publication-ready tools for exploring complex biological and ecological networks.


[GitHub Repository](https://github.com/Jiawang1209/ggNetView)

[User Manual](https://jiawang1209.github.io/ggNetView-manual/) 

[Zenodo DOI](https://doi.org/10.5281/zenodo.20175076) 






## Installation

`ggNetView` depends on a number of CRAN packages. We recommend installing the required dependencies first, and then installing `ggNetView` from GitHub.

Current development release: v0.1.0

### Step1: install CRAN dependencies

```
cran_pkgs <- c(
  "boot", "dplyr", "FNN", "future", "future.apply",
  "ggforce", "ggnewscale", "ggplot2", "ggraph", "ggrepel",
  "Hmisc", "huge", "igraph", "magrittr", "MASS",
  "Matrix", "patchwork", "progressr", "psych", "purrr",
  "qgraph", "Rcpp", "RcppArmadillo", "readr", "rlang",
  "scales", "scatterpie", "stringr", "tibble", "tidygraph",
  "tidyr", "vegan", "VGAM", "WGCNA"
)

new_pkgs <- cran_pkgs[!cran_pkgs %in% installed.packages()[, "Package"]]
if (length(new_pkgs)) install.packages(new_pkgs)
```

### Step2: (optional) install suggested packages

These packages are not required for the core functionality, but enable additional features (e.g. dynamic tree cut, node influence, vignettes, tests):

```
install.packages(c("dynamicTreeCut", "influential",
                   "knitr", "rmarkdown",
                   "RobustRankAggreg", "testthat"))
```

### Step3: install ggNetView from GitHub

```
# install.packages("devtools")
devtools::install_github("Jiawang1209/ggNetView")
```

## Example1: Co-expression Network

### Step1: load ggNetView

```{r}
library(ggplot2)
library(ggnewscale)
library(ggNetView)
```

### Step2: load Data

> You can load raw matrix

```{r}
data("otu_tab")          # raw OTU/feature count matrix (features x samples)
otu_tab[1:5, 1:5]        # peek at the first 5 rows/cols
```


> You can load rarely matrix. Note : the rownames of  `otu_rare` is the features.

```{r}
data("otu_rare")         # rarefied count matrix; rownames = features
otu_tab[1:5, 1:5]        # peek at the first 5 rows/cols
```

>

```{r}
data("otu_rare_relative")        # rarefied + relative-abundance matrix (features x samples)
otu_rare_relative[1:5, 1:5]      # peek at the first 5 rows/cols

```

> You can load node annotation. Note : the rownames of  `tax_tab` is NULL.


```{r}
data("tax_tab")          # node (taxonomy) annotation table; rownames = NULL
tax_tab[1:5, 1:5]        # peek at the first 5 rows/cols
```


### Step3: create graph object

```{r}
obj <- build_graph_from_mat(
  mat = otu_rare_relative,    # variables x samples abundance matrix
  transfrom.method = "none",  # pre-correlation transform; "none" = keep as-is
  method = "WGCNA",           # correlation backend: WGCNA::corAndPvalue
  cor.method = "pearson",     # Pearson correlation
  proc = "BH",                # multiple-testing correction (Benjamini-Hochberg)
  r.threshold = 0.7,          # |r| cutoff for keeping an edge
  p.threshold = 0.05,         # adjusted p-value cutoff
  node_annotation = tax_tab   # taxonomy joined onto each node by name
)

obj                           # tbl_graph with Modularity / Degree / Strength + taxonomy
```


### Step4: ggNetView to plot

> Basic network plot

```{r fig.align='center', fig.width=10, fig.height=10}
p1 <- ggNetView(
  graph_obj = obj,             # tbl_graph from build_graph_from_mat()
  layout = "gephi",            # node-positioning algorithm
  layout.module = "adjacent",  # place neighbouring modules close together
  group.by = "Modularity",     # node attribute used to define groups/modules
  fill.by = "Modularity",      # node attribute mapped to point fill
  pointsize = c(1, 5),         # min/max node size range
  center = F,                  # do NOT pull nodes toward each module centre
  jitter = F,                  # no positional jitter
  mapping_line = F,            # do not map edge aesthetics (uniform edges)
  shrink = 0.9,                # shrink layout inward (smaller = more compact)
  linealpha = 0.2,             # edge transparency
  linecolor = "#d9d9d9"        # edge colour
)

p1
```


```
ggsave(file = "Output/p1.pdf",
       plot = p1,
       height = 10,
       width = 10)
```


> Add outer line in netwotk plot

```{r fig.align='center', fig.width=15, fig.height=15}
p2 <- ggNetView(
  graph_obj = obj,             # tbl_graph from build_graph_from_mat()
  layout = "gephi",            # node-positioning algorithm
  layout.module = "adjacent",  # place neighbouring modules close together
  group.by = "Modularity",     # node attribute used to define groups/modules
  fill.by = "Modularity",      # node attribute mapped to point fill
  pointsize = c(1, 5),         # min/max node size range
  center = F,                  # do NOT pull nodes toward each module centre
  jitter = TRUE,               # jitter node positions to reduce overlap
  jitter_sd = 0.15,            # SD of the jitter (bigger -> more spread)
  mapping_line = TRUE,         # map edge aesthetics
  shrink = 0.9,                # shrink layout inward (smaller = more compact)
  linealpha = 0.2,             # edge transparency
  linecolor = "#d9d9d9",       # edge colour
  add_outer = T,               # draw an outer hull/line around each module
  label = T                    # show node labels
)

p2
```


```
ggsave(file = "Output/p2.pdf",
       plot = p2,
       height = 10,
       width = 10)
```


> Change the fill of node points.

```{r fig.align='center', fig.width=15, fig.height=15}
p3 <- ggNetView(
  graph_obj = obj,             # tbl_graph from build_graph_from_mat()
  layout = "gephi",            # node-positioning algorithm
  layout.module = "adjacent",  # place neighbouring modules close together
  group.by = "Modularity",     # group nodes by module
  fill.by = "Phylum",          # map point fill to taxonomy (Phylum) instead of module
  pointsize = c(1, 5),         # min/max node size range
  center = F,                  # do NOT pull nodes toward each module centre
  jitter = TRUE,               # jitter node positions to reduce overlap
  jitter_sd = 0.15,            # SD of the jitter
  mapping_line = TRUE,         # map edge aesthetics
  shrink = 0.9,                # shrink layout inward
  linealpha = 0.2,             # edge transparency
  linecolor = "#d9d9d9",       # edge colour
  add_outer = T,               # draw an outer hull/line around each module
  label = T                    # show node labels
)

p3
```


```
ggsave(file = "Output/p3.pdf",
       plot = p3,
       height = 10,
       width = 10)
```



> Change the color of node points.


```{r fig.align='center', fig.width=15, fig.height=15}
p4 <- ggNetView(
  graph_obj = obj,             # tbl_graph from build_graph_from_mat()
  layout = "gephi",            # node-positioning algorithm
  layout.module = "adjacent",  # place neighbouring modules close together
  group.by = "Modularity",     # group nodes by module
  fill.by = "Phylum",          # map point fill to taxonomy (Phylum)
  color.by = "Phylum",         # map point border colour to taxonomy (Phylum)
  pointsize = c(1, 5),         # min/max node size range
  center = F,                  # do NOT pull nodes toward each module centre
  jitter = TRUE,               # jitter node positions to reduce overlap
  jitter_sd = 0.15,            # SD of the jitter
  mapping_line = TRUE,         # map edge aesthetics
  shrink = 0.9,                # shrink layout inward
  linealpha = 0.2,             # edge transparency
  linecolor = "#d9d9d9",       # edge colour
  add_outer = T,               # draw an outer hull/line around each module
  label = T                    # show node labels
)

p4
```


```
ggsave(file = "Output/p4.pdf",
       plot = p4,
       height = 10,
       width = 10)
```



> Add node label


```{r fig.align='center', fig.width=15, fig.height=15}
p5 <- ggNetView(
  graph_obj = obj,             # tbl_graph from build_graph_from_mat()
  layout = "gephi",            # node-positioning algorithm
  layout.module = "adjacent",  # place neighbouring modules close together
  group.by = "Modularity",     # group nodes by module
  fill.by = "Modularity",      # map point fill to module
  pointsize = c(1, 5),         # min/max node size range
  center = F,                  # do NOT pull nodes toward each module centre
  jitter = TRUE,               # jitter node positions to reduce overlap
  jitter_sd = 0.15,            # SD of the jitter
  mapping_line = TRUE,         # map edge aesthetics
  shrink = 0.9,                # shrink layout inward
  linealpha = 0.2,             # edge transparency
  linecolor = "#d9d9d9",       # edge colour
  add_outer = T,               # draw an outer hull/line around each module
  label = T,                   # show node labels
  pointlabel = "top1"          # label only the top-1 hub node per module
)

p5
```

> Save Plot

```
ggsave(file = "Output/p3.pdf", 
       plot = p5,
       height = 10,
       width = 10)
```

## Example2: Subgraph

> Get information of graph_object

```{r}
Sub_module_1 <- get_subgraph(
  graph_obj = obj,        # full tbl_graph object
  select_module = "1"     # extract the subgraph for module "1"
)

names(Sub_module_1)       # components returned for the selected module
```


## Example3: Mantel-test with environment

```{r fig.align='center', fig.width=15, fig.height=15}
# load test data in ggNetView
data("Envdf_4st")   # environmental factor table (samples x env variables)
data("Spedf")       # species/community table (samples x taxa)
```


```{r fig.align='center', fig.width=15, fig.height=15}
out1 <- gglink_heatmaps(
  env = Envdf_4st,                  # environmental data frame
  spec = Spedf,                     # species/community data frame
  env_select = list(Env01 = 1:14,   # group env columns into blocks:  Env01 = cols 1-14
                    Env02 = 15:28,  #                                 Env02 = cols 15-28
                    Env03 = 29:42,  #                                 Env03 = cols 29-42
                    Env04 = 43:56), #                                 Env04 = cols 43-56
  spec_select = list(Spec01 = 1:8), # species block: Spec01 = cols 1-8
  relation_method = "correlation",  # env-spec association via correlation (vs "mantel")
  spec_layout = "circle_outline",   # arrange species heatmap as a circular outline
  cor.method = "pearson",           # Pearson correlation
  cor.use = "pairwise",             # pairwise-complete handling of missing values
  r = 6,                            # radius of the circular layout
  distance = 1,                     # spacing between heatmap blocks
  orientation = c("top_right", "bottom_right", "top_left", "bottom_left")  # placement of each env block
)

out1[[1]]                           # first plot in the returned list

```


## Example4: Mantel-test with environment

> Leave lines with a significance level less than 0.05, and change the color of heatmap.

```{r fig.align='center', fig.width=15, fig.height=15}
out2 <- gglink_heatmaps(
  env = Envdf_4st,                  # environmental data frame
  spec = Spedf,                     # species/community data frame
  env_select = list(Env01 = 1:14,   # env block Env01 = cols 1-14
                    Env03 = 29:40,  #           Env03 = cols 29-40
                    Env04 = 43:50), #           Env04 = cols 43-50
  spec_select = list(Spec01 = 1:8), # species block: Spec01 = cols 1-8
  relation_method = "correlation",  # association via correlation
  spec_layout = "circle_outline",   # circular outline layout for species heatmap
  cor.method = "pearson",           # Pearson correlation
  cor.use = "pairwise",             # pairwise-complete handling of missing values
  drop_nonsig = TRUE,               # keep only links with p < 0.05 (drop non-significant)
  HeatmapColorBar = list(c("#2166ac", "#b2182b"),   # custom low->high colour ramp per env block
                         c("#1b7837", "#762a83"),
                         c("#4393c3", "#d6604d")),
  HeatmapPointFill = "#8c6bb1",     # fill colour of heatmap anchor points
  CorePointFill = "#225ea8",        # fill colour of the central/core point
  HeatmapLabelOrient = 45,          # rotate heatmap labels by 45 degrees
  r = 6,                            # radius of the circular layout
  distance = 1,                     # spacing between heatmap blocks
  orientation = c("top_right", "top_left", "bottom_left")  # placement of each env block
)

out2[[2]]                           # second plot in the returned list

```


## Example5: Network-environment

```{r fig.align='center', fig.width=15, fig.height=15}
####----load Data----####
data("otu_rare_relative")   # rarefied relative-abundance matrix (features x samples)
data("tax_tab")             # node (taxonomy) annotation table
data("Envdf_4st_2")         # environmental factor table for the network-env analysis


####----build graph object----####
graph_obj <- build_graph_from_mat(
  mat = otu_rare_relative,       # variables x samples abundance matrix
  transfrom.method = "none",     # pre-correlation transform; "none" = keep as-is
  node_annotation = tax_tab,     # taxonomy joined onto each node by name
  p.threshold = 0.05,            # adjusted p-value cutoff
  r.threshold = 0.75,            # |r| cutoff for keeping an edge
  method = "WGCNA",              # correlation backend: WGCNA::corAndPvalue
  proc = "BH",                   # multiple-testing correction (Benjamini-Hochberg)
  module.method = "Fast_greedy", # community detection algorithm
  top_modules = 15,              # keep top-15 modules; rest -> "Others"
  seed = 1115                    # fix RNG for reproducibility
)

graph_obj                        # resulting tbl_graph


p_sub <- ggNetView(
  graph_obj = graph_obj,       # tbl_graph object
  layout = "gephi",            # node-positioning algorithm
  center = T,                  # pull nodes toward each module centre
  layout.module = "adjacent",  # place neighbouring modules close together
  group.by = "Modularity",     # group nodes by module
  fill.by = "Modularity"       # map point fill to module
)

p_sub


p_sub2 <- ggNetView(
  graph_obj = graph_obj,       # tbl_graph object
  layout = "gephi",            # node-positioning algorithm
  center = F,                  # do NOT pull nodes toward each module centre (compare with p_sub)
  layout.module = "adjacent",  # place neighbouring modules close together
  group.by = "Modularity",     # group nodes by module
  fill.by = "Modularity"       # map point fill to module
)

p_sub2

####----Network Environment PC1----####
res <- ggnetview_modularity_heatmaps(
  graph_obj,                        # network tbl_graph object
  Envdf_4st_2,                      # environmental factor table
  otu_rare_relative,                # abundance matrix (used to derive per-module index)
  env_select = list(Env01 = 1:14,   # env block Env01 = cols 1-14
                    Env02 = 15:28,   #           Env02 = cols 15-28
                    Env03 = 29:42,   #           Env03 = cols 29-42
                    Env04 = 43:56),  #           Env04 = cols 43-56
  drop_nonsig = T,                  # keep only significant module-env links
  r = 35,                           # radius of the circular heatmap layout
  distance = 5,                     # spacing between heatmap blocks
  HeatmapLabelOrient = 45,          # rotate heatmap labels by 45 degrees
  shrink = 0.65,                    # shrink the network layout inward
  module_index = "eigengene",  # 或 "abundance"   # per-module summary: eigengene (PC1)
  relation_method = "correlation",  # 或 "mantel",  # module-env association method
  HeatmapColorBar = list(           # custom low->high colour ramp per env block
    c("#2166ac", "#b2182b"),
    c("#1b7837", "#762a83"),
    c("#4393c3", "#d6604d"),
    c("#92c5de", "#f4a582")
  ),
  layout = "gephi",                 # node-positioning algorithm
  layout.module = "adjacent",       # place neighbouring modules close together
  jitter = T,                       # jitter node positions to reduce overlap
  add_outer = T,                    # draw an outer hull/line around each module
  HeatmapScale = 1.5,               # scale factor for heatmap point/tile size
  add_group_outer = T,              # draw an outer boundary around node groups
  label = F,                        # do not show node labels
  # labelsize = 5
)

res[[1]]

####----Network Environment abudance----####
res2 <- ggnetview_modularity_heatmaps(
  graph_obj,                        # network tbl_graph object
  Envdf_4st_2,                      # environmental factor table
  otu_rare_relative,                # abundance matrix (used to derive per-module index)
  env_select = list(Env01 = 1:14,   # env block Env01 = cols 1-14
                    Env02 = 15:28,   #           Env02 = cols 15-28
                    Env03 = 29:42,   #           Env03 = cols 29-42
                    Env04 = 43:56),  #           Env04 = cols 43-56
  drop_nonsig = T,                  # keep only significant module-env links
  r = 35,                           # radius of the circular heatmap layout
  distance = 5,                     # spacing between heatmap blocks
  HeatmapLabelOrient = 45,          # rotate heatmap labels by 45 degrees
  shrink = 0.65,                    # shrink the network layout inward
  module_index = "abundance",  # 或 "abundance"   # per-module summary: aggregated abundance
  relation_method = "mantel",  # 或 "mantel",      # module-env association via Mantel test
  HeatmapColorBar = list(           # custom low->high colour ramp per env block
    c("#2166ac", "#b2182b"),
    c("#1b7837", "#762a83"),
    c("#4393c3", "#d6604d"),
    c("#92c5de", "#f4a582")
  ),
  layout = "gephi",                 # node-positioning algorithm
  layout.module = "adjacent",       # place neighbouring modules close together
  jitter = T,                       # jitter node positions to reduce overlap
  add_outer = T,                    # draw an outer hull/line around each module
  HeatmapScale = 1.5,               # scale factor for heatmap point/tile size
  add_group_outer = T,              # draw an outer boundary around node groups
  label = F,                        # do not show node labels
  # labelsize = 5
)

res2[[1]]
res2[[2]]
```


## Example6: Network-compare


```{r fig.align='center', fig.width=8, fig.height=8}
# ---- Multi-network "linked" view (no per-group scale normalisation) ----
# `ggNetView_multi_link()` builds ONE network per group (defined by `group_info`),
# lays each one out independently, and places all sub-networks on a circular
# anchor frame so that cross-group edges/relationships can be visually compared.
out1 <- ggNetView_multi_link(
  mat              = otu_rare_relative, # variables x samples abundance matrix
  group_info       = otu_sample,        # sample metadata; defines how samples are split into groups
  transfrom.method = "none",            # pre-correlation transform on `mat`; "none" = keep as-is
  r.threshold      = 0.7,               # |r| cutoff for keeping an edge
  p.threshold      = 0.05,              # adjusted p-value cutoff
  method           = "WGCNA",           # correlation backend: WGCNA::corAndPvalue
  cor.method       = "pearson",         # Pearson correlation
  proc             = "BH",              # multiple-testing correction (Benjamini-Hochberg)
  module.method    = "Fast_greedy",     # community detection per sub-network
  layout.module    = "adjacent",        # neighbouring modules placed close together
  center           = T,                 # pull a node toward the centre of each sub-layout
  top_modules      = 15,                # keep top-15 modules per sub-network; rest -> "Others"
  layout           = "gephi",           # global node-positioning algorithm per sub-network
  shrink           = 0.5,               # shrink each sub-network inward (smaller = more compact)
  scale            = F,                 # do NOT normalise each group to a common scale -> sub-networks keep their native size differences
  jitter           = T,                 # jitter node positions slightly to reduce overlap
  jitter_sd        = 0.3,               # SD of the jitter (bigger -> more spread)
  anchor_dist      = 30,                 # distance between groups on the outer anchor circle
  seed             = 1115,              # fix RNG for reproducibility
  orientation      = "up",              # frame orientation; one of "up"/"down"/"left"/"right"
  angle            = 0                  # additional rotation angle (degrees)
)

p1 <- out1[["p"]]   # the assembled ggplot object
p1

out1$info           # auxiliary table: per-group node/edge counts, module info, etc.
```


```{r fig.align='center', fig.width=8, fig.height=8}
####----Plot2----####
# ---- Same setup but with `scale = TRUE` -> each group normalised to a common size ----
# Useful when groups have very different network sizes and you want them
# visually comparable side-by-side. With `scale = TRUE` the native size
# differences are removed, so jitter_sd is also reduced (0.01) accordingly.
out2 <- ggNetView_multi_link(
  mat              = otu_rare_relative,
  group_info       = otu_sample,
  transfrom.method = "none",
  r.threshold      = 0.7,
  p.threshold      = 0.05,
  method           = "WGCNA",
  cor.method       = "pearson",
  proc             = "BH",
  module.method    = "Fast_greedy",
  layout.module    = "adjacent",
  center           = T,
  top_modules      = 15,
  layout           = "gephi",
  shrink           = 0.5,
  scale            = T,                 # normalise each group to a comparable coordinate scale
  jitter           = T,
  jitter_sd        = 0.01,              # smaller jitter — sub-networks are already on a unified scale
  anchor_dist      = 1,
  seed             = 1115,
  orientation      = "up",
  angle            = 0
)


p2 <- out2[["p"]]
p2
```

## Example7: Network-topology


```{r}
# ---- Build a co-occurrence network from an abundance matrix ----
# Internal pipeline: transform -> correlation -> p-value adjustment ->
# edge filtering -> community detection -> attach taxonomy.
graph_obj <- build_graph_from_mat(
  mat              = otu_rare_relative,  # variables x samples numeric matrix
  transfrom.method = "none",             # input already relative abundance, no extra transform
  method           = "WGCNA",            # correlation backend: WGCNA::corAndPvalue
  proc             = "bonferroni",       # multiple-testing correction
  r.threshold      = 0.7,                # |r| cutoff for keeping an edge
  p.threshold      = 0.05,               # adjusted p-value cutoff
  node_annotation  = tax_tab,            # taxonomy joined onto each node by name
  top_modules      = 15,                 # keep top-15 modules; rest -> "Others"
  seed             = 1115                # fix RNG for reproducibility
)

graph_obj   # tbl_graph with Modularity / Degree / Strength + taxonomy columns



# ---- Compute the FULL set of network topology + robustness metrics ----
# When `mat` is provided, the function recomputes the thresholded correlation
# matrix from `mat` (used as `network.raw`) and ALL topology fields are
# returned with real values - including the ones that are NA when mat = NULL:
#   Cohension_Positive / Cohension_Negative
#   Robustness_weight  / Robustness_unweight
#   Stability
#   out$Robustness     (the 5%-100% node-removal curve)
topology_with_mat <- get_network_topology(
  graph_obj        = graph_obj,         # input tbl_graph (required)
  mat              = otu_rare_relative, # raw abundance matrix used to derive sp.ra and rebuild network.raw
  transfrom.method = "none",            # pre-correlation transform on `mat`; "none" = keep as-is
  method           = "WGCNA",           # correlation backend: WGCNA::corAndPvalue
  proc             = "bonferroni",      # multiple-testing correction
  r.threshold      = 0.7,               # |r| cutoff for keeping an edge in network.raw
  p.threshold      = 0.05,              # adjusted p-value cutoff for keeping an edge
  bootstrap        = 100                # # of bootstrap iterations for robustness AND # of random ER networks for the Random_nerwork column
)


topology_with_mat
```


## Example8: Zi-Pi

```{r}
# Extract the two inputs Zi-Pi needs from graph object
nodes_bulk <- get_graph_nodes(obj)      # node table (module + degree cols)
adj_mat    <- get_graph_adjacency(obj)  # adjacency / correlation matrix


role_palette <- c(
  "Peripherals"  = "#377eb8",
  "Connectors"   = "#4daf4a",
  "Module hubs"  = "#e41a1c",
  "Network hubs" = "#ff7f00"
)

# Compute Zi-Pi and classify
zp <- ggnetview_zipi(
  nodes_bulk     = nodes_bulk,    # node table: IDs in rownames or a `name` col
  z_bulk_mat     = adj_mat,       # adjacency matrix; non-zero entries = edges
  modularity_col = "Modularity",  # column holding module labels (no NAs)
  degree_col     = "Degree",      # column holding node degree   (no NAs)
  zi_threshold   = 2.5,           # Zi cutoff for role classification
  pi_threshold   = 0.62,          # Pi cutoff for role classification
  na.rm          = FALSE,         # FALSE = keep unclassifiable nodes (type = NA)
  point_colors   = role_palette,  # point + legend colours, keyed by role
  bg_colors      = c(             # quadrant background fills, keyed by role
    "Peripherals"  = "#f0f0f0",
    "Connectors"   = "#d9f0d3",
    "Module hubs"  = "#fde0dd",
    "Network hubs" = "#fee8c8"
  ),
  label_colors   = role_palette,  # quadrant text-label colours (default: black)
  label_size     = 5,             # quadrant text-label size  (default 5.5)
  bg_alpha       = 0.35           # background opacity 0..1    (default 0.25)
)

class(zp)

names(zp)

zp$plot
```


## Example9: RMT threshold


```
# ---- RMT threshold scan #1: WGCNA correlation backend ----
# `ggNetView_RMT()` scans a series of candidate |r| thresholds, builds the
# thresholded correlation matrix at each, computes its eigenvalue spacing
# distribution (NNSD), and picks the threshold at which the NNSD transitions
# from Gaussian Orthogonal Ensemble (signal + noise) to Poisson (noise-free,
# modular network) — this is the RMT-recommended cutoff.
out <- ggNetView_RMT(
  mat              = otu_rare_relative, # input matrix (variables x samples)
  transfrom.method = "none",            # already relative-abundance, no extra transform
  method           = "WGCNA",           # use WGCNA::corAndPvalue for correlation
  cor.method       = "pearson",         # Pearson correlation
  unfold.method    = "gaussian",        # Gaussian KDE unfolding of eigenvalues
  bandwidth        = "nrd0",            # KDE bandwidth rule (stats::density default)
  nr.fit.points    = 20,                # support points (only used if unfold.method = "spline")
  discard.outliers = TRUE,              # IQR-trim extreme eigenvalues before unfolding
  discard.zeros    = TRUE,              # drop all-zero rows/cols after thresholding
  min.mat.dim      = 40,                # early-stop if effective dim drops below 40
  max.ev.spacing   = 3,                 # truncate NNSD tail at spacing = 3
  save_plots       = FALSE,             # don't write diagnostic PNGs to disk
  out_dir          = "RMT_plots",       # (only used when save_plots = TRUE)
  verbose          = TRUE,              # print scan progress to console
  seed             = 1115               # fix RNG for reproducibility
)

# The chosen threshold to feed downstream into build_graph_from_mat(r.threshold = ...)
out$chosen_threshold
```



## sessionInfo

```{r}
sessionInfo()
```


#### Citation

If you use ggNetView in your research, please cite:

```
Yue Liu, Chao Wang (2026). ggNetView: An R Package for Reproducible Biological Network Analysis and Visualization.
```

#### Github & Manual

```
https://github.com/Jiawang1209/ggNetView
https://jiawang1209.github.io/ggNetView-manual/
```

<h4 align="center">©微信公众号 RPython</h5>
