Latent-Component PCA#

qiime gglasso pca projects your samples onto the eigenvectors of the low-rank component L of a Sparse + Low-Rank solution, not onto the principal components of the feature table. The sparse component Θ answers “which taxa are directly linked?”; L absorbs the dense, global structure that no sparse graph can represent — environmental gradients, sequencing depth, batch. Use the visualizer to see that structure and ask what it corresponds to.

Prerequisites#

Important

1. The solution must come from --p-latent True. pca reads solution/lowrank_ out of the solution artifact, and that group only exists for a latent problem. An SGL solution from Single Graphical Lasso fails here with a lookup error on the solution’s internals rather than a message about missing latent variables.

2. --m-sample-metadata-file is effectively required. It is registered as an optional Metadata parameter, but the function body dereferences it unconditionally — the first thing it does with the metadata is filter it to numeric columns — so omitting it raises an AttributeError on NoneType. Pass it every time.

Troubleshooting lists both: they are the two ways a first pca call usually fails.

Running the visualizer#

The solution comes from the latent fit in Sparse + Low-Rank:

qiime gglasso pca \
    --i-table data/atacama-table-mclr.qza \
    --i-solution data/atacama-solution-slr.qza \
    --m-sample-metadata-file data/selected-atacama-sample-metadata.tsv \
    --p-n-components 2 \
    --p-color-by ph \
    --o-visualization data/slr-pca.qzv

Explanation:

  • --i-table: the transformed table — the same artifact you passed to calculate-covariance in Data Preparation. The projection is a matrix product between the table and the eigenvectors of L, so the features must be the same set, in the same order, as the ones behind the covariance matrix. Passing the raw counts, or a table filtered differently, produces either a shape error or a silently meaningless plot.

  • --i-solution: a latent solution, per the prerequisite above.

  • --m-sample-metadata-file: sample metadata, used both to colour the points and to populate the axis-selection dropdowns.

  • --p-n-components: how many principal components enter the pair-plot grid (default 3). The command above runs only if the fitted low-rank block has rank 3 or more.

  • --p-color-by: the metadata column used for the colour scale.

  • --o-visualization: the .qzv, viewable with qiime tools view or at QIIME 2 View.

Note

No QIIME 2 2026.7 environment exists yet, so nothing has been re-run; the achieved rank, the variance shares on the axis labels and the appearance of the tabs are all pending verification against QIIME 2 2026.7. Read the rank off your own solution before fixing --p-n-components.

--p-n-components must not exceed the achieved rank#

The constraint is n_components <= rank(L) — asking for exactly as many components as the achieved rank is legitimate. pca validates it up front and raises

n_components (N) exceeds the rank of the low-rank component (R).
Pass --p-n-components R or lower.

The pair-plot carries the same check as a defensive assertion for direct callers, worded n_components (N) is greater than the rank of the low-rank component (R).

With the default of 3 you need a low-rank block of rank 3 or more. The rank is set indirectly by μ₁, and a larger μ₁ gives a smaller rank. If you tuned μ₁ for a compact, interpretable latent block you may well end up with rank 2, at which point the largest admissible value is --p-n-components 2 — enough for exactly one pair in the grid. Rank 1 is unusable outright: the single-plot tab defaults to PC1 against PC2 and needs at least two components to exist.

You cannot set the rank directly. --p-rank raises NotImplementedError on every released GGLasso; see Troubleshooting and, for the practical μ₁ scouting procedure, Choosing the Latent Rank.

To read the achieved rank, open the solution with summarize and look at the rank column of the statistics tab. That column comes from the model-selection path, so it is present only if the solution was fitted over a grid rather than as a single fit — see Regularization Paths & Model Selection.

Important

Do not size --p-n-components exactly to the number you read off that tab. Two things stand between it and the components you get. First, the tab prints one rank per grid point, so match the row to the selected λ₁/μ₁ from the best-parameter table yourself; that table reports the chosen hyperparameters, not the rank. Second, the limit pca enforces is np.linalg.matrix_rank recomputed on the stored L, whose default tolerance is far finer than the hard 1e-9 eigenvalue cut the projection itself applies — so matrix_rank can count eigenvalues that the projection then discards, and the guard can pass while fewer than n_components components exist. Leave yourself a margin below the reported rank rather than sizing to it exactly.

--p-color-by sees numeric columns only#

