Choose a matrix if you want to fit a hierarchy, an assignment table if you want to inspect a saved grouping, and the four-component Valencia subset if you want to explore coordinate charts. The package supplies five datasets and small examples can be constructed directly in R; it has no synthetic-data generation API. The function guide explains how each stage fits together.
Tables scroll horizontally on narrow screens. Focus a table and use the arrow keys, or swipe within it, to read every column without breaking function or dataset names.
Every object below is loaded with
data(object_name, package = "linf") and has its own help
page, for example help("agp_gut", package = "linf").
| Dataset | Unit, orientation and dimensions | Identifiers and main fields | Suitable workflow |
|---|---|---|---|
agp_gut |
766 gut samples by 314 taxa; integer read-count matrix. | counts, meta, taxa,
source; row names join to meta$Run (SRA
accessions). |
Count filtering and fitting. |
valencia2k |
2,000 vaginal samples by 178 taxa; unit-sum relative abundances. | rel, cst, reads,
taxa, source; local row IDs join to
cst$sample_id; cst$source_row joins to the
pinned source. |
Align metadata, then follow the vaginal tutorial. |
valencia13k_dcst_depth2_merged |
12,881 source samples; assignment table with six columns, not an abundance matrix. | assignments, summaries,
feature_labels, params, source;
sample_id and source_row. |
Inspect saved absorb-policy depth-1/2 assignments and sizes. |
valencia13k_dcst_depth3_merged |
Same 12,881 source samples; assignment table with seven columns. | Same fields as depth 2, plus dcst_depth3 and a depth-3
summary. |
Inspect the saved deeper grouping and compare depths. |
valencia_linf_hypercube_1k |
1,000 vaginal samples by four selected taxa; unit-sum matrix. | rel4, meta, component_map,
source; local sample_id, source-row index and
selected mass. |
Compute a static chart; coordinates are not precomputed. |
The two merged objects are ordinary lists of assignments and summary
tables. They lack the complete linf.csts object and input
matrix required by refine.linf.csts(),
dcst.view(), linf.landmarks() and
transfer.dcsts(). Do not change their class to make them
look like fresh fits.
data(agp_gut, package = "linf")
data(valencia2k, package = "linf")
data(valencia13k_dcst_depth2_merged, package = "linf")
data(valencia13k_dcst_depth3_merged, package = "linf")
data(valencia_linf_hypercube_1k, package = "linf")
observed <- rbind(
gut_counts = dim(agp_gut$counts),
vaginal_rel = dim(valencia2k$rel),
merged_depth2 = dim(valencia13k_dcst_depth2_merged$assignments),
merged_depth3 = dim(valencia13k_dcst_depth3_merged$assignments),
four_component_rel = dim(valencia_linf_hypercube_1k$rel4)
)
colnames(observed) <- c("Rows", "Columns")
stopifnot(identical(unname(observed),
matrix(c(766L, 2000L, 12881L, 12881L, 1000L,
314L, 178L, 6L, 7L, 4L), ncol = 2)))
knitr::kable(observed, caption = "Dimensions read from the bundled objects")| Rows | Columns | |
|---|---|---|
| gut_counts | 766 | 314 |
| vaginal_rel | 2000 | 178 |
| merged_depth2 | 12881 | 6 |
| merged_depth3 | 12881 | 7 |
| four_component_rel | 1000 | 4 |
agp_gut comes from American Gut Project public 16S V4
records under PRJEB11419,
processed to SILVA taxonomic counts through PRIME. The source
preparation first selected up to 5,000 samples with at least 1,000
reads. The 766-sample bundle includes all samples assigned to four
selected uncommon demonstration dCSTs (Prevotella_7, Pasteurellaceae,
Akkermansia and Staphylococcus), excludes Eukaryota/Unassigned depth-1
labels, and fills remaining slots from the eligible background using
Python’s seeded random sampling with seed 42.
The stored dcst_depth1/dcst_depth2 metadata
were derived in the source analysis; refitting on this selected subset
need not reproduce them. Phenotype fields were joined
after membership was fixed. Selection differs by dCST,
so this is not a probability sample for population inference.
Self-reported phenotypes are available for alignment demonstrations, not
general prevalence, association, causal or clinical claims. They are not
independent validation labels. Counts retain the limitations of 16S
taxonomic assignment and the documented caution about
Escherichia-Shigella in V4 data.
The four Valencia-derived objects use the filtered training source
for the VALENCIA
classifier described by France et
al. (2020). The prepared source has 12,881 samples and 178 taxa.
valencia2k was sampled with R seed 42 within the 13
supplied sub-CST groups, approximately preserving their proportions with
rounding and a minimum of five per stratum.
valencia2k$reads contains post-taxonomic-filter read
totals. Multiplying rel by reads gives
count-like reconstructions; rounding them does not
recover or certify original observed integer counts. Use
rel directly for normalization and rank-based fitting. The
upstream filtering is described in the existing vaginal tutorial; the subset-building
script takes that prepared matrix as input and does not repeat its
filtering.
The supplied Val_CST and Val_subCST labels
belong to the Valencia training source. A comparison made on these
bundled rows overlaps that source, even though dCST fitting does not use
its class labels. Such agreement is descriptive, not held-out validation
of a classifier or evidence of clinical performance.
The merged assignment assets were built on the full prepared source
with n0 = 50, low.freq.policy = "absorb" and
refinement.factor = 2, with one or two refinements. Their
summaries contain depth, dcst_label,
n, prop and path_length.
Proportions refer to this source sample set. Path lengths may be shorter
than the stored depth for terminal lineages; treat saved labels as
labels, not as a source of stable feature IDs.
valencia_linf_hypercube_1k selects Lactobacillus iners
(Li), Lactobacillus crispatus (Lc),
Gardnerella vaginalis (Gv) and BVAB1 (Bv).
Rows with zero total mass in those four taxa were removed, and retained
rows were renormalized to sum to one over those four
features. R seed 20261604 was used for a 1,000-row sample
stratified by the dominant selected component.
meta$selected_mass records how much of the original full
profile these four taxa represented. A large fraction within
rel4 can still correspond to little of the full community.
component_map connects abbreviations to source taxa;
neither the subset nor its charts replace the full 178-feature
profiles.
All objects include a provenance string. The installed provenance file records source preparation and upstream terms (which are separate from the code’s MIT license):
provenance <- system.file("DATA_PROVENANCE.md", package = "linf", mustWork = TRUE)
cat(readLines(provenance, warn = FALSE)[1:12], sep = "\n")
#> # Bundled data provenance and upstream terms
#>
#> The package code is distributed under the package's MIT license. The bundled
#> microbiome data are derived from the upstream resources described below. The
#> package license does not replace or narrow applicable upstream attribution
#> terms.
#>
#> ## VALENCIA-derived objects
#>
#> The `valencia2k`, `valencia_linf_hypercube_1k`,
#> `valencia13k_dcst_depth2_merged`, and `valencia13k_dcst_depth3_merged` objects
#> are derived from the VALENCIA training data:Read the full installed record at the console with
cat(readLines(provenance), sep = "\n"). This works offline.
Repository readers can open data
provenance, the input
manifest, and the reproduction
recipe.
Sample names are keys within an object, not universal cross-dataset
IDs. For valencia2k, IDs such as s1 were
reassigned after sampling. Its verified cst$source_row now
preserves the sampled row in the pinned prepared source. The
four-component and merged objects share that source_row
numbering. Join on this explicit key after checking provenance, never by
row position or an apparent numeric suffix in the different local
sample-ID schemes.
X <- agp_gut$counts
stopifnot(!anyDuplicated(agp_gut$meta$Run),
!anyDuplicated(agp_gut$taxa))
sample.order <- match(rownames(X), agp_gut$meta$Run)
feature.order <- match(colnames(X), agp_gut$taxa)
stopifnot(!anyNA(sample.order), !anyNA(feature.order))
meta <- agp_gut$meta[sample.order, , drop = FALSE]
features <- data.frame(
id = paste0("asv_", seq_len(ncol(X))),
taxonomy = agp_gut$taxa[feature.order]
)
stopifnot(identical(rownames(X), meta$Run))
# After filtering, indices refer to the supplied X, in its original order.
filtered <- filter.asv(X, min.lib = 1000, prev.prop = 0.05,
min.count = 2, verbose = FALSE)
meta.filtered <- meta[filtered$kept.sample.idx, , drop = FALSE]
features.filtered <- features[filtered$kept.feature.idx, , drop = FALSE]
stopifnot(identical(rownames(filtered$counts), meta.filtered$Run),
nrow(features.filtered) == ncol(filtered$counts))The stable IDs here describe the original column order and are
subsetted with the features; they are not regenerated after filtering.
Pass features.filtered$id and display labels made from its
taxonomy in that same order when fitting. Keep the mapping with the fit.
Landmarks preserve complete stable IDs, including taxonomy strings
containing __; see landmark
interpretation.
The following join uses the explicit shared source-row key:
merged <- valencia13k_dcst_depth3_merged
chart.meta <- valencia_linf_hypercube_1k$meta
stopifnot(!anyDuplicated(merged$assignments$source_row))
join <- match(chart.meta$source_row, merged$assignments$source_row)
stopifnot(!anyNA(join))
chart.depth3 <- merged$assignments$dcst_depth3[join]
stopifnot(identical(as.character(chart.meta$Val_CST),
as.character(merged$assignments$Val_CST[join])))
length(chart.depth3)
#> [1] 1000
subset.join <- match(valencia2k$cst$source_row, merged$assignments$source_row)
stopifnot(!anyNA(subset.join),
identical(as.character(valencia2k$cst$Val_CST),
as.character(merged$assignments$Val_CST[subset.join])))This attaches in-source saved labels; it is not a new reference/query experiment.
This deterministic matrix needs no random seed. It includes two supported dominant features, a low-support feature, a positive tie, an exact-zero row and a small row left unchanged by a positive tolerance. IDs differ from labels.
toy <- rbind(
a1 = c(10, 3, 1), a2 = c(9, 2, 1),
b1 = c(2, 10, 1), b2 = c(3, 9, 1),
low_support = c(1, 2, 10), tie = c(4, 4, 0),
zero = c(0, 0, 0), small = c(0.01, 0.005, 0)
)
colnames(toy) <- c("asv_1", "asv_2", "asv_3")
display <- c("Taxon A", "Taxon B", "Taxon C")
M <- normalize.linf(toy, tol = 0.02)
d <- linf.dominant.features(M, feature.labels = display)
fit <- linf.csts(M, feature.labels = display, n0 = 2)
edge.table <- data.frame(
sample = rownames(M), maximum = apply(M, 1, max),
dominant_ID = d$id, pure = fit$lineage.label.pure,
absorb = fit$lineage.label.absorb
)
knitr::kable(edge.table, row.names = FALSE)| sample | maximum | dominant_ID | pure | absorb |
|---|---|---|---|---|
| a1 | 1.00 | asv_1 | Taxon A | Taxon A |
| a2 | 1.00 | asv_1 | Taxon A | Taxon A |
| b1 | 1.00 | asv_2 | Taxon B | Taxon B |
| b2 | 1.00 | asv_2 | Taxon B | Taxon B |
| low_support | 1.00 | asv_3 | RARE_DOMINANT | Taxon B |
| tie | 1.00 | asv_1 | Taxon A | Taxon A |
| zero | 0.00 | NA | RARE_DOMINANT | Taxon A |
| small | 0.01 | asv_1 | Taxon A | Taxon A |
stopifnot(is.na(d$id[7]), d$id[6] == "asv_1", d$id[8] == "asv_1",
identical(unname(M["small", ]), unname(toy["small", ])))The tied row chooses the first column. The small row retains maximum 0.01 and still has a dominant feature. The zero row has no dominant feature; pure fitting puts it in the rare bucket and absorb fitting uses the most-supported retained state. The low-support row is absorbed into Taxon B, its largest retained feature. Neither absorption is evidence that the assigned feature was the original maximum.
For random ties, reset the seed before each call you want to reproduce:
Use a small seeded sample of 160 Valencia rows. The first 120 sampled rows form the reference; the other 40 are kept out of fitting and refinement. This split demonstrates frozen transfer mechanics within one source dataset, not external validation, and no outcome or CST label is used to fit the reference.
set.seed(20260914)
rows <- sample(seq_len(nrow(valencia2k$rel)), 160)
reference.rows <- rows[1:120]
query.rows <- rows[121:160]
stopifnot(length(intersect(reference.rows, query.rows)) == 0L)
reference <- valencia2k$rel[reference.rows, , drop = FALSE]
query <- valencia2k$rel[query.rows, , drop = FALSE]
reference.M <- normalize.linf(reference)
reference.fit <- linf.csts(reference.M, n0 = 5,
low.freq.policy = "absorb")
reference.fit <- refine.linf.csts(
reference.M, reference.fit, n0 = 3, refinement.factor = 2,
low.freq.policy = "absorb", verbose = FALSE
)
# Deliberately reverse query columns. Matching uses the unchanged feature IDs.
query <- query[, rev(seq_len(ncol(query))), drop = FALSE]
stopifnot(setequal(colnames(query), reference.fit$feature.ids))
transferred <- transfer.dcsts(query, reference.fit, match.by = "feature.ids")
knitr::kable(data.frame(
depth = colnames(transferred$assignment),
assigned = colSums(!is.na(transferred$assignment)),
unassigned = colSums(is.na(transferred$assignment))
), row.names = FALSE)| depth | assigned | unassigned |
|---|---|---|
| depth1 | 40 | 0 |
| depth2 | 39 | 1 |
No query filtering rule or hierarchy is learned here. Missing
reference columns would be filled with zero; extra query columns would
be ignored. Counts and positive row-scaled abundances give the same
ranking for this transfer. NA means the walk found no
positive realized candidate at that depth; it does not create a new
dCST. A partial depth-1 assignment can coexist with a depth-2
NA.
unmatched <- matrix(5, nrow = 1, ncol = 1,
dimnames = list("unmatched_query", "not_in_reference"))
no.assignment <- transfer.dcsts(unmatched, reference.fit)$assignment
stopifnot(all(is.na(no.assignment)))
no.assignment
#> depth1 depth2
#> unmatched_query NA NA
#> NA
#> NAFor a longer count-based workflow use the gut demonstration; for descriptive comparisons to source CST labels use the vaginal workflow.
The returned chart has three coordinates. This plot shows two of them for all 1,000 bundled samples; color identifies which of the four selected components has the largest abundance. It is a projection of a representation, with no learned classifier or biological-separation test.
four <- valencia_linf_hypercube_1k
embedding <- linf.hypercube.embedding(four$rel4, reference = "Li")
stopifnot(identical(dim(embedding), c(1000L, 3L)),
all(is.finite(embedding)))
colors <- c(Li = "#0072B2", Lc = "#D55E00", Gv = "#009E73", Bv = "#CC79A7")
plot(embedding[, 1], embedding[, 2],
col = colors[as.character(four$meta$dominant_component)],
pch = 16, cex = 0.5, xlim = c(0, 1), ylim = c(0, 1),
xlab = "Lc coordinate (reference Li)",
ylab = "Gv coordinate (reference Li)")
legend("topright", legend = names(colors), col = colors, pch = 16,
title = "Dominant component", bty = "n", cex = 0.8)Two coordinates of the Li-reference chart. Colors describe dominance within the selected four taxa; overlapping points and the omitted third coordinate limit what this projection shows.
Check summary(four$meta$selected_mass) before
interpreting the four-taxon composition. The optional interactive
embedding article adds three-dimensional views and is website-only.
The four installed vignettes are listed by
browseVignettes("linf"); their normal builds need no
network downloads, interactive device or external dataset.