---
title: "A biological network: HMP/U01"
output:
  rmarkdown::html_vignette:
    toc: true
vignette: >
  %\VignetteIndexEntry{A biological network: HMP/U01}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

<style>
body { max-width: 1050px; }
body:has(nav.navbar) { max-width: none; }
.ivue-legend { max-width: 100%; }
.rglWebGL { max-width: 100%; }
th, td { vertical-align: top; }
pre { overflow-x: auto; }
</style>

```{r setup, include=FALSE}
library(grip)
knitr::opts_chunk$set(dev="jpeg", dev.args=list(quality=90), fig.retina=1, dpi=72, collapse=TRUE,comment='#>',fig.width=9,fig.height=5,out.width='100%')
source(system.file('scripts','vignette-views.R',package='grip'),local=TRUE)
```

Installed figures use static projections. To enable 3D rotation and layout
selection, render with `options(grip.vignette.interactive = TRUE)` and
**ivue** and **rgl** installed.


This graph summarizes similarities among HMP+U01 16S amplicon samples.
The supplied object records a representation based on taxa at at least 1%
relative abundance followed by principal component analysis, and a
nearest-neighbor construction with k=3. Coarsening reduces the original giant
component to 1,828 vertices and 4,656 weighted edges.

The biological labels are **community state types (CSTs)** and finer subtypes.
Use them to interpret groups in the drawing; separated colors do not by
themselves establish that the geometry is accurate.

## Inspect the graph

```{r graph}
data(hmp.u01.gc.coarse)
g <- hmp.u01.gc.coarse
knitr::kable(data.frame(Quantity=c('Original giant-component vertices',
  'Coarsened vertices','Undirected edges','Selected k'),
  Value=unlist(g$graph_info[c('original_vertices','coarse_vertices','edge_count','selected_k')],use.names=FALSE)))
```

The original giant component has 6,474 vertices. Seven other components were
discarded in the recorded preparation; no claim is made here about their
arrangement. This coarsened weighted HMP/U01 object differs from the unweighted
HMP graph in the external-engine comparison.

## Compare three layouts

The panels show **SGD metric MDS**, **weighted GRIP**
(`metric="edge_length"`) and **hop-based GRIP**. The SGD and weighted-GRIP fits
use the same coarsened graph, positive edge lengths, three dimensions and seed
1. SGD uses full weighted graph distances, uniform pair weights, a random
start and a 200-iteration budget, without edge-KK refinement. Weighted GRIP
uses its edge-length hierarchy and default optimization settings. This is a
one-seed illustration, not a controlled method-ranking experiment.

Hop-based GRIP uses supplied edge lengths for adjacent attractions and hop
distances for hierarchy searches. The figure shows its default preset with
seed 1. The preset comparison below also includes tree and torus settings.

```{r saved, include=FALSE}
results <- readRDS(system.file('extdata','hmp_u01_gc_coarse','vignette_results.rds',package='grip'))
edges <- do.call(rbind,lapply(seq_along(g$adj_list),function(i) {
  j <- g$adj_list[[i]];j <- j[j>i];cbind(rep(i,length(j)),j)
}))
```

```{r hmp-view, echo=FALSE}
fresh <- readRDS(system.file('extdata','hmp_u01_gc_coarse','weighted_layouts.rds',package='grip'))
documentation.group.layouts(list(
  `SGD metric MDS`=fresh$sgd$value$coords,
  `Weighted GRIP`=fresh$weighted_grip$value,
  `Hop-based GRIP`=results$layouts$preset$default),
  edges,g$vertex_data$cst,
  description='HMP/U01: CST colors are identical across layouts.')
```

Rotation helps distinguish actual branches from overlaps in projection.
Coordinates are centered and uniformly rescaled to the same root-mean-square
radius for display, so each method is visible despite its different fitted
scale. Shapes and orientations are preserved, with common bounds and an
unchanged camera when switching. CST colors remain fixed. Saved coordinates
and diagnostics are unchanged; this display does not compare absolute scale
or align layouts to a biological reference.

### Fit status

```{r new-status}
knitr::kable(fresh$sgd$value$metadata$starts,digits=4)
knitr::kable(data.frame(Method=c("SGD metric MDS","Weighted GRIP"),
  Seconds=c(fresh$sgd$elapsed_seconds,fresh$weighted_grip$elapsed_seconds)),digits=2)
```

An iteration limit means that SGD returned coordinates without meeting its
stopping criterion. Weighted GRIP uses a fixed optimization schedule; returning
a layout is not a convergence claim. The scores below describe the
hop-based preset candidates; they do not score the SGD or weighted-GRIP fits.

## Compare the recorded candidates

```{r preset-scores}
knitr::kable(results$preset_summary[,c('candidate','sampled.stress.mean',
  'edge.length.cv.mean','cluster.separation.mean','score.composite')],digits=3)
```

Stress describes graph-distance agreement; cluster separation describes the
CST labels. Their priorities may differ. This saved search has one seed per
candidate, so it does not measure variation over random starts.

The recorded local search varied final refinement rounds and repulsion near
the selected settings. Its full summaries and individual outcomes are retained
in `results$local_search_summary` and `results$local_search_runs`.

```{r local-scores}
knitr::kable(results$local_search_summary[,c('candidate','final.rounds',
  'repulsion.factor','sampled.stress.mean','cluster.separation.mean')],digits=3)
```

## Reproduce the weighted fits

Start with SGD metric MDS for a new weighted graph-distance fit. The
edge-length GRIP alternative used in the figure is shown below. This
recipe uses edge-length distances; the preset tables above use hop-based GRIP.

```{r new-weighted, eval=FALSE}
mds <- metric.mds(adj.list=g$adj_list,weight.list=g$weight_list,
  n=length(g$adj_list),dim=3,backend='sgd',init='random',seed=1,
  max.iter=200,pair.weights='uniform',diagnostics=FALSE)
coords <- grip(adj.list=g$adj_list,weight.list=g$weight_list,
  n=length(g$adj_list),dim=3,metric='edge_length',seed=1)
score.layout(coords,adj.list=g$adj_list,weight.list=g$weight_list,
  n=length(g$adj_list),clusters=g$vertex_data$cst,edge.crossings='never')
```

See [weighted layouts](weighted-grip-intro.html) for the metric semantics and
[Choosing and evaluating](grip-real-data.html) for repeated seeds and candidate
selection.

## Data and coarsening record

The object contains `adj_list`, parallel `weight_list`, `vertex_data`, and
`graph_info`. The vertex metadata includes aggregated CST and subtype labels.
The recorded coarsening rounds are:

```{r coarsening}
knitr::kable(g$graph_info$coarsening_rounds)
```

Saved results reside in `extdata/hmp_u01_gc_coarse/vignette_results.rds` in the
installed package. They include candidate settings, scores, fitted coordinates,
and the software session. To run the hop-based preset comparison into a separate
file, explicitly set the output path before sourcing its script:

```{r reproduce, eval=FALSE}
Sys.setenv(GRIP_HMP_RESULTS_OUTPUT='fresh-hmp-results.rds')
source(system.file('scripts','precompute-hmp-results.R',package='grip'))
```

That script reproduces its documented hop-based workflow; it does not rerun
the weighted recipe above. Use separate output files for each comparison.

The SGD and weighted-GRIP fits are stored in `weighted_layouts.rds`, with
settings, warnings, runtimes, source/data checksums and session information.
Reproduce them from the source checkout with
`Rscript inst/scripts/precompute-hmp-layout-selector.R`. This does not overwrite
the hop-based preset comparison.
