dream#
voom_with_dream_weights() gives voom’s precision weights
from mixed models of every gene, fitted by maximum likelihood, as
variancePartition’s voomWithDreamWeights does.
moderated_fixed_effect_tests() moderates the
Satterthwaite or Kenward-Roger t-tests of
fixed_effect_tests() by empirical Bayes, as
variancePartition’s eBayes does for dream fits, adds topTable’s z-statistic, and
tests the contrasts at once by the moderated F-statistic.
dream_voom() runs these steps on every cell
type of a cube, with dream’s choice of the degrees of freedom.
dream: voom weights from mixed models, and moderated tests of their fixed effects.
dream (Hoffman and Roussos 2021) is limma-voom with a linear mixed model in place of
the linear model, for designs with repeated measures: several samples of a donor,
tissues of one patient, time courses. The donor (or another grouping factor) gets a
random intercept, whose variance is estimated for every gene, and contrasts of the
fixed effects are tested with Kenward and Roger’s (1997) degrees of freedom in small
studies and Satterthwaite’s (1946) in larger ones. dreamlet (Hoffman et al. 2026) runs
it on the pseudobulk profiles of every cell type. The steps, as variancePartition runs
them (voomWithDreamWeights, dream, eBayes and topTable):
Precision weights,
voom_with_dream_weights(). voom’s (Law et al. 2014): the log2 counts per million are fitted, the square roots of the residual standard deviations are smoothed by LOWESS against the average log2 counts, and each observation gets the inverse fourth power of the trend at its fitted value (cytepool.stats.voom). The fit is the mixed model of every feature, by maximum likelihood, and the fitted values include the predicted random effects.Fits and tests:
fit_mixed_model()by REML with those weights, andfixed_effect_tests(), with the degrees of freedom of dream’sddf: by default ("adaptive") Kenward and Roger’s for fewer than 20 samples, with their adjusted standard errors, and Satterthwaite’s otherwise.Moderation,
moderated_fixed_effect_tests(). The residual variance of every feature, that of an observation of its average weight, is shrunk towards a prior by limma’s empirical Bayes (Smyth 2004) on the approximate residual degrees of freedom of the mixed model, tr((I - H)’ (I - H)) for its hat matrix H (MixedModelFit.residual_df). The moderated t-statistic divides an estimate by its standard error with the posterior variance in place of the residual variance, and has the degrees of freedom of the test plus the prior’s. Several contrasts are tested at once by the moderated F-statistic t’ R^-1 t / r, limma’s, for their moderated t-statistics and the correlation matrix R of their estimates, with r the number of linearly independent contrasts.
Conventions that the documentation leaves open were found by running variancePartition 1.36.2, with limma 3.62.1 and lme4 1.1-38, as a black box:
voomWithDreamWeightsfits the mixed models by maximum likelihood (its weights agree with those of maximum likelihood fits to lme4’s tolerance, and differ from those of REML fits by up to 12% in an example), and reads the trend at lme4’sfittedvalues, which include the predicted random effects. Without random effects it is limma’svoom.It divides each feature’s prior weights by their mean before the fits, for sample weights and observation weights alike. By default it returns the trend’s weights alone (
rescaleWeightsAfter = FALSE), as limma’svoomdoes; withrescaleWeightsAfter = TRUE, the trend’s weights times the scaled prior weights, which are the weights a fit needs and the ones returned here. They do not change when the prior weights are multiplied by a constant.dreamalso fits each feature with its weights divided by their mean, so itssigmais the residual standard deviation of an observation of the feature’s average weight:residual_variance / mean_weightsof a fit to the weights as given. With voom’s weights this is about the variance that the trend predicts at the feature’s expression, so the variances thateBayesmoderates keep the mean-variance trend that the weights removed;trend=Truelets the prior follow it. Itssigmatherefore differs from limma’s with the same weights; with every variance component at zero, the fit is limma’s weighted fit, and the moderated tests are limma’s for the weights of each feature divided by their mean.eBayesmoderates those variances on the approximate residual degrees of freedomrdf, with limma’ssqueezeVarand its default estimator: the likelihood estimator (Chen et al. 2025) when the degrees of freedom differ between features, as they usually do, and the method of moments otherwise (legacy = NULL). The moderated t-statistics and the B-statistics are those of limma’seBayesfor these variances on these degrees of freedom; the p-values use Satterthwaite’s degrees of freedom plus the prior’s, which, unlike limma’s total degrees of freedom, are not capped at the sum of the residual degrees of freedom.topTableaddsz.std, sign(t) times the standard normal quantile of half the two-sided p-value: the z-statistic with the p-value of the t-statistic, so that tests on different degrees of freedom can be compared. It computes it from the p-value floored at 1e-300.dream(ddf = "adaptive"), the default, uses Kenward and Roger’s method for 19 samples and Satterthwaite’s for 20; the help page says “<= 20 samples”. Withddf = "Kenward-Roger"it tests with lmerTest’scontest, which calls pbkrtest: Kenward and Roger’s adjustment is computed with every observation at the average weight (seecytepool.stats.mixed_models), the standard errors are the adjusted ones, andeBayesmoderates the tests as it does Satterthwaite’s. A gene whose adjusted covariance matrix of the coefficients is not positive definite or has a condition number above 1e6, by R’s estimatekappa, is tested by Satterthwaite’s method instead (variancePartition’s NEWS for 1.31.16 states the rule; the bound was found by probing). The condition number depends on the units of continuous covariates.topTablewith several coefficients gives the coefficients,AveExpr,F,P.Value,adj.P.ValandF.std: F is limma’s moderated F-statistic, from the moderated t-statistics and each gene’s covariance matrix of the coefficients, Kenward and Roger’s adjusted one under their method, andF.stdthe F-statistic on infinite denominator degrees of freedom with the same p-value.
Deliberate differences from variancePartition, reported by validation/dream.py
and validation/kenward_roger_and_f_tests.py:
The LOWESS span is chosen from the number of features by default, as
voom()and limma’svoom(since limma 3.66) choose it.voomWithDreamWeightsuses 0.5, whichspan=0.5reproduces.Beyond a p-value of 1e-300, the z-statistic is computed from the logarithm of the tail probability, so it stays exact where
topTablestops at 37.07.A feature whose mixed model has no minimum, which the fixed and random effects reproduce, is not fitted (see
MixedModelFit): it is left out of the trend, its weights are read at its values, which the effects reproduce, and its tests are NaN. lme4 fits it with a residual standard deviation near zero, which enters the trend, anddreamtests it.topTablecomputes the p-values of an F-test of every gene on the total degrees of freedom of the first gene for the first coefficient listed (found by probing), so that they change with the order of the genes and of the coefficients. Here each gene has its own: F is the mean of the squares of r uncorrelated moderated t-statistics, those of the eigenvectors of R, whose degrees of freedom are those of their contrasts plus the prior’s, and the denominator degrees of freedom combine them as lmerTest combines those of its F-tests (2 E / (E - r), with E = sum nu_m / (nu_m - 2); seecytepool.stats.mixed_models). With one contrast, the F-test is the moderated t-test.F.stduses the number of coefficients where it differs from their rank; here the rank, the F-test’s numerator degrees of freedom.dream_voomdecides which genes fall back to Satterthwaite’s method from the exact condition number, where dream uses R’s estimate: they agree except within about 2% of 1e6.
Random slopes are not implemented yet; variancePartition’s variance partitioning is
cytepool.variance_partitioning.
References
Hoffman GE, Roussos P (2021). Dream: powerful differential expression analysis for repeated measures designs. Bioinformatics 37, 192-201. doi:10.1093/bioinformatics/btaa687
Hoffman GE, Lee D, Bendl J, Prashant NM, Hong A, Casey C, Alvia M, Shao Z, Argyriou S, Therrien K, Venkatesh S, Voloudakis G, Haroutunian V, Fullard JF, Roussos P (2026). Efficient differential expression analysis of large-scale single-cell transcriptomics data using Dreamlet. Nature Communications 17, 9597. doi:10.1038/s41467-026-75680-8
Law CW, Chen Y, Shi W, Smyth GK (2014). voom: precision weights unlock linear model analysis tools for RNA-seq read counts. Genome Biology 15, R29. doi:10.1186/gb-2014-15-2-r29
Kenward MG, Roger JH (1997). Small sample inference for fixed effects from restricted maximum likelihood. Biometrics 53, 983-997. doi:10.2307/2533558
Smyth GK (2004). Linear models and empirical Bayes methods for assessing differential expression in microarray experiments. Statistical Applications in Genetics and Molecular Biology 3, article 3. doi:10.2202/1544-6115.1027
Chen Y, Chen L, Lun ATL, Baldoni PL, Smyth GK (2025). edgeR v4: powerful differential analysis of sequencing data with expanded functionality and improved support for small counts and larger datasets. Nucleic Acids Research 53, gkaf018. doi:10.1093/nar/gkaf018
Satterthwaite FE (1946). An approximate distribution of estimates of variance components. Biometrics Bulletin 2, 110-114. doi:10.2307/3002019
- class cytepool.stats.dream.ModeratedFixedEffectTests(tests, residual_variance_at_mean_weight, residual_df, prior_variance, prior_df, posterior_variance, t, df_total, p_value, lods, z, coefficient_prior_variance, proportion, prior_estimator, f_statistic, f_df1, f_df2, f_p_value, standardized_f_statistic)#
dream’s moderated t-tests of contrasts of the fixed effects of mixed models.
Rows of the per-feature arrays are features and columns are contrasts, as in
tests. The arrays are read-only.- Variables:
tests – The tests moderated, with their fit, contrasts and Satterthwaite’s degrees of freedom.
residual_variance_at_mean_weight –
(n_features,)the variances moderated: the residual variance of an observation of each feature’s average weight,fit.residual_variance / fit.mean_weights(dream’ssigma^2).residual_df –
(n_features,)their degrees of freedom, the fit’s approximate residual degrees of freedom (dream’srdf).prior_variance – The prior variance (
s2.prior): a float, or one value per feature with a trend.prior_df – The prior degrees of freedom (
df.prior): a float, possibly infinite, or one value per feature from a robust fit that finds outliers.posterior_variance –
(n_features,)posterior variances (s2.post).t –
(n_features, n_contrasts)moderated t-statistics: the estimates over their standard errors times (residual_variance_at_mean_weight / posterior_variance)^(1/2).df_total –
(n_features, n_contrasts)their degrees of freedom: Satterthwaite’s plus the prior’s (df.total).p_value – Two-sided p-values of
tondf_totaldegrees of freedom.lods – Log-odds that each contrast is non-zero (the B-statistic), as limma’s
eBayesgives them for these variances onresidual_df.z – Signed z-statistics with the same p-values, sign(t) times the standard normal quantile of half the p-value (
topTable’sz.std).coefficient_prior_variance –
(n_contrasts,)unscaled prior variance of a non-zero contrast (var.prior).proportion – The assumed proportion of non-zero contrasts behind
lods.prior_estimator – The estimator of the prior:
"moments"or"likelihood".f_statistic –
(n_features,)moderated F-statistics testing every contrast oftestsat once: t’ R^-1 t /f_df1, for the moderated t-statistics t and the correlation matrix R of their estimates (topTable’sFfor these contrasts).f_df1 – The numerator degrees of freedom of the F-tests, the number of linearly independent contrasts.
f_df2 –
(n_features,)their denominator degrees of freedom; see the module docstring.f_p_value –
(n_features,)p-values off_statisticonf_df1andf_df2degrees of freedom.standardized_f_statistic –
(n_features,)the F-statistic onf_df1and infinite degrees of freedom with the same p-value (topTable’sF.std), so that tests on different degrees of freedom compare.
Explained in: Mixed models, REML and dream
- cytepool.stats.dream.moderated_fixed_effect_tests(tests, *, proportion=0.01, stdev_coef_lim=(0.1, 4.0), trend=False, robust=False, winsor_tail_p=(0.05, 0.1), prior_estimator=None)#
Empirical Bayes moderated t-tests of mixed model contrasts, as dream’s eBayes.
variancePartition’s
eBayesfordreamfits, withtopTable’s z-statistic: the residual variance of an observation of each feature’s average weight is shrunk towards a prior on the approximate residual degrees of freedom by limma’s empirical Bayes (moderated_statistics(), with its estimators and options), each contrast’s t-statistic uses the posterior variance, and its degrees of freedom are those of the tests (Satterthwaite’s or Kenward and Roger’s) plus the prior’s. The moderated F-statistic tests every contrast oftestsat once, astopTabledoes for several coefficients. See the module docstring.- Parameters:
tests – Tests from
fixed_effect_tests(), of a REML fit asdreammakes them by default. To F-test some of the contrasts, test those alone.proportion – Assumed proportion of non-zero contrasts, in (0, 1).
stdev_coef_lim – Limits for the standard deviation of a non-zero contrast, as for
moderated_statistics.trend – Whether the prior variance follows the mean expression of the features (
eBayes(trend = TRUE)), or an(n_features,)covariate.robust – Whether to estimate the prior robustly (
robust = TRUE).winsor_tail_p – Winsorized tail proportions of the robust moment estimator.
prior_estimator –
"moments","likelihood"or None for limma’s default (legacy = NULL), as formoderated_statistics.
- Returns:
The moderated tests.
- Raises:
TypeError – If
testsis not aFixedEffectTests, or an option has the wrong type or is a numpy masked array.ValueError – If
testshas no contrasts, an option is invalid, or no feature has a fit.
Explained in: Mixed models, REML and dream
- cytepool.stats.dream.voom_with_dream_weights(counts, design, *, library_sizes=None, norm_factors=None, span=None, weights=None, method='ml', n_threads=None)#
voom’s precision weights from the mean-variance trend of mixed model fits.
variancePartition’s
voomWithDreamWeights: voom (seevoom()), with the linear model replaced by the mixed model ofdesign, fitted to every feature by maximum likelihood, and the trend read at the fitted values with the predicted random effects; the module docstring gives the conventions. Continue withfit_mixed_model(result.log_cpm, design, weights=result.weights),fixed_effect_testsandmoderated_fixed_effect_tests().- Parameters:
counts –
(n_samples, n_features)counts, as forvoom: finite and non-negative, at least two features.design – A
Designwith random intercepts, asfit_mixed_model()takes; for a design without random effects usevoom.library_sizes – Library size of each sample; defaults to the total counts.
norm_factors – Normalization factor of each sample, such as TMM factors; defaults to ones.
span – The span of the LOWESS trend, in (0, 1]; by default chosen from the number of features, as
voomchooses it.voomWithDreamWeightsuses 0.5.weights – Prior weights:
(n_samples,)sample weights, such as each pseudobulk sample’s number of cells, or(n_samples, n_features)observation weights; finite and positive. Each feature’s weights are divided by their mean, then weight the fits behind the trend, and multiply the weights returned.method –
"ml", maximum likelihood, asvoomWithDreamWeightsfits, or"reml".n_threads – The most threads for the fits, as for
fit_mixed_model.
- Returns:
The log2 counts per million, their weights (the trend’s times the scaled prior weights), the effective library sizes, and the trend with its span.
- Raises:
TypeError – If an argument has the wrong type, or is or holds a numpy masked array.
ValueError – If
countsis not a 2-D array of finite non-negative values with at least two features, the design has no random effects or cannot be fitted (as forfit_mixed_model), its samples are not the rows ofcounts, a library size or normalization factor is not positive,spanis not in (0, 1], a prior weight is not finite and positive, fewer than two features with counts can be fitted, or the trend is not positive where weights are read from it.
Explained in: Mixed models, REML and dream