causarray 0.0.5__tar.gz → 0.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {causarray-0.0.5 → causarray-0.0.6}/.gitignore +19 -1
- {causarray-0.0.5 → causarray-0.0.6}/PKG-INFO +33 -6
- {causarray-0.0.5 → causarray-0.0.6}/README.md +30 -3
- {causarray-0.0.5 → causarray-0.0.6}/causarray/DR_estimation.py +26 -3
- {causarray-0.0.5 → causarray-0.0.6}/causarray/DR_inference.py +9 -3
- causarray-0.0.6/causarray/DR_learner.py +728 -0
- causarray-0.0.6/causarray/__about__.py +1 -0
- causarray-0.0.6/causarray/__init__.py +31 -0
- causarray-0.0.6/causarray/gcate.py +609 -0
- {causarray-0.0.5 → causarray-0.0.6}/causarray/gcate_glm.py +204 -7
- {causarray-0.0.5 → causarray-0.0.6}/causarray/gcate_opt.py +187 -20
- causarray-0.0.6/causarray/nb_glm_fast.py +777 -0
- {causarray-0.0.5 → causarray-0.0.6}/causarray/utils.py +102 -9
- {causarray-0.0.5 → causarray-0.0.6}/pyproject.toml +3 -3
- causarray-0.0.5/causarray/DR_learner.py +0 -324
- causarray-0.0.5/causarray/__about__.py +0 -1
- causarray-0.0.5/causarray/__init__.py +0 -21
- causarray-0.0.5/causarray/gcate.py +0 -246
- {causarray-0.0.5 → causarray-0.0.6}/LICENSE +0 -0
- {causarray-0.0.5 → causarray-0.0.6}/causarray/gcate_likelihood.py +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# Planning documents
|
|
2
|
+
plan/
|
|
3
|
+
|
|
1
4
|
# Byte-compiled / optimized / DLL files
|
|
2
5
|
__pycache__/
|
|
3
6
|
*.py[cod]
|
|
@@ -160,5 +163,20 @@ cython_debug/
|
|
|
160
163
|
#.idea/
|
|
161
164
|
|
|
162
165
|
|
|
163
|
-
|
|
166
|
+
# Generic module tests under tests/ ARE tracked (regression coverage for
|
|
167
|
+
# the causarray API). Exclude only benchmark / scratch files that are
|
|
168
|
+
# not part of the unit-test suite — add new exclusions here when
|
|
169
|
+
# benchmark or tutorial-coupled test files appear.
|
|
170
|
+
tests/benchmark_adamson.py
|
|
171
|
+
|
|
164
172
|
causarray/___*.py
|
|
173
|
+
/docs/source/tutorial/adamson
|
|
174
|
+
|
|
175
|
+
# Replogle tutorial: large data files (regenerate with prep_tutorial_data.py or
|
|
176
|
+
# download from the project data repository; replogle_subset.h5ad is ~2 GB)
|
|
177
|
+
docs/source/tutorial/replogle/replogle_subset.h5ad
|
|
178
|
+
docs/source/tutorial/replogle/replogle_normed.h5ad
|
|
179
|
+
docs/source/tutorial/replogle/replogle_results.h5
|
|
180
|
+
|
|
181
|
+
# Unrelated tutorial directory (not part of causarray package docs)
|
|
182
|
+
docs/source/tutorial/scp/
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: causarray
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.6
|
|
4
4
|
Summary: causarray is a Python module for simultaneous causal inference with an array of outcomes.
|
|
5
|
-
Author-email: Jin-Hong Du <jinhongd@
|
|
6
|
-
Maintainer-email: Jin-Hong Du <jinhongd@
|
|
5
|
+
Author-email: Jin-Hong Du <jinhongd@hku.hk>, Maya Shen <myshen@andrew.cmu.edu>, Hansruedi Mathys <mathysh@pitt.edu>, Kathryn Roeder <jinhongd@hku.hk>
|
|
6
|
+
Maintainer-email: Jin-Hong Du <jinhongd@hku.hk>
|
|
7
7
|
License: MIT License
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
Classifier: Intended Audience :: Developers
|
|
@@ -49,17 +49,44 @@ The module can be installed via PyPI:
|
|
|
49
49
|
pip install causarray
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
For optimal parallel performance, we recommend installing `llvm-openmp` if using conda:
|
|
53
|
+
```cmd
|
|
54
|
+
conda install -c conda-forge llvm-openmp
|
|
55
|
+
```
|
|
56
|
+
|
|
52
57
|
For `R` users, `reticulate` can be used to call `causarray` from `R`.
|
|
53
58
|
The documentation and tutorials using both `Python` and `R` are available at [causarray.readthedocs.io](https://causarray.readthedocs.io/en/latest/).
|
|
54
59
|
|
|
55
60
|
|
|
56
61
|
|
|
57
|
-
##
|
|
62
|
+
## Batch fitting for large-scale screens
|
|
63
|
+
|
|
64
|
+
For screens with hundreds to thousands of perturbations, use the batch API
|
|
65
|
+
so that peak memory is bounded by one batch at a time:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from causarray import gcate_lfc_batch
|
|
69
|
+
|
|
70
|
+
df_res = gcate_lfc_batch(
|
|
71
|
+
Y, X, A, r,
|
|
72
|
+
batch_size=10, # perturbations per batch (or use n_batches= for a fixed count)
|
|
73
|
+
max_cells=2000, # max pert cells per batch (ctrl added on top)
|
|
74
|
+
n_ctrl=2000, # fixed ctrl subsample shared across batches
|
|
75
|
+
cache_path='results.h5', # resume if interrupted
|
|
76
|
+
verbose=True,
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
See the [Replogle-E-K562 tutorial](https://causarray.readthedocs.io/en/latest/)
|
|
81
|
+
for a demonstration on 200 perturbations from a genome-wide CRISPRi screen.
|
|
82
|
+
|
|
83
|
+
## Changelog
|
|
58
84
|
|
|
59
85
|
- [x] (2025-01-30) Python package released on PyPI
|
|
60
|
-
- [x] (2025-02-01)
|
|
86
|
+
- [x] (2025-02-01) Code for reproducing figures in paper
|
|
61
87
|
- [x] (2025-02-02) Tutorial for Python and R
|
|
62
|
-
- [
|
|
88
|
+
- [x] (2026-05-31) Batch fitting API (`gcate_lfc_batch`) for large-scale screens
|
|
89
|
+
- [x] (2026-05-31) Documentation at [causarray.readthedocs.io](https://causarray.readthedocs.io/en/latest/)
|
|
63
90
|
|
|
64
91
|
|
|
65
92
|
<!--
|
|
@@ -24,17 +24,44 @@ The module can be installed via PyPI:
|
|
|
24
24
|
pip install causarray
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
For optimal parallel performance, we recommend installing `llvm-openmp` if using conda:
|
|
28
|
+
```cmd
|
|
29
|
+
conda install -c conda-forge llvm-openmp
|
|
30
|
+
```
|
|
31
|
+
|
|
27
32
|
For `R` users, `reticulate` can be used to call `causarray` from `R`.
|
|
28
33
|
The documentation and tutorials using both `Python` and `R` are available at [causarray.readthedocs.io](https://causarray.readthedocs.io/en/latest/).
|
|
29
34
|
|
|
30
35
|
|
|
31
36
|
|
|
32
|
-
##
|
|
37
|
+
## Batch fitting for large-scale screens
|
|
38
|
+
|
|
39
|
+
For screens with hundreds to thousands of perturbations, use the batch API
|
|
40
|
+
so that peak memory is bounded by one batch at a time:
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from causarray import gcate_lfc_batch
|
|
44
|
+
|
|
45
|
+
df_res = gcate_lfc_batch(
|
|
46
|
+
Y, X, A, r,
|
|
47
|
+
batch_size=10, # perturbations per batch (or use n_batches= for a fixed count)
|
|
48
|
+
max_cells=2000, # max pert cells per batch (ctrl added on top)
|
|
49
|
+
n_ctrl=2000, # fixed ctrl subsample shared across batches
|
|
50
|
+
cache_path='results.h5', # resume if interrupted
|
|
51
|
+
verbose=True,
|
|
52
|
+
)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
See the [Replogle-E-K562 tutorial](https://causarray.readthedocs.io/en/latest/)
|
|
56
|
+
for a demonstration on 200 perturbations from a genome-wide CRISPRi screen.
|
|
57
|
+
|
|
58
|
+
## Changelog
|
|
33
59
|
|
|
34
60
|
- [x] (2025-01-30) Python package released on PyPI
|
|
35
|
-
- [x] (2025-02-01)
|
|
61
|
+
- [x] (2025-02-01) Code for reproducing figures in paper
|
|
36
62
|
- [x] (2025-02-02) Tutorial for Python and R
|
|
37
|
-
- [
|
|
63
|
+
- [x] (2026-05-31) Batch fitting API (`gcate_lfc_batch`) for large-scale screens
|
|
64
|
+
- [x] (2026-05-31) Documentation at [causarray.readthedocs.io](https://causarray.readthedocs.io/en/latest/)
|
|
38
65
|
|
|
39
66
|
|
|
40
67
|
<!--
|
|
@@ -3,6 +3,7 @@ from sklearn.linear_model import LogisticRegression
|
|
|
3
3
|
from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
|
|
4
4
|
from sklearn_ensemble_cv import reset_random_seeds, Ensemble, ECV
|
|
5
5
|
from causarray.gcate_glm import fit_glm
|
|
6
|
+
import causarray.gcate_glm as _gcate_glm # module-qualified so _USE_FAST_BACKEND changes take effect at call time
|
|
6
7
|
from causarray.utils import *
|
|
7
8
|
from causarray.utils import _filter_params
|
|
8
9
|
from joblib import Parallel, delayed
|
|
@@ -101,7 +102,19 @@ def cross_fitting(
|
|
|
101
102
|
fit_pi = True if pi_hat is None else False
|
|
102
103
|
pi_hat = np.zeros_like(A, dtype=float) if fit_pi else pi_hat
|
|
103
104
|
fit_Y = True if Y_hat is None else False
|
|
104
|
-
|
|
105
|
+
if fit_Y:
|
|
106
|
+
_yhat_gb = Y.shape[0] * Y.shape[1] * A.shape[1] * 2 * 8 / 1e9
|
|
107
|
+
_mem_limit_gb = kwargs.get('mem_limit_gb', None)
|
|
108
|
+
if _mem_limit_gb is not None and _yhat_gb > _mem_limit_gb:
|
|
109
|
+
import warnings
|
|
110
|
+
warnings.warn(
|
|
111
|
+
f"Y_hat allocation ({_yhat_gb:.1f} GB as float64) exceeds "
|
|
112
|
+
f"mem_limit_gb={_mem_limit_gb} GB; using float32 to halve peak memory.",
|
|
113
|
+
ResourceWarning, stacklevel=3,
|
|
114
|
+
)
|
|
115
|
+
Y_hat = np.zeros((Y.shape[0], Y.shape[1], A.shape[1], 2), dtype=np.float32)
|
|
116
|
+
else:
|
|
117
|
+
Y_hat = np.zeros((Y.shape[0], Y.shape[1], A.shape[1], 2), dtype=float)
|
|
105
118
|
|
|
106
119
|
# perform ECV at once
|
|
107
120
|
if fit_pi and ps_model == 'random_forest_cv':
|
|
@@ -145,9 +158,19 @@ def cross_fitting(
|
|
|
145
158
|
|
|
146
159
|
if fit_Y:
|
|
147
160
|
if verbose: pprint.pprint('Fit outcome models...')
|
|
161
|
+
# Subset offset to training fold (for fitting) and test fold (for
|
|
162
|
+
# imputation) when it is a pre-computed array, so that
|
|
163
|
+
# ``fit_glm_auto`` receives arrays with matching leading
|
|
164
|
+
# dimensions in both stages.
|
|
165
|
+
params_glm_fold = params_glm
|
|
166
|
+
offset_test_arr = None
|
|
167
|
+
if 'offset' in params_glm and isinstance(params_glm['offset'], np.ndarray):
|
|
168
|
+
params_glm_fold = dict(params_glm)
|
|
169
|
+
params_glm_fold['offset'] = params_glm['offset'][train_index]
|
|
170
|
+
offset_test_arr = params_glm['offset'][test_index]
|
|
148
171
|
# Fit GLM on training data and predict on test data
|
|
149
|
-
res =
|
|
150
|
-
impute=X_test, **
|
|
172
|
+
res = _gcate_glm.fit_glm_auto(Y_train, X_train, A_train, family=family, alpha=glm_alpha,
|
|
173
|
+
impute=X_test, offset_test=offset_test_arr, **params_glm_fold)
|
|
151
174
|
Y_hat[test_index,:,:,0] = res[1][0]
|
|
152
175
|
Y_hat[test_index,:,:,1] = res[1][1]
|
|
153
176
|
|
|
@@ -150,7 +150,7 @@ def fdx_control(
|
|
|
150
150
|
return V
|
|
151
151
|
|
|
152
152
|
|
|
153
|
-
def bh_correction(tvalues_init):
|
|
153
|
+
def bh_correction(tvalues_init, df=None):
|
|
154
154
|
'''
|
|
155
155
|
Perform BH correction.
|
|
156
156
|
|
|
@@ -179,7 +179,10 @@ def bh_correction(tvalues_init):
|
|
|
179
179
|
qvals_adj = np.full(tvalues_init.shape, np.nan)
|
|
180
180
|
|
|
181
181
|
if np.sum(idx) > 0:
|
|
182
|
-
|
|
182
|
+
if df is not None:
|
|
183
|
+
pvals[idx] = sp.stats.t.sf(np.abs(tvalues_init[idx]), df=df[idx]) * 2
|
|
184
|
+
else:
|
|
185
|
+
pvals[idx] = sp.stats.norm.sf(np.abs(tvalues_init[idx])) * 2
|
|
183
186
|
qvals[idx] = multipletests(pvals[idx], alpha=0.05, method='fdr_bh')[1]
|
|
184
187
|
|
|
185
188
|
# BH correction with empirical null adjustment
|
|
@@ -189,7 +192,10 @@ def bh_correction(tvalues_init):
|
|
|
189
192
|
if mad>0:
|
|
190
193
|
tvalues_init_adj = (tvalues_init - med) / mad
|
|
191
194
|
|
|
192
|
-
|
|
195
|
+
if df is not None:
|
|
196
|
+
pvals_adj[idx] = sp.stats.t.sf(np.abs(tvalues_init_adj[idx]), df=df[idx]) * 2
|
|
197
|
+
else:
|
|
198
|
+
pvals_adj[idx] = sp.stats.norm.sf(np.abs(tvalues_init_adj[idx])) * 2
|
|
193
199
|
qvals_adj[idx] = multipletests(pvals_adj[idx], alpha=0.05, method='fdr_bh')[1]
|
|
194
200
|
|
|
195
201
|
return pvals, qvals, pvals_adj, qvals_adj
|