Skip to content

Commit 90d6bf9

Browse files
committed
Update Perturb-seq example
1 parent 44fbe4e commit 90d6bf9

7 files changed

Lines changed: 1463 additions & 255 deletions

File tree

causarray/DR_learner.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -301,19 +301,29 @@ def LFC(
301301
302302
* ``'unequal'`` (default, v0.0.6+): Welch variance
303303
``s₀²/n₀ + s₁²/n₁`` with Welch-Satterthwaite degrees of
304-
freedom; p-values use the t-distribution. This is the recommended
305-
choice for perturbation screens and for case-control, bulk, and
306-
donor-level pseudo-bulk analyses. Independence of the rows does not
307-
imply equal treatment-arm variances, and biological heterogeneity or
308-
unequal effective sample sizes can make pooled inference
309-
anti-conservative.
304+
freedom; p-values use the t-distribution. Prefer this estimator when
305+
treatment and control sample sizes or effective sample sizes are
306+
meaningfully unbalanced, when arm-specific pseudo-outcome variances
307+
may differ, and for case-control, bulk, and donor-level pseudo-bulk
308+
analyses. Independence of the rows does not imply equal
309+
treatment-arm variances, and biological heterogeneity or imbalance
310+
can make pooled inference anti-conservative.
310311
* ``'pooled'``: pooled-variance estimator ``(s² + eps_var) / n``.
311-
Treat this as an opt-in sensitivity or legacy analysis, not as the
312-
default for small case-control studies. Use it only when equal arm
313-
variances have a strong scientific and empirical justification.
314-
Pooled inference can produce substantially smaller standard errors
315-
and many more discoveries; donor-level independence alone is not a
316-
justification for pooling.
312+
For a small, approximately balanced perturbation comparison, this
313+
estimator may provide better power when the independent sampling
314+
units and arm-specific pseudo-outcome variances are reasonably
315+
comparable. Treat it as an opt-in, empirically justified analysis,
316+
not as an automatic choice for every small study. Balanced sample
317+
counts alone are insufficient for case-control data, where biological
318+
heterogeneity commonly favors ``'unequal'``. Pooled inference can
319+
produce substantially smaller standard errors and many more
320+
discoveries.
321+
322+
There is no universal arm-size ratio at which the choice should switch.
323+
Inspect nominal and propensity-weighted effective sample sizes,
324+
arm-specific pseudo-outcome variability, and sensitivity of the
325+
discoveries. When those diagnostics are uncertain, retain
326+
``'unequal'``.
317327
318328
``'unequal'`` accommodates arm-specific variance but does not model
319329
within-donor or within-subject correlation. Repeated cells from the
@@ -634,10 +644,13 @@ def gcate_lfc_batch(
634644
lfc_kwargs : dict or None
635645
Extra keyword arguments forwarded to :func:`LFC`
636646
(e.g. ``usevar``, ``fdx``, ``thres_min``). Retain the default
637-
``usevar='unequal'`` for perturbation screens and for case-control,
638-
bulk, or pseudo-bulk analyses. Pass
639-
``lfc_kwargs=dict(usevar='pooled')`` only for a deliberately justified
640-
equal-variance sensitivity or legacy analysis.
647+
``usevar='unequal'`` when arm sizes or effective sample sizes are
648+
meaningfully unbalanced, when arm-specific variability may differ, and
649+
for case-control, bulk, or pseudo-bulk analyses. For a small,
650+
approximately balanced perturbation comparison with comparable
651+
pseudo-outcome variability, ``lfc_kwargs=dict(usevar='pooled')`` may
652+
improve power. There is no universal balance threshold; compare the
653+
relevant diagnostics and retain ``'unequal'`` when uncertain.
641654
**kwargs
642655
Additional arguments forwarded to both :func:`fit_gcate_batch` and
643656
:func:`LFC`. When a key collides with ``gcate_kwargs`` /

docs/source/main_function/lfc.rst

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,29 @@ Choosing the variance estimator
1313
-------------------------------
1414

1515
``LFC`` defaults to ``usevar='unequal'`` (Welch inference), which estimates
16-
the treatment and control variances separately. Retain this default for
17-
perturbation screens and for case-control, bulk, and donor-level pseudo-bulk
18-
analyses. Independence of the rows does not imply equal treatment-arm
19-
variances: disease severity, biological response, residual composition,
20-
library size, treatment imbalance, and heterogeneous expression can all make
21-
pooled inference anti-conservative.
22-
23-
Treat ``usevar='pooled'`` as an opt-in sensitivity or legacy analysis. Use it
24-
only when equal arm variances have a strong scientific and empirical
25-
justification; do not select it merely because a case-control study has a
26-
small number of independent samples. Pooled inference can produce much smaller
27-
standard errors and substantially more discoveries. For a deliberately
28-
justified batched sensitivity analysis, pass
29-
``lfc_kwargs=dict(usevar='pooled')``.
16+
the treatment and control variances separately. Prefer this default when the
17+
treatment and control sample sizes, or their propensity-weighted effective
18+
sample sizes, are meaningfully unbalanced. Also retain it when arm-specific
19+
pseudo-outcome variances may differ and for case-control, bulk, and donor-level
20+
pseudo-bulk analyses. Independence of the rows does not imply equal
21+
treatment-arm variances: disease severity, biological response, residual
22+
composition, library size, treatment imbalance, and heterogeneous expression
23+
can all make pooled inference anti-conservative.
24+
25+
For a small, approximately balanced perturbation comparison,
26+
``usevar='pooled'`` may provide better power when the independent sampling
27+
units and arm-specific pseudo-outcome variances are reasonably comparable.
28+
Treat it as an opt-in, empirically justified analysis rather than an automatic
29+
small-sample choice. Balanced counts alone do not justify pooling in a
30+
case-control study. Pooled inference can produce much smaller standard errors
31+
and substantially more discoveries. For a deliberately justified batched
32+
analysis, pass ``lfc_kwargs=dict(usevar='pooled')``.
33+
34+
There is no universal sample-size ratio at which the recommendation changes.
35+
Compare nominal arm sizes, propensity-weighted effective sample sizes,
36+
arm-specific pseudo-outcome variability, and the stability of discoveries
37+
under both estimators. Retain ``usevar='unequal'`` when these diagnostics do not
38+
support pooling.
3039

3140
Donor-level independence alone does not establish equal arm variances. For
3241
example, the SEA-AD tutorial uses ``usevar='unequal'`` because disease severity,

docs/source/tutorial/perturbseq/perturbseq-py.ipynb

Lines changed: 223 additions & 219 deletions
Large diffs are not rendered by default.

docs/source/tutorial/perturbseq/perturbseq-r.Rmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ res_gate <- causarray$fit_gcate(Y, X, A, r, verbose=TRUE) # a list of results fr
6969
U <- res_gate[[2]]$U
7070
```
7171

72-
Next, we apply causarray to estimate the causal effects of perturbations on gene expression. We use unequal (Welch) variance because treatment and control cells can have different pseudo-outcome variability; pooling those variances can be anti-conservative in a perturbation screen.
72+
Next, we apply causarray to estimate the causal effects of perturbations on gene expression. Here the 106 GFP control cells and the perturbation groups (median 89 cells) are approximately balanced. We therefore use pooled variance to retain power in this relatively small comparison. This is a dataset-specific choice: unequal variance remains preferable when arm sizes or effective sample sizes are meaningfully unbalanced, when pseudo-outcome variability differs between arms, and for the Replogle and case-control tutorials.
7373

7474
```{r}
7575
offsets <- log(res_gate[[2]][['kwargs_glm']][['size_factor']]) # use the precomputed size factors
7676
res <- causarray$LFC(Y, cbind(X, U), A, cbind(X_A, U), offset=offsets,
77-
usevar="unequal", verbose=TRUE)
77+
usevar="pooled", verbose=TRUE)
7878
```
7979

8080
```{r}

docs/source/tutorial/perturbseq/perturbseq-r.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,18 @@ U <- res_gate[[2]]$U
132132
```
133133

134134
Next, we apply causarray to estimate the causal effects of perturbations
135-
on gene expression. We use unequal (Welch) variance because treatment and
136-
control cells can have different pseudo-outcome variability; pooling those
137-
variances can be anti-conservative in a perturbation screen.
135+
on gene expression. Here the 106 GFP control cells and the perturbation
136+
groups (median 89 cells) are approximately balanced. We therefore use
137+
pooled variance to retain power in this relatively small comparison. This
138+
is a dataset-specific choice: unequal variance remains preferable when arm
139+
sizes or effective sample sizes are meaningfully unbalanced, when
140+
pseudo-outcome variability differs between arms, and for the Replogle and
141+
case-control tutorials.
138142

139143
``` r
140144
offsets <- log(res_gate[[2]][['kwargs_glm']][['size_factor']]) # use the precomputed size factors
141145
res <- causarray$LFC(Y, cbind(X, U), A, cbind(X_A, U), offset=offsets,
142-
usevar="unequal", verbose=TRUE)
146+
usevar="pooled", verbose=TRUE)
143147
```
144148

145149
## 'Estimating LFC...'
-21.3 KB
Loading

docs/source/tutorial/replogle/replogle-pooled-py.ipynb

Lines changed: 1178 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)