Standard curves, detection limits and omics · Choose a method

Comparing flow cytometry MFI between groups: median fluorescence, log scale, staining day and the mouse as n

Summarise each mouse by its median (or geometric mean) fluorescence, compare groups on the log scale with the mouse as n, and block by staining day when MFI shifts between staining days. Events are not replicates. Python and R code.

By Licklider · Published · Last reviewed · How this page was made · Markdown

On this page
  1. Which analysis for your question
  2. Worked example: a knockout that lowers a surface marker
  3. Before you analyse
  4. Check what an AI assistant ran
  5. Report it
  6. References

Quick answer. Summarise each mouse (or donor) by the median or geometric mean fluorescence of the gated population (MdFI or gMFI, not the arithmetic mean), then compare groups with the mouse as n, on the log scale, and report the ratio (of geometric means) with its 95% confidence interval. The thousands of events from one mouse are not replicates: with events as n, 62.5% of our simulated studies with no real difference came out “significant”. MFI also shifts between staining days and instrument settings, so stain every group on every day and include the day as a block; in our simulation that raised power for a 20% difference from 21.9% to 78.5%.

Terms used below. Event: one cell (or particle) measured by the cytometer. Gate: a region that selects a cell population. MFI: strictly the arithmetic mean fluorescence intensity; also used loosely, as in this page’s title, for any average intensity. gMFI: the geometric mean fluorescence intensity (the back-transformed mean of the logs). MdFI: the median fluorescence intensity. Log scale: analysing log(intensity), so a 20% decrease is the same difference at any brightness; every per-mouse value must be above 0. Staining day (batch): samples stained and acquired together, with the same reagents and instrument settings. Welch’s t-test: compares two groups without assuming equal spreads. Two-way ANOVA (linear model): a regression with two categorical predictors, here group and day. Block: a predictor, such as the staining day, included in the analysis so that its shifts are separated from the noise. FMO control: fluorescence minus one, a sample stained with all markers except one. Isotype control: an antibody of the same class with no relevant target. Counting beads: beads of known number added to a sample to convert events to absolute cell counts. Standardisation beads: beads of known fluorescence used to set or check instrument settings. Interaction: whether the group difference changes from day to day. Mixed model: a regression with random effects for units such as mouse or day, so repeated values from one unit are not treated as independent. Degrees of freedom: roughly, the number of independent values minus the number of estimated means. Quasi-Poisson: a regression for counts that allows extra variation. 95% confidence interval (CI): the range of values compatible with the data. Power: the chance of detecting an effect that is really there. False positive: a “significant” result when there is no real effect.

Which analysis for your question

Question Analysis Report
Does marker intensity differ between groups (all samples stained on one day)? Per-mouse MdFI or gMFI; Welch’s t-test on log values (mouse as n) Ratio with 95% CI, n mice, p
Samples stained on several days, every group on every day Per-mouse log MdFI ~ group + day (two-way ANOVA without interaction); a paired t-test if there is exactly one mouse per group per day Ratio with 95% CI, adjusted for day
A group missing from some days Day and group are confounded; no model separates them. Restain in a balanced design —
Does the percentage of positive cells differ? Per-mouse percentage with the gate set from FMO controls; compare as a percentage (comparing percentages) Difference in percentage points with 95% CI
Absolute cell numbers Counting beads or a cell count per mouse; a count model such as quasi-Poisson (count data) Ratio with 95% CI
Many markers or populations The same per marker, with a correction across the markers tested, such as Holm or Benjamini–Hochberg (which correction) Ratios with 95% CIs and adjusted p-values

The 2019 flow cytometry guidelines explain that “most fluorescence data collected on modern flow cytometers, is skewed and conforms to an approximately log-normal distribution, indicating that the gMFI and MdFI may be better choices than the MFI” (Cossarizza et al. 2019); for the series 1, 10, 100, 1,000, 10,000, the median and the geometric mean are both 100, while the arithmetic mean is 2,222. The guidelines also note that the gMFI cannot handle values below zero created by compensation, which favours the median when such values occur. The same guidelines describe scale calibration as a way “to measure absolute values … instead of relative mean fluorescent intensities (MFIs)”, and state that the FMO control “is required to accurately determine the threshold for positive staining”. On the unit of analysis, Lazic shows that n “must therefore represent the number of independent observations, which in this case is the number of rats, not the number of cells” (Lazic 2010). The MIFlowCyt standard asks authors “to state denominators used to calculate percentages of events within a gate” (Lee et al. 2008).

