Quality control for flow, spectral, and mass cytometry - time-based anomaly cleaning (flowAI, flowCut, PeacoQC, flowClean), margin/boundary event removal, signal-drift detection, dead-cell exclusion, CyTOF Gaussian/DNA/event-length checks, instrument calibration/standardization (MESF, CS&T, peak-2), and batch-level outlier flagging. Use when assessing acquisition quality, choosing a cleaning tool, ordering QC relative to compensation, deciding margin removal before density-based steps, or flagging problematic samples before clustering or differential analysis.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
bio-flow-cytometry-cytometry-qc
description
Quality control for flow, spectral, and mass cytometry - time-based anomaly cleaning (flowAI, flowCut, PeacoQC, flowClean), margin/boundary event removal, signal-drift detection, dead-cell exclusion, CyTOF Gaussian/DNA/event-length checks, instrument calibration/standardization (MESF, CS&T, peak-2), and batch-level outlier flagging. Use when assessing acquisition quality, choosing a cleaning tool, ordering QC relative to compensation, deciding margin removal before density-based steps, or flagging problematic samples before clustering or differential analysis.
Before using code patterns, verify installed versions match. If versions differ:
R: packageVersion('<pkg>') then ?function_name to verify parameters
Counterintuitive defaults to confirm: flowAI checks are FR/FS/FM (FM = dynamic range, not "flow"); PeacoQC MAD/IT_limit are LESS strict when HIGHER. Verify with ?flow_auto_qc and ?PeacoQC before tuning.
Cytometry QC
"Run quality control on my cytometry data" -> Detect and remove acquisition artifacts (flow-rate instability, signal drift, margin events, dead cells, CyTOF doublets) on the Time axis, then flag outlier samples.
R (flow/spectral): flowAI::flow_auto_qc(), PeacoQC::PeacoQC() (+ RemoveMargins())
R (mass): CATALYST::normCytof() beads + Gaussian/DNA/event-length gating
The Single Most Important Modern Insight -- The Time Parameter Is the Master QC Axis, and Order Matters
Nearly every acquisition artifact - clogs, bubbles, flow-rate surges, electronics warm-up, CyTOF sensitivity decay, oxide buildup - manifests as a CHANGE IN SIGNAL versus the Time channel. flowAI, flowCut, flowClean, and PeacoQC are all, at heart, Time-vs-signal anomaly detectors; a missing or mis-scaled $TIMESTEP silently degrades or breaks all of them. Just as important is the ORDER: compensation/unmixing -> transform -> margin removal -> time-based QC -> debris/doublet/dead-cell gating -> batch normalization. Margin (boundary) events piled at a detector min/max form spurious high-density ridges that fool density-based cleaning and density gates, so they must be stripped BEFORE any density step; and time-based QC on untransformed data misbehaves because the density structure the algorithms rely on lives on the transformed scale.
Cleaning-Tool Taxonomy
Tool
Citation
Mechanism
When to use / caveat
flowAI
Monaco 2016 Bioinformatics 32:2473
3 checks: flow rate (FR), signal acquisition (FS), dynamic range (FM)
classic; known AGGRESSIVE - can remove normal data
PeacoQC
Emmaneel 2022 Cytometry A 101:325
per-channel density peaks + MAD + isolation tree
only tool validated across flow + mass + spectral; QC engine of CytoPipeline
flowCut
Meskas 2023 Cytometry A 103:71
segments Time, removes low-density/deviant segments
less aggressive than flowAI; flags whole files
flowClean
Fletez-Brant 2016 Cytometry A 89:461
tracks subset frequency in centered-log-ratio space
floor ~30,000 events; writes a "GoodVsBad" parameter to gate on
Run flowAI (with the correct API)
Goal: Auto-clean a sample for flow-rate, signal-acquisition, and dynamic-range anomalies.
Approach:flow_auto_qc() returns a flowFrame of high-quality events when output=1; FM is the dynamic-range check; supply timeCh for concatenated/clock-reset files. flowAI is the time-based QC step - run it after compensation/transform/margin removal (per the ordering above), not on a raw uncompensated frame.
Goal: Remove boundary events, then clean unstable time/peak structure across all channels.
Approach:RemoveMargins() strips detector-min/max events; then PeacoQC() - remember higher MAD/IT_limit = LESS strict.
library(PeacoQC)
ff_nm <- RemoveMargins(ff, channels =c('FSC-A','SSC-A'))# do this BEFORE density QC
res <- PeacoQC(ff_nm, channels = marker_channels,
MAD =6, IT_limit =0.55,# defaults; higher = less strict (counterintuitive)
save_fcs =FALSE, plot =TRUE)
ff_clean <- res$FinalFF
Dead-Cell, Drift, and CyTOF Checks
Goal: Exclude dead cells, detect per-channel drift, and apply CyTOF-specific gates.
Approach: Viability dye threshold (bimodal); per-time-bin median slope for drift; for CyTOF use DNA intercalator + Gaussian/event-length; EQ-bead-median-vs-Time is the primary CyTOF drift readout (see bead-normalization).
expr <- exprs(ff)# dead cells take up more viability dye -> cut at the bimodal density VALLEY (data-driven), not a fixed quantile
dead_cut <- flowDensity::deGate(ff, channel ='Live_Dead')
live <- expr[,'Live_Dead']< dead_cut
# CyTOF single-cell gatesif('Event_length'%in% colnames(expr)){
keep <- expr[,'Event_length']>=10& expr[,'Event_length']<=75# confirm range per instrument}
dna <- grep('Ir191|Ir193', colnames(expr), value =TRUE)# intercalator-positive = nucleated
Calibration and Standardization (cross-study comparability)
A discovery analyst often skips this, but cross-experiment/cross-site MFI comparison is meaningless without it (Maecker & Trotter 2006 Cytometry A 69:1037):
MESF / MEF / ERF beads express intensity in molecules-of-equivalent-fluorochrome - comparable across instruments and time (NIST/ISAC standard; PE/Pacific Blue use ERF surrogates).
Quantibrite PE (defined PE molecules/bead, ~1:1 conjugation) converts MFI to antibodies-bound-per-cell / receptor density (bead values are LOT-dependent).
CS&T / 8-peak rainbow beads for daily QC (laser delay, area scaling, linearity).
Peak-2 / voltration: run a dim particle across PMT voltages, pick the CV-vs-voltage inflection = minimum voltage for optimal resolution. This is why MIFlowCyt mandates reporting voltages.
Batch-Level Outlier Flagging
Goal: Flag samples whose event count, flow stability, or marker medians deviate from the batch.
Approach: Per-file metrics + MAD-based bounds; track an anchor/reference sample if present.
Trigger: PeacoQC/flowClean before RemoveMargins. Mechanism: axis pile-ups are false high-density ridges. Symptom: real events removed near the boundary, or margins kept. Fix: remove margins first.
flowAI over-removal
Trigger: default flowAI on a low-rate or short acquisition. Mechanism: FR check flags normal slow segments. Symptom: large unexplained event loss. Fix: raise second_fractionFR; inspect the HTML report; consider flowCut/PeacoQC.
QC on untransformed/uncompensated data
Trigger: running QC on raw linear values. Mechanism: high-intensity tail dominates density. Symptom: misplaced anomaly calls. Fix: compensate + transform first.
Time axis missing/reset
Trigger: concatenated files, some sorters. Mechanism: no usable Time. Symptom: flow-rate check fails or is meaningless. Fix:timeCh= or reconstruct; otherwise skip time-based checks.
Quantitative Thresholds
Threshold
Source
Rationale
flowClean floor ~30,000 events
Fletez-Brant 2016 Cytometry A 89:461
below this the CLR frequency tracking under-detects
PeacoQC MAD=6, IT_limit=0.55
Emmaneel 2022 Cytometry A 101:325
defaults; HIGHER = less strict
dead cells > ~10-30%
community
sample-handling flag, not a hard cutoff - report, don't auto-exclude the sample
CyTOF retune ~ daily / per long run
instrument practice (flagged)
sensitivity decays from cone fouling/plasma drift
Common Errors
Error / symptom
Cause
Solution
flow_auto_qc returns unexpected object
assuming $fcs/report list
output=1 returns a flowFrame; set output explicitly