Vol. 01 · No. 1 · Beta Edition

Multi-Sample Integration Tutorial

Merge multiple scRNA-seq samples into a single dataset, remove batch effects with Harmony, and produce an integrated UMAP where biology — not sequencing batch — drives clustering.

Intermediate·Multi-sample · Batch Correction

What you'll learn

  • Concatenate multiple H5AD files with Merge Data, preserving each cell's sample identity in obs["sample"].
  • Run batch-aware HVG selection (batch_key="sample") so feature selection isn't dominated by batch artifacts.
  • Apply Harmony correction, route Neighbors to use_rep="X_pca_harmony", and verify the integrated UMAP shows cells of both samples interleaved within each cluster.

Prerequisites

  • • Oreumics installed (install guide).
  • • Familiarity with the standard scRNA workflow — complete the PBMC tutorial first.
  • • Harmony tutorial (2-sample case, follows the shipped scRNA Harmony Integration template) recommended — this tutorial generalizes that pattern to N samples.
  • • Sample data: sampledata/scrna/pbmc3k_raw.h5ad (loaded twice, labelled per input in Merge Data).

When do you need multi-sample integration?

  • • Multiple donors / conditions: control vs. disease, timepoint A vs. B, patient cohort studies
  • • Multiple library preps: data produced on different days, different 10x chemistry versions, or different labs
  • • Different sequencing runs: samples sequenced across multiple flow cells or instruments

If your data comes from a single sample / single run, skip integration and use the standard PBMC tutorial.

Dataset

Sample files (pre-packaged)

sampledata/scrna/pbmc3k_raw.h5adsampledata/scrna/pbmc3k_raw.h5ad ← loaded a second time as "sample_B"
Both included in Oreumics. The same file is used twice to simulate a 2-sample experiment. In real workflows, each file would be a different donor/condition.

What this tutorial demonstrates

Two independent H5AD files are loaded, merged into a single AnnData with a sample batch column, preprocessed, and then batch-corrected with Harmony. The tutorial shows how to verify that batches are mixed correctly in the final UMAP.

Section 1

Load and Merge Samples

