multi-omics-integration/mixomics-analysis/SKILL.md
Builds supervised and unsupervised multivariate integration across bulk omics blocks with mixOmics - sPLS for sparse pairwise correlation, DIABLO (block.splsda) for a multi-block discriminant signature, rCCA for regularized canonical correlation, and MINT for multi-study integration. Covers why these projection methods maximize covariance or correlation and not truth, why DIABLO's design matrix is the central correlation-versus-discrimination decision, why cross-validation must wrap keepX selection or the reported error is leaked, why balanced error rate is required under class imbalance, and why DIABLO needs matched samples while MINT handles multiple cohorts. Use when finding a cross-omic discriminant signature for a known outcome, selecting correlated features between two omics, tuning keepX, or integrating one omic across studies. For unsupervised factors see mofa-integration; for the method decision see integration-design; for cross-validation theory see machine-learning/model-validation.
npx skillsauth add GPTomics/bioSkills bio-multi-omics-mixomics-analysisInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference examples tested with: mixOmics 6.26+.
Before using code patterns, verify installed versions match. If versions differ:
packageVersion('mixOmics') then ?function_name to verify parametersIf code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.
The DIABLO model is block.splsda - there is no function literally named diablo. mixOmics input is samples-by-features (the opposite of MOFA2's features-by-samples), and scale=TRUE is the default, so feed appropriately transformed but not pre-standardized matrices.
"Find a cross-omic signature that discriminates my groups" -> Project the blocks onto sparse latent components that maximize an association criterion - because these methods maximize covariance, not truth, so a signature that discriminates the training cohort is guaranteed and only out-of-sample replication makes it real.
block.splsda() (DIABLO, supervised), spls() (pairwise), mint.splsda() (multi-study)Scope: supervised multi-block discriminant integration (DIABLO), sparse pairwise correlation (sPLS), regularized CCA (rCCA), and multi-study integration (MINT). Unsupervised factor models -> mofa-integration. The method-selection decision -> integration-design. Generic cross-validation / leakage theory -> machine-learning/model-validation. Per-omic scaling/batch -> data-harmonization. Enrichment of selected features -> pathway-analysis/go-enrichment.
These are projection methods: they find linear combinations of features that optimize an association criterion (covariance for PLS/DIABLO, correlation for CCA), and DIABLO additionally optimizes whatever the design matrix tells it to. With n much smaller than p the methods can fit almost anything, so the output is never "the cross-omic drivers of the disease" - it is the features that best satisfied the chosen criterion on the available samples. Three rules follow:
perf() cross-validation error on the same data is leakage (up to ~0.15 AUC inflation). mixOmics selects inside folds when tuning, which is correct for choosing keepX - but the minimized CV error it returns is still optimistic. The honest number comes from an external test set never touched during tuning, or a fully nested CV.| Method (mixOmics fn) | Citation | Optimizes | Supervision |
|----------------------|----------|-----------|-------------|
| sPLS (spls) | Le Cao 2008 Stat Appl Genet Mol Biol 7:Article 35 | covariance between TWO blocks, sparse | unsupervised pairwise |
| rCCA (rcc) | Gonzalez 2008 J Stat Softw 23(12) | correlation between two blocks, ridge/shrinkage regularized | unsupervised pairwise |
| DIABLO (block.splsda) | Singh 2019 Bioinformatics 35:3055 | covariance across MANY blocks + discrimination, sparse | supervised, multi-block |
| MINT (mint.splsda) | Rohart 2017 BMC Bioinformatics 18:128 | one omic across studies, study as fixed effect | supervised, horizontal |
| sPLS-DA (splsda) | Le Cao 2011 BMC Bioinformatics 12:253 | discrimination in ONE block, sparse | supervised, single-block |
| sPCA (spca) | Shen 2008 J Multivar Anal 99:1015 | variance in one block, sparse | unsupervised, single-block |
| Scenario | Recommended | Why |
|----------|-------------|-----|
| Two or more omics, matched samples, a categorical outcome | DIABLO (block.splsda) | supervised multi-block; design tunes correlation vs discrimination |
| Two omics, no outcome, want a sparse correlated feature list | sPLS canonical (spls, mode='canonical') | covariance, symmetric, feature selection |
| Two omics, no outcome, want the global correlation landscape | rCCA (rcc, shrinkage) | correlation criterion, regularized for p>n |
| One omic predicts another (directional) | sPLS regression (spls, mode='regression') | asymmetric, Y as response |
| SAME omic across multiple cohorts, reproducible signature | MINT (mint.splsda) | horizontal; study as a fixed effect |
| No outcome, want variance-attributed factors, missing blocks OK | -> mofa-integration | Bayesian factor model, not a projection |
| Need an honest performance number | external test set or nested CV | the tuned CV error is optimistic |
| Which method at all / paired vs horizontal | -> integration-design | the correspondence and supervision decision |
Goal: Guarantee the row-by-row sample matching DIABLO/sPLS/rCCA require, so the model correlates feature vectors of the same individuals.
Approach: Intersect to common samples and verify identical rowname order across every block; for combining one omic across cohorts, that is horizontal integration and needs MINT, not DIABLO.
library(mixOmics)
common <- Reduce(intersect, list(rownames(X_rna), rownames(X_prot))) # samples x features
X_blocks <- list(RNA=X_rna[common, ], Protein=X_prot[common, ])
Y <- factor(pheno[common, 'Condition'])
stopifnot(identical(rownames(X_blocks$RNA), rownames(X_blocks$Protein))) # matched rownames or the result is garbage
Goal: Select a sparse set of features that covary between two omics.
Approach: Choose mode deliberately - 'canonical' for two omics on equal footing (the CCA-like symmetric framing), 'regression' (the default) only when one block is a designated response. Tune component count, then fit with keepX/keepY feature selection.
spls_res <- spls(X_blocks$RNA, X_blocks$Protein, ncomp=3, mode='canonical', # symmetric; default 'regression' treats Protein as a response of RNA
keepX=c(50, 50, 50), keepY=c(30, 30, 30))
plotVar(spls_res, comp=c(1, 2))
Goal: Find a cross-omic feature signature that discriminates a known outcome, with the correlation-versus-discrimination trade-off chosen and reported.
Approach: Set the design matrix from the goal (high off-diagonal for coherent networks, low for prediction), tune the component count on a non-sparse model, tune keepX inside cross-validation folds using balanced error rate, fit, then report performance on an external set.
design <- matrix(0.5, nrow=length(X_blocks), ncol=length(X_blocks),
dimnames=list(names(X_blocks), names(X_blocks))) # 0.5-1 favors cross-block correlation; <0.5 favors prediction - choose from the goal
diag(design) <- 0
ncomp_fit <- perf(block.plsda(X_blocks, Y, ncomp=5, design=design), # tune ncomp on a NON-sparse model first
validation='Mfold', folds=10, nrepeat=10) # nrepeat>=10; a single split is noise
tune <- tune.block.splsda(X_blocks, Y, ncomp=2, design=design,
test.keepX=list(RNA=c(10, 25, 50), Protein=c(10, 25, 50)),
validation='Mfold', folds=10, nrepeat=10,
measure='BER', BPPARAM=BiocParallel::MulticoreParam(workers=4)) # BER, not overall error, for imbalanced classes; cpus= is defunct, use BPPARAM
diablo <- block.splsda(X_blocks, Y, ncomp=2, keepX=tune$choice.keepX, design=design)
The features chosen here discriminate the training cohort by construction. For an honest accuracy, hold out an external test set never used in tuning and report predict() / auroc() on it; the perf() error on the tuning data is optimistic because keepX was chosen to minimize it.
Goal: Extract the signature as candidates and visualize cross-block structure without overclaiming.
Approach: Pull selected variables per block and component, inspect inter-block correlations, and frame the list as cohort-specific candidates requiring replication.
sel_rna <- selectVar(diablo, block='RNA', comp=1)$RNA$name # candidate features, not validated biomarkers
circosPlot(diablo, cutoff=0.7) # inter-block correlations of the selected features
auc <- auroc(diablo, roc.block='RNA', roc.comp=1)
Goal: Build a signature for ONE omic that replicates across cohorts by modeling study as a known effect.
Approach: Pass a study factor so the model accounts for study-specific variation; this is horizontal integration (same features, different cohorts), the opposite of DIABLO's vertical matched-sample design.
mint_res <- mint.splsda(X=X_rna, Y=Y, study=study, ncomp=3, keepX=c(50, 50, 50)) # study = fixed effect; one omic, many cohorts
plotIndiv(mint_res, study='global', legend=TRUE)
Trigger: tuning keepX on all samples, then reporting perf() CV error on all samples. Mechanism: the features were chosen with knowledge of every sample, so no fold is truly held out. Symptom: an excellent CV error that collapses in a new cohort. Fix: external test set or nested CV; the number used to pick keepX is not an estimate of performance.
Trigger: using 0.1 (or any value) without choosing it. Mechanism: the off-diagonal trades discrimination against cross-block correlation. Symptom: a result marketed as "integrated" while the design told the model to ignore most cross-block correlation. Fix: choose the design from the goal, justify it, and ideally show the result under a high and a low weight.
Trigger: running plain CCA on omics. Mechanism: CCA divides out variances and needs to invert a singular covariance, so it reports correlation 1.0 by overfitting. Symptom: perfect, meaningless canonical correlations. Fix: use rcc with ridge or shrinkage regularization, or sPLS canonical.
Trigger: partially overlapping or mis-ordered samples across blocks, or DIABLO on two cohorts of one omic. Mechanism: DIABLO/sPLS relate samples row-by-row. Symptom: garbage signatures from correlating different individuals. Fix: intersect and verify identical rowname order; use MINT for one omic across cohorts.
Trigger: tuning on overall classification error with imbalanced classes. Mechanism: the majority class dominates the metric. Symptom: high accuracy while the minority class is mis-predicted. Fix: measure='BER' and report per-class error.
Trigger: calling the selected features mechanistic drivers. Mechanism: they discriminate the training cohort by construction. Symptom: a biomarker claim that fails to replicate. Fix: frame as cohort candidates; require external/cross-study replication.
| Threshold | Source | Rationale |
|-----------|--------|-----------|
| Design off-diagonal: ~1 for coherence, <0.5 for prediction | Singh 2019 Bioinformatics 35:3055 | weights trade cross-block correlation against discrimination; 0.1 is tutorial convention only |
| nrepeat >= 10 (50 for a headline number) | mixOmics docs | a single M-fold split is high-variance; nrepeat=1 is illustration only |
| folds 5-10 in M-fold CV | mixOmics docs | balances bias and variance of the CV estimate at small n |
| measure='BER' for imbalanced classes | mixOmics docs | overall error is dominated by the majority class |
| ncomp 1-3, set by perf() elbow | Singh 2019 Bioinformatics 35:3055 | more components rarely help and risk overfit |
| External test set or nested CV for reported accuracy | machine-learning/model-validation | the tuned CV error is optimistically biased |
| Error / symptom | Cause | Solution |
|-----------------|-------|----------|
| could not find function "diablo" | DIABLO is block.splsda | call block.splsda, not diablo |
| Perfect canonical correlations | un-regularized CCA on p>n | use rcc ridge/shrinkage |
| Reported accuracy fails in a new cohort | CV scored on tuning data | external test set or nested CV |
| tune.block.splsda very slow | grid too large / not parallelized | shrink test.keepX, set BPPARAM (cpus= is defunct) |
| High accuracy, minority class missed | overall error under imbalance | measure='BER' |
| Nonsense signature | unmatched/mis-ordered samples | intersect and verify rowname order |
tools
End-to-end CLIP-seq pipeline from FASTQ to ENCODE-compliant binding sites, single-nucleotide crosslink maps, annotation, motifs, and (optionally) differential binding. Use when running the full Yeo lab eCLIP / iCLIP / iCLIP2 / iCLIP3 / irCLIP / PAR-CLIP analysis with SMInput control, protocol-specific UMI extraction, ENCODE STAR parameters, CLIPper or Skipper peak calling with stringent log2 FC and -log10 p thresholds, IDR rescue and self-consistency QC, and downstream motif registration with mCross or PEKA.
development
Detect, date, and contextualize whole-genome duplication (WGD / paleopolyploidy) events using wgd v2 (Chen et al 2024), KsRates (Sensalari 2022 substitution-rate-corrected Ks dating), DupGen_finder (Qiao 2019), MAPS (Li 2018 phylogenomic), POInT (Conant 2008 ordered-block), SLEDGe (2024 ML-based), Whale.jl (Bayesian DL+WGD), and synteny-anchored paranome construction. Use when identifying ancient polyploidy from Ks distributions and synteny block analysis, positioning WGD events relative to speciation, distinguishing tandem from segmental from WGD duplications, dating the 2R/3R vertebrate / fish / salmonid WGDs, building paranome and Ks-age mixture models, applying KsRates substitution-rate correction across lineages, or testing alternative biased-fractionation / dosage-balance models post-WGD.
tools
Build whole-genome alignments using Progressive Cactus (Armstrong 2020 reference-free clade-level WGA), Minigraph-Cactus (Hickey 2024 pangenome-aware), LASTZ chain/net (UCSC pipeline), MUMmer4 (Marçais 2018 pairwise), minimap2 -x asm5/10/20 (Li 2018 fast pairwise), AnchorWave (Song 2022 WGD-aware), and Mauve / progressiveMauve (bacterial). Operates the HAL toolkit (Hickey 2013) for downstream extraction including halSynteny, halLiftover, halBranchMutations, and hal2maf. Use when constructing multi-species alignments for comparative-annotation projection (TOGA), synteny detection, conservation analyses (phyloP / PhastCons), or pangenome graph construction; selecting between reference-free (Cactus) and reference-anchored (LASTZ chains/nets) approaches; tuning sensitivity for closely vs distantly related genomes; or producing HAL files for genome-wide downstream tools.
development
Detect syntenic blocks and structural rearrangements between genomes using MCScanX (Wang 2012), JCVI/MCScan (Tang 2008 Python), GENESPACE (Lovell 2022) for orthology-anchored riparian visualization, SyRI for structural variation, AnchorWave for sequence-level synteny, i-ADHoRe 3.0 for highly diverged species, SynNet for synteny networks, and ntSynt for multi-genome macrosynteny. Use when identifying collinear gene blocks across species, distinguishing macrosynteny from microsynteny, detecting inversions/translocations/duplications, anchoring orthology in WGD lineages, producing publication riparian plots, computing synteny block age via Ks (cross-references whole-genome-duplication), or running synteny-aware ortholog inference in polyploids.