Before anything is plotted, the metadata is filtered to numeric columns. A categorical column — a yes/no vegetation flag, say, as carried by tier 2’s sample-metadata.tsv — is dropped, and naming it in --p-color-by fails with a lookup error on a column that is no longer there. The same filter governs the axis dropdowns, so categorical variables cannot be plotted against a component either. To see a grouping variable, encode it numerically in the metadata file first. The tier-1 file used above, selected-atacama-sample-metadata.tsv, holds four numeric columns and no categorical one, so on this data the filter is a no-op and nothing is dropped.

The filtered metadata is then re-indexed onto the sample IDs of the table. Any sample ID present in the table but absent from the metadata file, or spelled differently in the two, becomes a missing value rather than an error. Missing values in the colouring column are load-bearing: the pair-plot drops those samples before projecting, so it can show fewer points than the single plot, and the single plot derives its colour-scale bounds from the raw minimum and maximum of the column, which missing entries can poison. Check that your colouring column is complete for exactly the samples in the table.

Tip

pca builds a complete pair-plot grid for every numeric metadata column and then displays only the one named by --p-color-by. Wide metadata therefore costs real time for output you never see. Trim the metadata file to the columns you care about before running it on anything large.

The seq-depth fallback#

Omit --p-color-by and the visualizer computes a column itself: per-sample sequencing depth from the input table, rescaled to [0, 1] and added as seq-depth. If the leading component tracks seq-depth, the low-rank block is modelling a technical gradient, and any biological reading of it is unsafe.

Note

The orientation is not guessed. pca first lines the table up against the low-rank component — whichever axis has \(p\) entries becomes the feature axis, and the table is transposed if needed — and raises if neither axis matches. The helper then sums over features unconditionally, so the derived column is always indexed by sample and joins cleanly to the sample-indexed metadata at any \(p/N\) ratio, including the 13 ASVs of this Atacama table. Prefer --p-color-by whenever you have a variable in mind; the fallback is the default because it is the right first plot.

The two tabs#

Single plot. One large scatter of the samples, PC1 against PC2 by default, with a colour bar for the selected variable and hover tooltips carrying the coordinates. The two X-Axis / Y-Axis dropdowns to the right of the plot re-map the axes client-side to any other component or any numeric metadata column. Plotting PC1 directly against ph or elevation is the quickest way to see whether a latent axis is a measured gradient in disguise.

Axis labels carry the share of variance each component explains, computed from the eigenvalues of L — that is, the proportion of the latent structure, not of the total variance in the table. Only eigenvalues above a numerical tolerance are kept, so the number of components on offer is the numerical rank of L. The projection is whitened by those eigenvalues, so scores on different components are on comparable scales and a wide spread on a late component does not mean it dominates.

Pair-plot. A triangular grid of every pair among the first --p-n-components components, all coloured by --p-color-by, with the colour bar in the corner cell; the diagonal and one triangle stay empty. Panels are small and fixed-size, so use the grid to spot which pair separates your samples and go back to the single plot to look at that pair properly.

The two tabs use different colour palettes for the same variable — a blue ramp in the single plot, viridis in the pair-plot. Compare positions across tabs, not shades.

Reading latent components as putative drivers#

Do not ask what PC1 is; ask whether PC1 lines up with anything you measured.

If a component correlates visibly with a measured covariate, the low-rank block is standing in for that covariate. Stop treating it as latent: append the covariate to the table with transform-features --p-add-metadata True and re-fit, as in Adaptive Graphical Lasso, so the variable is modelled explicitly and the remaining sparse edges are conditional on it. Comparing the edge set before and after turns “there is confounding” into “these specific edges were environment-mediated” — the comparison set out in Interpretation.

If a component lines up with nothing you measured, you have a candidate unmeasured driver: an unrecorded gradient, a collection batch, an extraction run. That is a hypothesis to check against your study design, not a result.

Important

Do not over-read individual axes. The eigenvectors of L are determined only up to sign, so the direction of an axis carries no meaning, and components with close eigenvalues are only defined up to rotation within their shared subspace — which of two near-tied components a sample loads on is not interpretable. Interpret the subspace spanned by the leading components, and treat a component-by-component story as unsupported unless the eigenvalues are clearly separated.

A worked, higher-dimensional version of this analysis — several ranks, the same metadata — is in Latent PCA on the 300-ASV table. The full parameter list is in the q2-gglasso parameter reference.