Load each sample independently, then use Merge Data to concatenate them into a single AnnData. Merge Data adds a sample column to obs so you can identify which cell came from which sample — this is the batch_key you will use later in Harmony. The label for each input is entered on the Merge Data node itself (one card per connected input, prefilled from the source node's name) — Load H5AD has no sample-name parameter.

Pipeline

Load H5AD (Sample A)
Load H5AD (Sample B)
→
Merge Data
Load H5AD — Sample AInput / Output

Load the first sample. Rename the node to "Sample A" (double-click its title) — Merge Data uses node names to prefill the per-input labels.

file_pathsampledata/scrna/pbmc3k_raw.h5ad

What you'll see

AnnData: 2,700 cells × 32,738 genes.

Load H5AD — Sample BInput / Output

Load the second sample the same way and name the node "Sample B". Both outputs connect to the single Merge Data node.

file_pathsampledata/scrna/pbmc3k_raw.h5ad

What you'll see

AnnData: 2,700 cells × 32,738 genes.

Merge DataInput / Output

Concatenate both AnnData objects into a single dataset. batch_key names the obs column that receives the per-input labels; the labels themselves are typed into the input cards (batch_labels_list). Cell barcodes are de-duplicated automatically, and the live pre-merge preview shows the resulting cell and gene counts before you run.

batch_keysamplecolumn name in the merged obs
batch_labels_listsample_A, sample_Bone card per input
joininnerkeep only genes present in ALL samples (default: outer)

What you'll see

5,400 cells × 32,738 genes. obs["sample"] identifies each cell's origin. Use join="outer" if samples have different gene sets and you want to keep all genes (missing values become 0).

Tip

Prefer join="inner" unless samples were aligned to different annotations. "outer" padding with zeros can inflate sparsity and distort downstream statistics.

Section 2

Quality Control

QC is applied to the merged dataset. Because both samples have already been concatenated, the thresholds apply globally. For real multi-sample experiments, inspect QC distributions per sample before filtering — set color_by='sample' on a label-mode Quality Control node to get per-sample violin plots.

Pipeline

Merge Data
→
Quality Control (label mode)
→
Quality Control (filter)
Quality Control (label mode)Preprocessing

Compute per-cell QC metrics across all merged cells without removing anything, and draw one violin per sample. Human mitochondrial prefix is MT- (uppercase); for mouse data use mt- (lowercase).

modelabel
mito_prefixMT-
ribo_prefixRPS,RPL
plot_typeviolin
metrics["n_genes_by_counts", "total_counts", "pct_counts_mt"]
color_bysampleone violin per sample

Tip

If one sample has a much lower n_genes median (< 500), it may be a low-quality library that warrants separate investigation or exclusion before merging. The QC Workspace shows MAD-based threshold recommendations for the pooled data.

Quality Control (filter)Preprocessing

Filter cells and genes using thresholds derived from the per-sample violin plots. These values work for typical human PBMC data.

modefilter
min_genes200
max_pct_mito20
filter_min_cellstrue
min_cells3
Section 3

Standard Preprocessing

Preprocessing is identical to a single-sample workflow. Run these nodes in strict order — normalize → log1p → HVG → scale → PCA. Harmony is inserted after PCA.

Pipeline

Quality Control
→
Normalize
→
Log1p
→
Highly Variable Genes
→
Scale
→
PCA
NormalizePreprocessing

Normalize each cell to the same total count. save_counts: true stores the raw integer counts in adata.layers["counts"] — needed if you want seurat_v3 HVG selection or a counts-based test later.

target_sum10000
save_countstrue
Log1pPreprocessing

Log-transform the normalized counts. This stabilizes variance and makes the data approximately normally distributed — a prerequisite for PCA.

basenullnatural log
Highly Variable GenesPreprocessing

Select 2,000 highly variable genes. For multi-sample data, set batch_key so HVGs are chosen within each sample and then combined — this stops genes that merely differ between batches from being selected. flavor "seurat" runs on the log-normalized matrix; "seurat_v3" is an alternative that expects raw counts, so pair it with layer: counts.

n_top_genes2000
flavorseurat
batch_keysampleper-sample HVG selection

Tip

Providing batch_key selects genes that are variable inside samples, not just because of batch differences. This is the recommended approach for multi-sample datasets.

ScalePreprocessing

Standardize each gene to zero mean and unit variance. With hvg_only: true (default) X keeps only the HVGs while the full log-normalized gene set is saved to adata.raw. After scaling adata.X contains z-scores — never use it directly for expression visualization (the plot nodes read adata.raw or layers["normalized"] via layer="auto").

max_value10
zero_centertrue
hvg_onlytrue
PCAAnalysis

Run PCA on scaled HVGs. At this stage the PCA embedding (X_pca) still contains batch effects — Harmony will correct it in the next section.

n_comps50
use_highly_variabletrue

Tip

Add a PCA Visualization node (plot_type: pca_scatter, color_by: sample) after PCA. If the first PCs separate samples instead of cell types, batch effects are strong — Harmony correction is essential.

Section 4

Harmony Batch Correction

Harmony operates on the PCA embedding and outputs a corrected version in obsm['X_pca_harmony']. The gene expression matrix (adata.X) is never modified — only the PCA coordinates are corrected. You must then pass use_rep='X_pca_harmony' to the Neighbors node, otherwise the batch correction has no effect downstream.

Critical: Harmony output key

Harmony outputs obsm['X_pca_harmony'] — it does NOT overwrite obsm['X_pca']. The most common mistake is forgetting to set use_rep='X_pca_harmony' in the Neighbors node. Without this, UMAP and clustering will use the uncorrected PCA and batch effects will remain.

Pipeline

PCA
→
Harmony
→
Neighbors
→
UMAP
→
Clustering
→
Embedding Plot
HarmonyAnalysis

Run Harmony integration on the PCA embedding. batch_key must match the obs column you assigned during Merge Data (e.g., "sample"; the node default is "batch"). Outputs obsm["X_pca_harmony"] — the batch-corrected PCA embedding.

batch_keysamplemust match obs column from Merge Data
theta2.0higher = more aggressive mixing
max_iter_harmony10

What you'll see

obsm["X_pca_harmony"] added. This embedding should show cells from both samples interleaved, while uncorrected X_pca still separates them.

NeighborsAnalysis

Build the kNN graph using the Harmony-corrected embedding. This is the most critical step — use_rep MUST be set to X_pca_harmony, not X_pca.

n_neighbors15
use_repX_pca_harmony← CRITICAL: use Harmony output
UMAPAnalysis

Compute UMAP from the Harmony-corrected neighbor graph. The resulting embedding reflects biology (cell types), not batch of origin.

min_dist0.3
spread1.0
ClusteringAnalysis

Run Leiden clustering on the Harmony-corrected neighbor graph.

methodleiden
resolution0.8
Embedding PlotVisualization

UMAP colored by cluster. Add a second Embedding Plot with color_by: sample to verify that batches are well-mixed within clusters — this is the integration quality check. (Cluster Visualization has no "umap" plot_type; it draws composition/proportions bars — its plot_type: proportions with groupby: sample gives a per-sample cluster breakdown.)

plot_typeumap
color_byleidenthen a second node with "sample"

What you'll see

A well-integrated UMAP: each cluster contains cells from both sample_A and sample_B. If one cluster is dominated by a single sample, try increasing theta in Harmony (up to 4) for stronger correction.

Tip

Good integration = clusters are not sample-specific. Because the demo loads the same file twice, mixing is trivially perfect — with real donors you should still expect some sample-specific clusters where biology differs.

Section 5

Downstream Analysis

After integration, downstream analysis proceeds identically to a single-sample workflow. DEG Analysis identifies cluster-specific genes. The sample column can be used for condition-aware analyses (e.g., comparing cluster composition between groups).

Pipeline

Clustering
→
DEG Analysis
→
Marker Visualization
→
Save H5AD
DEG AnalysisAnalysis

Rank differentially expressed genes per cluster (formerly "Find Markers"). Works the same as in the single-sample workflow; leave n_genes empty to rank all genes. The Wilcoxon test is non-parametric and works well for integrated data.

groupbyleiden
methodwilcoxon
n_genesnullall genes
Marker VisualizationVisualization

Dotplot of the top N marker genes per cluster. Use this to annotate cell types and then use Edit Clusters to rename clusters.

plot_typerank_genes_groups_dotplot
n_genes5
Save H5ADInput / Output

Save the fully processed, integrated AnnData. The saved file contains the Harmony embedding, UMAP coordinates, cluster labels, and DEG results — ready for downstream comparative analyses.

output_pathresults/integrated_pbmc.h5ad
compressiongzip

Integration Quality Checklist

Run Embedding Plot with color_by='sample' and check:

  • ✓ Batch mixing: Each UMAP cluster contains cells from multiple samples — no cluster is dominated by a single batch
  • ✓ Cell type preservation: Known cell type markers still show expected patterns (CD3D for T cells, LYZ for monocytes)
  • ✓ Cluster coherence: Clusters visible in the Harmony-corrected UMAP are biologically interpretable, not random mixtures

If integration quality is poor:

  • • Increase theta in Harmony (2 → 3 → 4) for more aggressive mixing
  • • Increase max_iter_harmony to 20 if convergence is slow
  • • Re-run Highly Variable Genes with batch_key='sample' (and, if you saved counts, flavor='seurat_v3' + layer='counts') for better feature selection
  • • Check if samples have very different total cell counts — extreme size imbalance can reduce integration quality

Common Pitfalls

Forgetting use_rep in Neighbors

The #1 mistake: running Harmony then leaving Neighbors at the default use_rep="X_pca". The batch correction only takes effect if Neighbors uses "X_pca_harmony".

Correcting when you should not

If "batch" differences actually reflect biology (e.g., comparing disease vs. control), over-correcting with high theta removes the signal you want to detect. Use lower theta or compare with uncorrected results.

Merging before per-sample QC

For real experiments, run a label-mode Quality Control node on each sample separately before merging. A single failed library can contaminate the merged dataset.

Using join="outer" without checking gene overlap

Outer join pads missing genes with zeros. For samples aligned to different genomes (e.g., hg38 vs mm10 in xenograft experiments), use inner join or pre-filter to the shared gene set.

Going Further

  • Use the Harmony + Doublet tutorial for an explicit 2-batch walk-through with a doublet-screening front-end.
  • Run cluster-level differential expression between samples (condition, treatment) using DEG Analysis with groupby="sample", or restrict the test to chosen clusters with its groups parameter.
  • Map cell-type labels from a reference dataset onto your integrated AnnData with the Cell Mapper node (the Reference Label Transfer template), or label cells directly with CellTypist Annotation — both bypass manual cluster-by-marker annotation.

Glossary

batch_key
An obs column that labels each cell's batch / sample / donor of origin. Set by Merge Data; consumed by Highly Variable Genes, Harmony, and condition-aware DEG.
join (inner vs. outer)
Merge Data's gene-set behavior. inner = keep only genes present in all samples (recommended). outer = keep all genes, padding missing values with 0 (the node default).
layers["counts"]
The raw integer counts that Normalize keeps aside when save_counts is on. seurat_v3 HVG selection and counts-based tests read from here; adata.raw (set by Scale) holds the log-normalized full gene set instead.
obsm["X_pca_harmony"]
Harmony's output — the batch-corrected PCA embedding. Pass to Neighbors via use_rep, otherwise correction is silently lost.
Integration quality
A subjective check — render the UMAP twice, once colored by leiden (clusters look biological?) and once by sample (cells from each batch interleaved within each cluster?).