causarray 0.0.1__py3-none-any.whl → 0.0.2__py3-none-any.whl
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/DR_estimation.py +5 -4
- causarray/DR_learner.py +1 -0
- causarray/__about__.py +1 -1
- causarray/gcate_glm.py +24 -13
- {causarray-0.0.1.dist-info → causarray-0.0.2.dist-info}/METADATA +42 -8
- causarray-0.0.2.dist-info/RECORD +14 -0
- causarray-0.0.1.dist-info/RECORD +0 -14
- {causarray-0.0.1.dist-info → causarray-0.0.2.dist-info}/WHEEL +0 -0
- {causarray-0.0.1.dist-info → causarray-0.0.2.dist-info}/licenses/LICENSE +0 -0
causarray/DR_estimation.py
CHANGED
|
@@ -69,8 +69,8 @@ def cross_fitting(
|
|
|
69
69
|
pi_hat : array
|
|
70
70
|
Estimated propensity score.
|
|
71
71
|
'''
|
|
72
|
-
func_ps, params_ps = _get_func_ps(ps_model, **kwargs)
|
|
73
|
-
params_glm = _filter_params(fit_glm, kwargs)
|
|
72
|
+
func_ps, params_ps = _get_func_ps(ps_model, verbose=verbose, **kwargs)
|
|
73
|
+
params_glm = _filter_params(fit_glm, {**kwargs, 'verbose': verbose})
|
|
74
74
|
|
|
75
75
|
if verbose:
|
|
76
76
|
pprint.pprint(params_ps)
|
|
@@ -97,6 +97,7 @@ def cross_fitting(
|
|
|
97
97
|
Y_train, Y_test = Y[train_index], Y[test_index]
|
|
98
98
|
|
|
99
99
|
if fit_pi:
|
|
100
|
+
if verbose: pprint.pprint('Fit propensity score models...')
|
|
100
101
|
i_ctrl = (np.sum(A_train, axis=1) == 0.)
|
|
101
102
|
|
|
102
103
|
pi = np.zeros_like(A_test, dtype=float)
|
|
@@ -111,13 +112,13 @@ def cross_fitting(
|
|
|
111
112
|
else:
|
|
112
113
|
pi[:,j] = func_ps(XA_train[i_cells], A_train[i_cells][:,j], XA_test)
|
|
113
114
|
|
|
115
|
+
if verbose: pprint.pprint('Fit outcome models...')
|
|
114
116
|
# Fit GLM on training data and predict on test data
|
|
115
117
|
res = fit_glm(Y_train, X_train, A_train, family=family, alpha=glm_alpha,
|
|
116
118
|
impute=X_test, **params_glm)
|
|
117
119
|
|
|
118
120
|
# Store results
|
|
119
|
-
if fit_pi:
|
|
120
|
-
pi_hat[test_index] = pi
|
|
121
|
+
if fit_pi: pi_hat[test_index] = pi
|
|
121
122
|
|
|
122
123
|
Y_hat[test_index,:,:,0] = res[1][0]
|
|
123
124
|
Y_hat[test_index,:,:,1] = res[1][1]
|
causarray/DR_learner.py
CHANGED
|
@@ -109,6 +109,7 @@ def compute_causal_estimand(
|
|
|
109
109
|
Y_hat=Y_hat, pi_hat=pi_hat, random_state=random_state, verbose=verbose, **kwargs)
|
|
110
110
|
pi_hat = pi_hat.reshape(*A.shape)
|
|
111
111
|
|
|
112
|
+
if verbose: pprint.pprint('Estimating AIPW mean...')
|
|
112
113
|
# point estimation of the treatment effect
|
|
113
114
|
_, etas = AIPW_mean(Y, np.stack([1-A, A], axis=-1),
|
|
114
115
|
Y_hat, np.stack([1-pi_hat, pi_hat], axis=-1), positive=True)
|
causarray/__about__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.0.
|
|
1
|
+
__version__ = "0.0.2"
|
causarray/gcate_glm.py
CHANGED
|
@@ -49,13 +49,26 @@ def fit_glm(Y, X, A=None, family='gaussian', disp_family='poisson',
|
|
|
49
49
|
impute : bool
|
|
50
50
|
whether to impute potential outcomes and get predicted values
|
|
51
51
|
offset : bool
|
|
52
|
-
whether to use log of sum of Y as offset
|
|
52
|
+
whether to use log of sum of Y as offset
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
B : array
|
|
57
|
+
d x p matrix of coefficients
|
|
58
|
+
Yhat : array
|
|
59
|
+
n x p x a matrix of predicted values
|
|
60
|
+
disp_glm : array
|
|
61
|
+
p x 1 vector of dispersion parameters
|
|
62
|
+
offsets : array
|
|
63
|
+
n x 1 vector of offsets
|
|
64
|
+
resid_deviance : array
|
|
65
|
+
n x p matrix of deviance residuals
|
|
53
66
|
'''
|
|
54
67
|
np.random.seed(random_state)
|
|
55
68
|
|
|
56
69
|
if family not in ['gaussian', 'poisson', 'nb']:
|
|
57
70
|
raise ValueError('Family not recognized')
|
|
58
|
-
|
|
71
|
+
|
|
59
72
|
d = X.shape[1]
|
|
60
73
|
|
|
61
74
|
if A is None:
|
|
@@ -70,8 +83,6 @@ def fit_glm(Y, X, A=None, family='gaussian', disp_family='poisson',
|
|
|
70
83
|
X_test = X
|
|
71
84
|
X_test = np.c_[X,np.zeros_like(A)]
|
|
72
85
|
X = np.c_[X,A]
|
|
73
|
-
# X_test = X.copy()
|
|
74
|
-
|
|
75
86
|
a = A.shape[1]
|
|
76
87
|
|
|
77
88
|
if offset is not None and offset is not False:
|
|
@@ -90,7 +101,7 @@ def fit_glm(Y, X, A=None, family='gaussian', disp_family='poisson',
|
|
|
90
101
|
pprint.pprint('Fitting {} GLM{}...'.format(family, '' if offsets is None else ' with offset'))
|
|
91
102
|
is_constant = np.all(X == X[0, :], axis=0)
|
|
92
103
|
alpha[is_constant] = 0
|
|
93
|
-
|
|
104
|
+
|
|
94
105
|
|
|
95
106
|
families = {
|
|
96
107
|
'gaussian': lambda disp: sm.families.Gaussian(),
|
|
@@ -122,11 +133,11 @@ def fit_glm(Y, X, A=None, family='gaussian', disp_family='poisson',
|
|
|
122
133
|
Yhat_0 = np.zeros((Y.shape[0], a))
|
|
123
134
|
Yhat_1 = np.zeros((Y.shape[0], a))
|
|
124
135
|
if impute is not False:
|
|
125
|
-
for
|
|
136
|
+
for k in range(a):
|
|
126
137
|
X_test_copy = X_test.copy()
|
|
127
|
-
Yhat_0[:,
|
|
128
|
-
X_test_copy[:, d+
|
|
129
|
-
Yhat_1[:,
|
|
138
|
+
Yhat_0[:,k] = mod.predict(X_test_copy, offset=offsets)
|
|
139
|
+
X_test_copy[:, d+k] = 1
|
|
140
|
+
Yhat_1[:,k] = mod.predict(X_test_copy, offset=offsets)
|
|
130
141
|
else:
|
|
131
142
|
Yhat_0[:,:] = Yhat_1[:,:] = mod.predict(X, offset=offsets).reshape(-1, a)
|
|
132
143
|
|
|
@@ -146,9 +157,11 @@ def fit_glm(Y, X, A=None, family='gaussian', disp_family='poisson',
|
|
|
146
157
|
|
|
147
158
|
results = Parallel(n_jobs=n_jobs)(delayed(fit_model)(
|
|
148
159
|
j, Y, X, offsets, family, disp_glm, impute, alpha) for j in tqdm(range(Y.shape[1])))
|
|
160
|
+
pprint.pprint('Fitting GLM done.')
|
|
161
|
+
if verbose: pprint.pprint('Fitting GLM done.')
|
|
149
162
|
|
|
150
163
|
B, Yhat_0, Yhat_1, resid_deviance = zip(*results)
|
|
151
|
-
B = np.array(B)
|
|
164
|
+
B = np.array(B)
|
|
152
165
|
Yhat_0 = np.array(Yhat_0).transpose(1, 0, 2)
|
|
153
166
|
Yhat_1 = np.array(Yhat_1).transpose(1, 0, 2)
|
|
154
167
|
resid_deviance = np.array(resid_deviance).T
|
|
@@ -171,7 +184,6 @@ def estimate_disp(Y, X=None, A=None, Y_hat=None, disp_family='gaussian', offset=
|
|
|
171
184
|
else:
|
|
172
185
|
offsets = None
|
|
173
186
|
sf = 1.
|
|
174
|
-
|
|
175
187
|
|
|
176
188
|
if Y_hat is None:
|
|
177
189
|
if verbose:
|
|
@@ -183,8 +195,7 @@ def estimate_disp(Y, X=None, A=None, Y_hat=None, disp_family='gaussian', offset=
|
|
|
183
195
|
if disp_family=='gaussian':
|
|
184
196
|
Y_norm = Y/sf
|
|
185
197
|
reg = LinearRegression(fit_intercept=False).fit(X, Y_norm)
|
|
186
|
-
Y_hat = reg.predict(X)
|
|
187
|
-
# Y_hat = np.clip(Y_hat, 0, 1) * sf
|
|
198
|
+
Y_hat = reg.predict(X)
|
|
188
199
|
elif disp_family=='poisson':
|
|
189
200
|
Y_hat = fit_glm(Y, X, None, offset=offsets, family='poisson', impute=False, **kwargs)[1]
|
|
190
201
|
Y_hat /= sf
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: causarray
|
|
3
|
-
Version: 0.0.
|
|
4
|
-
Summary: causarray is a Python module for
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: causarray is a Python module for simultaneous causal inference with an array of outcomes.
|
|
5
5
|
Author-email: Jin-Hong Du <jinhongd@andrew.cmu.com>, Maya Shen <myshen@andrew.cmu.edu>, Hansruedi Mathys <mathysh@pitt.edu>, Kathryn Roeder <jinhongd@andrew.cmu.com>
|
|
6
6
|
Maintainer-email: Jin-Hong Du <jinhongd@andrew.cmu.com>
|
|
7
7
|
License: MIT License
|
|
@@ -23,25 +23,55 @@ Requires-Dist: statsmodels
|
|
|
23
23
|
Requires-Dist: tqdm
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
|
|
26
|
+
[](https://causarray.readthedocs.io/en/latest/?badge=latest)
|
|
27
|
+
[](https://pypi.org/project/causarray)
|
|
28
|
+
[](https://pepy.tech/project/causarray)
|
|
29
|
+
|
|
30
|
+
|
|
26
31
|
# causarray
|
|
27
32
|
|
|
28
33
|
Advances in single-cell sequencing and CRISPR technologies have enabled detailed case-control comparisons and experimental perturbations at single-cell resolution. However, uncovering causal relationships in observational genomic data remains challenging due to selection bias and inadequate adjustment for unmeasured confounders, particularly in heterogeneous datasets. To address these challenges, we introduce `causarray` [Du25], a doubly robust causal inference framework for analyzing array-based genomic data at both bulk-cell and single-cell levels. `causarray` integrates a generalized confounder adjustment method to account for unmeasured confounders and employs semiparametric inference with flexible machine learning techniques to ensure robust statistical estimation of treatment effects.
|
|
29
34
|
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
## Usage
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
We recommend using `causarray` in a conda environment:
|
|
39
|
+
```cmd
|
|
40
|
+
# create a new conda environment and install the necessary packages
|
|
41
|
+
conda create -n causarray python=3.12 -y
|
|
42
|
+
|
|
43
|
+
# activate the environment
|
|
44
|
+
conda activate causarray
|
|
45
|
+
```
|
|
34
46
|
|
|
47
|
+
The module can be installed via PyPI:
|
|
35
48
|
```cmd
|
|
36
|
-
|
|
49
|
+
pip install causarray
|
|
37
50
|
```
|
|
38
51
|
|
|
52
|
+
For `R` users, `reticulate` can be used to call `causarray` from `R`.
|
|
53
|
+
The documentation and tutorials using both `Python` and `R` are available at [causarray.readthedocs.io](https://causarray.readthedocs.io/en/latest/).
|
|
54
|
+
|
|
55
|
+
|
|
39
56
|
|
|
57
|
+
## Logs
|
|
58
|
+
|
|
59
|
+
- [x] (2025-01-30) Python package released on PyPI
|
|
60
|
+
- [x] (2025-02-01) code for reproducing figures in paper
|
|
61
|
+
- [x] (2025-02-02) Tutorial for Python and R
|
|
62
|
+
- [ ] Documentation
|
|
40
63
|
|
|
41
64
|
|
|
42
65
|
<!--
|
|
43
66
|
# Development
|
|
44
67
|
|
|
68
|
+
The dependencies for running `causarray` method are listed in `environment.yml` and can be installed by running
|
|
69
|
+
|
|
70
|
+
```cmd
|
|
71
|
+
PIP_NO_DEPS=1 conda env create -f environment.yml
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
|
|
45
75
|
## Build
|
|
46
76
|
```cmd
|
|
47
77
|
git tag 0.0.0
|
|
@@ -59,12 +89,16 @@ python -m pytest tests/test_DR_learner.py
|
|
|
59
89
|
|
|
60
90
|
```cmd
|
|
61
91
|
mkdir docs
|
|
62
|
-
sphinx-quickstart
|
|
63
92
|
cd docs
|
|
93
|
+
sphinx-quickstart
|
|
94
|
+
|
|
64
95
|
make html # sphinx-build source build
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
rmarkdown::render("perturbseq.Rmd", rmarkdown::md_document(variant = "markdown_github"))
|
|
65
99
|
```
|
|
66
100
|
-->
|
|
67
101
|
|
|
68
102
|
|
|
69
|
-
|
|
70
|
-
[Du25] Jin-Hong Du, Maya Shen, Hansruedi Mathys, and Kathryn Roeder (2025). Causal differential expression analysis under unmeasured confounders with causarray. bioRxiv, 2025-01.
|
|
103
|
+
## References
|
|
104
|
+
[Du25] Jin-Hong Du, Maya Shen, Hansruedi Mathys, and Kathryn Roeder (2025). Causal differential expression analysis under unmeasured confounders with causarray. bioRxiv, 2025-01.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
causarray/DR_estimation.py,sha256=DqlrFEDj7RtAIUAqUf_6nXA2PRyk8qnouBjFzzIDxmo,9210
|
|
2
|
+
causarray/DR_inference.py,sha256=0r5qxXTgvw-49ItP5TePC7KCDu4b8XrzgnlJfVWRcZo,5323
|
|
3
|
+
causarray/DR_learner.py,sha256=4C1bAXr1L_yf8ZDqHMg40mkuQGqodSekqq6GjfqShAU,9461
|
|
4
|
+
causarray/__about__.py,sha256=QvlVh4JTl3JL7jQAja76yKtT-IvF4631ASjWY1wS6AQ,22
|
|
5
|
+
causarray/__init__.py,sha256=bTyCz9EY3NVccFb472w7gqMxrmidBsxHZjlsfMawPsk,657
|
|
6
|
+
causarray/gcate.py,sha256=pnx8O-OnJl6VDjCF1RkgCuruQJVymTrGljc1V0jnRsc,8478
|
|
7
|
+
causarray/gcate_glm.py,sha256=bqDEGjw9K089RA1ynrl_QbLgynKrl1VVMTKlf3wbS7Y,9213
|
|
8
|
+
causarray/gcate_likelihood.py,sha256=srs2ql2uEhgn386w1lES41E_Gb0EKHT5YDIW-25YDec,4797
|
|
9
|
+
causarray/gcate_opt.py,sha256=w3KWQiBfwek1O8uslFXPoDBol3XWj0U2yBYZ4WmMJxM,10589
|
|
10
|
+
causarray/utils.py,sha256=fTrah_QX1C6FF6p2i-O1Y9_tljdjYcmxLkWE0tCbrJU,6765
|
|
11
|
+
causarray-0.0.2.dist-info/METADATA,sha256=oBmoweLK43F9CaLag5c-c4GTWUSneRZRdY0tjoK2GaU,3547
|
|
12
|
+
causarray-0.0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
13
|
+
causarray-0.0.2.dist-info/licenses/LICENSE,sha256=4zFElAgYMtL4dKsu0A1p70cEo2SXRsGEWmJFdFb2hNg,1067
|
|
14
|
+
causarray-0.0.2.dist-info/RECORD,,
|
causarray-0.0.1.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
causarray/DR_estimation.py,sha256=wc8jsz1XjsXX5Vp6grbwvEYV8j1MHB-VA70wYbyYUEw,9050
|
|
2
|
-
causarray/DR_inference.py,sha256=0r5qxXTgvw-49ItP5TePC7KCDu4b8XrzgnlJfVWRcZo,5323
|
|
3
|
-
causarray/DR_learner.py,sha256=DdgGbVmvNbF-TulF5XGMvf5mf7Exd2uPPOoBeyRf4Ug,9404
|
|
4
|
-
causarray/__about__.py,sha256=sXLh7g3KC4QCFxcZGBTpG2scR7hmmBsMjq6LqRptkRg,22
|
|
5
|
-
causarray/__init__.py,sha256=bTyCz9EY3NVccFb472w7gqMxrmidBsxHZjlsfMawPsk,657
|
|
6
|
-
causarray/gcate.py,sha256=pnx8O-OnJl6VDjCF1RkgCuruQJVymTrGljc1V0jnRsc,8478
|
|
7
|
-
causarray/gcate_glm.py,sha256=lpVvsH2lDsmxvqzrXA9sbRf7bZed4of_rtM10eZHE2s,8956
|
|
8
|
-
causarray/gcate_likelihood.py,sha256=srs2ql2uEhgn386w1lES41E_Gb0EKHT5YDIW-25YDec,4797
|
|
9
|
-
causarray/gcate_opt.py,sha256=w3KWQiBfwek1O8uslFXPoDBol3XWj0U2yBYZ4WmMJxM,10589
|
|
10
|
-
causarray/utils.py,sha256=fTrah_QX1C6FF6p2i-O1Y9_tljdjYcmxLkWE0tCbrJU,6765
|
|
11
|
-
causarray-0.0.1.dist-info/METADATA,sha256=AoarxDPfvp0qQv1PSSkRwZsNGaEfcPTn0lj6DJ1SirY,2425
|
|
12
|
-
causarray-0.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
13
|
-
causarray-0.0.1.dist-info/licenses/LICENSE,sha256=4zFElAgYMtL4dKsu0A1p70cEo2SXRsGEWmJFdFb2hNg,1067
|
|
14
|
-
causarray-0.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|