Worked example: a knockout that lowers a surface marker

Constructed data: fluorescence of one marker on a gated population, 1,000 events per mouse, from 6 wild-type (WT) and 6 knockout (KO) mice, 2 of each stained and acquired on each of 3 days. By design, the knockout lowers the median fluorescence by 20% (ratio 0.8); each day shifts every sample’s brightness (staining batch and instrument settings). The random seed was the first one tried and was not chosen for its result. Stored code and data: events.csv, model.py, make_data.py, analysis.py, analysis.R and the analysis output; analysis.py and analysis.R print the same output.

The WT mice’s median fluorescence averaged 2,288 on day 1, 1,141 on day 2 and 2,002 on day 3: the day changed brightness by up to two-fold, far more than the knockout did.

Analysis KO ÷ WT Result
Events as n (6,000 vs 6,000 events), Welch’s t-test on raw fluorescence — p = 1.9 × 10⁻²⁴
Per-mouse arithmetic mean, ignoring day, Welch’s t-test 0.82 (ratio of means) p = 0.28
Per-mouse median, log scale, ignoring day 0.84 (ratio of geometric means; 95% CI 0.57 to 1.26) p = 0.37
Per-mouse median, log scale, day as a block 0.84 (95% CI 0.74 to 0.97) p = 0.02

Events as n gives an absurdly small p-value from 6 mice per group. The estimate 0.84 differs from the true 0.80 by ordinary sampling error, and the interval from the model with day as a block covers 0.80. With the mouse as n, the day-to-day shifts swamp the knockout effect unless the analysis compares mice within each day; with the day as a block, the interval for the knockout is narrow and excludes a ratio of 1. In 10,000 simulated studies of this design (simulation.py, the simulation output):

Scenario Events as n, p < 0.05 Per-mouse median, ignoring day Per-mouse median, day as a block
No difference 62.5% (false positives) 0.5% (false positives) 5.0% (false positives)
KO 20% lower 99.5% (power) 21.9% (power) 78.5% (power)

Ignoring the day is not wrong in this balanced design, only wasteful: it rarely gives false positives but detects a real 20% difference in about one study in five. Blocking by day keeps false positives at 5% and nearly quadruples the power. If any group is missing from a day, day and group are confounded and neither analysis is valid. These rates are for this simulated design (true ratio 0.8, 6 mice per group over 3 days; on the log scale, a day-to-day standard deviation of 0.30, mouse-to-mouse 0.12 and cell-to-cell 0.8); with less day-to-day variation, blocking gains less.

The code expects one row per event with columns day, mouse, genotype (WT or KO) and fluorescence, exported from the gated population. If your software exports one median per mouse instead, load that table as m with columns day, mouse, genotype and mdfi (Python) or fluorescence (R), and skip the aggregation line. Rename your columns and group labels to match, and run the code in the folder that holds the CSV file. Every per-mouse MdFI must be above 0 for the log; if compensation leaves a median at or below 0, report that population descriptively. analysis.py needs NumPy, pandas and SciPy; the condensed snippet also needs statsmodels; the R code uses base R only.

# Condensed: analysis.py also gives the events-as-n, arithmetic-mean and unblocked comparisons
import numpy as np, pandas as pd
import statsmodels.formula.api as smf

e = pd.read_csv("events.csv")
m = e.groupby(["day", "mouse", "genotype"]).fluorescence.median().reset_index(name="mdfi")   # one MdFI per mouse
fit = smf.ols("np.log(mdfi) ~ C(genotype, Treatment('WT')) + C(day)", m).fit()             # day as a block
b = fit.params.iloc[1]; lo, hi = fit.conf_int().iloc[1]
print(np.exp(b), np.exp(lo), np.exp(hi), fit.pvalues.iloc[1])                               # KO / WT, 95% CI, p
# all samples stained on one day: drop "+ C(day)" from the formula (or Welch's t-test on np.log(m.mdfi) by genotype)
e <- read.csv("events.csv")
m <- aggregate(fluorescence ~ day + mouse + genotype, data = e, FUN = median)                # one MdFI per mouse
fit <- lm(log(fluorescence) ~ factor(genotype, levels = c("WT", "KO")) + factor(day), data = m)   # day as a block; control group first
exp(coef(fit)[2]); exp(confint(fit)[2, ]); summary(fit)$coefficients[2, 4]                  # KO / WT, 95% CI, p

Before you analyse

  1. Stain and acquire every group on every day, in a balanced design, with the same panel, reagent lots and instrument settings; record the day of each sample. If all KO mice are stained on one day and all WT on another, no analysis can separate genotype from day.
  2. Set gates from FMO controls and apply the same gates to all samples; report the gating strategy and the denominator of each percentage.
  3. Export one value per mouse (MdFI or gMFI of the gated population, and the number of gated events); if mice were sampled on several days, use a mixed model with mouse as a random effect. Very small populations give unstable medians; decide a minimum event count in advance. If mice of one group share cages or litters, treat the cage or litter as the unit or add it to the model (what counts as n).
  4. Keep instrument settings fixed or calibrate. Standardisation beads or calibrated scales make MFI comparable across days and instruments; without them, block by day as above.
  5. Normalising to the day’s control is an alternative to blocking: divide every mouse’s MdFI, WT included, by the mean WT MdFI of its day, then compare the two groups’ log ratios. Testing only the KO ratios against 1 treats the control as known without error. Blocking in the model does the same job more simply (statistics on fold change). If the knockout effect may differ between days, use more days and a model with day and day × genotype as random effects.

Check what an AI assistant ran

  1. The assistant compared events (cells) between groups. Ask for one value per mouse and the mouse as n; with 6 mice per group a t-test has about 10 degrees of freedom, and degrees of freedom in the thousands mean events were counted.
  2. The assistant averaged arithmetic means of the fluorescence. Ask for medians or geometric means, analysed on the log scale.
  3. The assistant ignored the staining day. Ask for day as a block, and check that every group was stained on every day.
  4. The assistant set gates differently per sample or used isotype controls for the positivity threshold. Ask for FMO-based gates applied to all samples.

Report it

For each mouse, the median fluorescence intensity (MdFI) of [marker] on [gated population] was exported ([1,000] or more events per mouse). Gates were set from FMO controls. Log-transformed MdFI was compared between genotypes with a linear model including staining day as a block ([3] days, [2] mice per genotype per day; mouse as the unit, n = [6] per genotype; R [4.3.3]).

Adjusted for staining day, knockout MdFI was [0.84] times that of wild-type mice (ratio of geometric means; 95% CI [0.74] to [0.97]; p = [0.02]).

Replace the bracketed values with your own.

References

  • Cossarizza A, Chang HD, Radbruch A, et al. (2019). Guidelines for the use of flow cytometry and cell sorting in immunological studies (second edition). European Journal of Immunology 49:1457–1973. doi:10.1002/eji.201970107
  • Lazic SE (2010). The problem of pseudoreplication in neuroscientific studies: is it affecting your analysis? BMC Neuroscience 11:5. doi:10.1186/1471-2202-11-5
  • Lee JA, Spidlen J, Boyce K, et al. (2008). MIFlowCyt: the minimum information about a flow cytometry experiment. Cytometry Part A 73A:926–930. doi:10.1002/cyto.a.20623

How this page was made

  • Written and published by Licklider. Recommendations cite peer-reviewed guidelines, standards and methods papers listed under References; cited passages were checked against the source text.
  • The worked example uses constructed data. Its numbers were produced by stored code (Python 3.13 with SciPy 1.18.1; R 4.3.3, base R; the condensed Python snippet uses statsmodels 0.15.0), and the two languages print identical output; the simulation was run in Python.
  • Separate review passes checked the statistics, the citations and readability before publication.