tigramite-fast 5.2.10.1__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.
Files changed (38) hide show
  1. tigramite/__init__.py +0 -0
  2. tigramite/causal_effects.py +1525 -0
  3. tigramite/causal_mediation.py +1592 -0
  4. tigramite/data_processing.py +1574 -0
  5. tigramite/graphs.py +1509 -0
  6. tigramite/independence_tests/LBFGS.py +1114 -0
  7. tigramite/independence_tests/__init__.py +0 -0
  8. tigramite/independence_tests/cmiknn.py +661 -0
  9. tigramite/independence_tests/cmiknn_mixed.py +1397 -0
  10. tigramite/independence_tests/cmisymb.py +286 -0
  11. tigramite/independence_tests/gpdc.py +664 -0
  12. tigramite/independence_tests/gpdc_torch.py +820 -0
  13. tigramite/independence_tests/gsquared.py +190 -0
  14. tigramite/independence_tests/independence_tests_base.py +1310 -0
  15. tigramite/independence_tests/oracle_conditional_independence.py +1582 -0
  16. tigramite/independence_tests/pairwise_CI.py +383 -0
  17. tigramite/independence_tests/parcorr.py +369 -0
  18. tigramite/independence_tests/parcorr_mult.py +485 -0
  19. tigramite/independence_tests/parcorr_wls.py +451 -0
  20. tigramite/independence_tests/regressionCI.py +403 -0
  21. tigramite/independence_tests/robust_parcorr.py +403 -0
  22. tigramite/jpcmciplus.py +966 -0
  23. tigramite/lpcmci.py +3649 -0
  24. tigramite/models.py +2257 -0
  25. tigramite/pcmci.py +3935 -0
  26. tigramite/pcmci_base.py +1218 -0
  27. tigramite/plotting.py +4735 -0
  28. tigramite/rpcmci.py +467 -0
  29. tigramite/toymodels/__init__.py +0 -0
  30. tigramite/toymodels/context_model.py +261 -0
  31. tigramite/toymodels/non_additive.py +1231 -0
  32. tigramite/toymodels/structural_causal_processes.py +1201 -0
  33. tigramite/toymodels/surrogate_generator.py +319 -0
  34. tigramite_fast-5.2.10.1.dist-info/METADATA +182 -0
  35. tigramite_fast-5.2.10.1.dist-info/RECORD +38 -0
  36. tigramite_fast-5.2.10.1.dist-info/WHEEL +5 -0
  37. tigramite_fast-5.2.10.1.dist-info/licenses/license.txt +621 -0
  38. tigramite_fast-5.2.10.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,383 @@
1
+ """Tigramite causal discovery for time series."""
2
+
3
+ # Author: Jakob Runge <jakob@jakob-runge.com>
4
+ #
5
+ # License: GNU General Public License v3.0
6
+
7
+ from __future__ import print_function
8
+ from scipy import stats
9
+ import numpy as np
10
+ import sys
11
+ import warnings
12
+
13
+ from tigramite.independence_tests.independence_tests_base import CondIndTest
14
+ from tigramite.independence_tests.parcorr import ParCorr
15
+
16
+ class PairwiseMultCI(CondIndTest):
17
+ r""" Multivariate CI-test that aggregates univariate tests
18
+
19
+ Basically, the algorithm consists of two main steps:
20
+
21
+ - Step 1: On the first part of the sample, conditional independencies of the form :math:`X_i \perp Y_j|Z`
22
+ are learned
23
+
24
+ - Step 2: On the second part of the sample, conditional independencies
25
+ :math:`X_i \perp Y_j|(Z, S_{ij})` are tested, where the set :math:`S_{ij}` consists of components
26
+ of :math:`X` that are independent of :math:`Y_j` given :math:`Z` (or components of :math:`Y` that
27
+ are independent of :math:`X_i` given :math:`Z`). Using the Bonferroni method, the univariate tests
28
+ are then aggregated.
29
+
30
+ The main reasoning behind this two-step procedure is that the conditional independence tests in the second step
31
+ have larger effect sizes. One can show, that in cases where the within-:math:`X` or within-:math:`Y` dependence
32
+ is large, this method outperforms naive pairwise independence testing (i.e., without having the sets :math:`S_{ij}`)
33
+
34
+ For the details, we refer to:
35
+
36
+ - Tom Hochsprung, Jonas Wahl*, Andreas Gerhardus*, Urmi Ninad*, and Jakob Runge.
37
+ Increasing Effect Sizes of Pairwise Conditional Independence Tests between Random Vectors. UAI2023, 2023.
38
+
39
+ Parameters
40
+ ----------
41
+
42
+ learn_augmented_cond_sets: boolean
43
+ Boolean on whether PairwiseMultCI should be executed with a pre step that learns conditional independencies
44
+ and then augments conditioning sets.
45
+ That is explained in the tutorial or the above mentioned paper in more detail.
46
+ False indicates that conditioning sets should not be increased
47
+
48
+ alpha_pre: float
49
+ Significance level for the first step of the algorithm.
50
+ If cond_ind_test is instantiated with significance = "fixed_thres",
51
+ then the value of alpha_pre is not used, and can, for example, be set to None
52
+
53
+ pre_step_sample_fraction: float
54
+ Relative size for the first part of the sample
55
+ (abbreviation for "size block one")
56
+
57
+ cond_ind_test: conditional independence test object
58
+ This can be ParCorr or other classes from
59
+ ``tigramite.independence_tests`` or an external test passed as a
60
+ callable. This test can be based on the class
61
+ tigramite.independence_tests.CondIndTest.
62
+
63
+ fixed_thres_pre: In case cond_ind_test or self is instantiated with significance
64
+ = "fixed_thres" (at least one such setting suffices), the pre_step works with a threshold instead of significance
65
+ level
66
+
67
+
68
+ **kwargs :
69
+ Arguments passed on to Parent class CondIndTest.
70
+ """
71
+
72
+ # documentation
73
+ @property
74
+ def measure(self):
75
+ """
76
+ Concrete property to return the measure of the independence test
77
+ """
78
+ return self._measure
79
+
80
+ def __init__(self, learn_augmented_cond_sets = False, cond_ind_test = ParCorr(), alpha_pre = 0.5, pre_step_sample_fraction = 0.2, fixed_thres_pre = None, **kwargs):
81
+ self._measure = 'pairwise_CI'
82
+ self.cond_ind_test = cond_ind_test
83
+ self.alpha_pre = alpha_pre
84
+ self.pre_step_sample_fraction = pre_step_sample_fraction
85
+ self.fixed_thres_pre = fixed_thres_pre
86
+ self.two_sided = cond_ind_test.two_sided
87
+ self.learn_augmented_cond_sets = learn_augmented_cond_sets
88
+ CondIndTest.__init__(self, **kwargs)
89
+
90
+
91
+ def calculate_dep_measure_and_significance(self, array, xyz, data_type = None, ci_test_thres = None):
92
+ """Return aggregated p-value of all univariate independence tests.
93
+
94
+ First, learns conditional independencies, uses these conditional independencies to have new conditional
95
+ independence tests with larger effect sizes.
96
+
97
+ Parameters
98
+ ----------
99
+ array : array-like
100
+ data array with X, Y, Z in rows and observations in columns
101
+
102
+ xyz : array of ints
103
+ XYZ identifier array of shape (dim,).
104
+
105
+ data_type: array of 0's and 1's, same dimensions as array
106
+ relevant, for example for the CI-test RegressionCI,
107
+ to indicate whether variables are discrete (=1) or
108
+ continuous (=0).
109
+
110
+
111
+ Returns
112
+ -------
113
+ pval : float
114
+ an aggregated p-value of all univariate tests.
115
+ """
116
+
117
+ fixed_thres_bool = False
118
+ if self.significance == "fixed_thres":
119
+ fixed_thres_bool = True
120
+ self.cond_ind_test.significance = "fixed_thres"
121
+ if self.cond_ind_test.significance == "fixed_thres":
122
+ fixed_thres_bool = True
123
+ self.significance = "fixed_thres"
124
+
125
+ if (fixed_thres_bool) and (self.fixed_thres_pre == None) and (self.learn_augmented_cond_sets == True):
126
+ raise ValueError("If significance == 'fixed_thres', fixed_thres_pre for the"
127
+ " pre-step needs to be defined in initializing PairwiseMultCI.")
128
+
129
+ if self.learn_augmented_cond_sets == False:
130
+ self.pre_step_sample_fraction = 0
131
+
132
+ x_indices = np.where(xyz == 0)[0]
133
+ y_indices = np.where(xyz == 1)[0]
134
+ z_indices = np.where(xyz == 2)[0]
135
+
136
+ dim_x = x_indices.shape[0]
137
+ dim_y = y_indices.shape[0]
138
+ # what if unconditional test ...
139
+ dim_z = z_indices.shape[0]
140
+ T = array.shape[1]
141
+ size_first_block = np.floor(self.pre_step_sample_fraction * T)
142
+ size_first_block = size_first_block.astype(int)
143
+
144
+ if size_first_block < 10:
145
+ self.pre_step_sample_fraction = 0
146
+
147
+
148
+ # split the sample
149
+ array_s1 = array[:, 0:size_first_block]
150
+ x_s1 = array_s1[x_indices]
151
+ y_s1 = array_s1[y_indices]
152
+ z_s1 = array_s1[z_indices]
153
+
154
+ array_s2 = array[:, size_first_block : T]
155
+ x_s2 = array_s2[x_indices]
156
+ y_s2 = array_s2[y_indices]
157
+ z_s2 = array_s2[z_indices]
158
+
159
+ if data_type is not None:
160
+ x_type = data_type[x_indices, :].T
161
+ y_type = data_type[y_indices, :].T
162
+ z_type = data_type[z_indices, :].T
163
+ else:
164
+ x_type = None
165
+ y_type = None
166
+ z_type = None
167
+ if x_type is not None:
168
+ x_type_s1 = x_type[0:size_first_block, :]
169
+ x_type_s2 = x_type[size_first_block : T, :]
170
+ else:
171
+ x_type_s1 = None
172
+ x_type_s2 = None
173
+ if y_type is not None:
174
+ y_type_s1 = y_type[0:size_first_block, :]
175
+ y_type_s2 = y_type[size_first_block : T, :]
176
+ else:
177
+ y_type_s1 = None
178
+ y_type_s2 = None
179
+ if z_type is not None:
180
+ z_type_s1 = z_type[0:size_first_block, :]
181
+ z_type_s2 = z_type[size_first_block: T, :]
182
+ else:
183
+ z_type_s1 = None
184
+ z_type_s2 = None
185
+
186
+ ## Step 1: estimate conditional independencies
187
+ if self.pre_step_sample_fraction > 0:
188
+ if fixed_thres_bool == False:
189
+ p_vals_pre = np.zeros((dim_x, dim_y))
190
+ else:
191
+ vals_pre = np.zeros((dim_x, dim_y))
192
+ for j in np.arange(0, dim_x):
193
+ for jj in np.arange(0, dim_y):
194
+ if fixed_thres_bool == False:
195
+ p_vals_pre[j, jj] = self.cond_ind_test.run_test_raw(x_s1[j].reshape(size_first_block, 1),
196
+ y_s1[jj].reshape(size_first_block, 1),
197
+ z_s1.T,
198
+ x_type = x_type_s1,
199
+ y_type = y_type_s1,
200
+ z_type = z_type_s1)[1]
201
+ else:
202
+ vals_pre[j, jj] = self.cond_ind_test.run_test_raw(x_s1[j].reshape(size_first_block, 1),
203
+ y_s1[jj].reshape(size_first_block, 1),
204
+ z_s1.T,
205
+ x_type = x_type_s1,
206
+ y_type = y_type_s1,
207
+ z_type = z_type_s1,
208
+ alpha_or_thres=999.)[0] # just a dummy
209
+ if fixed_thres_bool == False:
210
+ indep_set = np.where(p_vals_pre > self.alpha_pre)
211
+ else:
212
+ indep_set = np.where(np.abs(vals_pre) >= self.fixed_thres_pre)
213
+ else:
214
+ indep_set = np.where(np.zeros((dim_x, dim_y)) > np.zeros((dim_x, dim_y)))
215
+
216
+ # Step 2: test conditional independencies with increased effect sizes
217
+ if self.cond_ind_test.significance != "fixed_thres":
218
+ p_vals_main = np.zeros((dim_x, dim_y))
219
+ else:
220
+ dependent_main = np.zeros((dim_x, dim_y))
221
+ test_stats_main = np.zeros((dim_x, dim_y))
222
+
223
+ for j in np.arange(0, dim_x):
224
+ for jj in np.arange(0, dim_y):
225
+ indicesY = np.zeros(0)
226
+ indicesX = np.zeros(0)
227
+
228
+ if (j in indep_set[0]):
229
+ indicesX_locs = np.where(indep_set[0] == j)
230
+ indicesY = np.setdiff1d(indep_set[1][indicesX_locs], jj)
231
+ if (jj in indep_set[1]):
232
+ indicesY_locs = np.where(indep_set[1] == jj)
233
+ indicesX = np.setdiff1d(indep_set[0][indicesY_locs], j)
234
+ lix = indicesX.shape[0]
235
+ liy = indicesY.shape[0]
236
+
237
+ if lix + liy > 0:
238
+ if (lix > liy):
239
+ if x_type_s2 is not None:
240
+ z_type = np.hstack((z_type_s2, x_type_s2[:, indicesX]))
241
+ if fixed_thres_bool == False:
242
+ test_result = self.cond_ind_test.run_test_raw(x_s2[j].reshape(T - size_first_block, 1),
243
+ y_s2[jj].reshape(T - size_first_block, 1),
244
+ np.hstack((z_s2.T,
245
+ x_s2[indicesX].T)),
246
+ x_type = x_type_s2,
247
+ y_type = y_type_s2,
248
+ z_type = z_type_s2)
249
+ else:
250
+ test_result = self.cond_ind_test.run_test_raw(x_s2[j].reshape(T - size_first_block, 1),
251
+ y_s2[jj].reshape(T - size_first_block, 1),
252
+ np.hstack((z_s2.T,
253
+ x_s2[indicesX].T)),
254
+ x_type = x_type_s2,
255
+ y_type = y_type_s2,
256
+ z_type = z_type_s2,
257
+ alpha_or_thres=999.) # just a dummy
258
+ elif (lix <= liy):
259
+ if y_type_s2 is not None:
260
+ z_type_s2 = np.hstack((z_type_s2, y_type_s2[:, indicesY]))
261
+ if fixed_thres_bool == False:
262
+ test_result = self.cond_ind_test.run_test_raw(x_s2[j].reshape(T - size_first_block, 1),
263
+ y_s2[jj].reshape(T - size_first_block, 1),
264
+ np.hstack((z_s2.T,
265
+ y_s2[indicesY].T)),
266
+ x_type = x_type_s2,
267
+ y_type = y_type_s2,
268
+ z_type = z_type_s2)
269
+ else:
270
+ test_result = self.cond_ind_test.run_test_raw(x_s2[j].reshape(T - size_first_block, 1),
271
+ y_s2[jj].reshape(T - size_first_block, 1),
272
+ np.hstack((z_s2.T,
273
+ y_s2[indicesY].T)),
274
+ x_type = x_type_s2,
275
+ y_type = y_type_s2,
276
+ z_type = z_type_s2,
277
+ alpha_or_thres=999.) # just a dummy
278
+
279
+ else:
280
+ if fixed_thres_bool == False:
281
+ test_result = self.cond_ind_test.run_test_raw(x_s2[j].reshape(T - size_first_block, 1),
282
+ y_s2[jj].reshape(T - size_first_block, 1),
283
+ z_s2.T,
284
+ x_type = x_type_s2,
285
+ y_type = y_type_s2,
286
+ z_type = z_type_s2)
287
+
288
+ else:
289
+ test_result = self.cond_ind_test.run_test_raw(x_s2[j].reshape(T - size_first_block, 1),
290
+ y_s2[jj].reshape(T - size_first_block, 1),
291
+ z_s2.T,
292
+ x_type = x_type_s2,
293
+ y_type = y_type_s2,
294
+ z_type = z_type_s2,
295
+ alpha_or_thres=999.) # just a dummy
296
+
297
+ test_stats_main[j, jj] = test_result[0]
298
+ if fixed_thres_bool == False:
299
+ p_vals_main[j, jj] = test_result[1]
300
+
301
+
302
+ # Aggregate p-values
303
+ max_abs_test_stat = np.max(np.abs(test_stats_main))
304
+ pos_max = np.where(np.abs(test_stats_main) == max_abs_test_stat)
305
+ test_stats_aggregated = test_stats_main[pos_max[0], pos_max[1]][0]
306
+
307
+ if self.cond_ind_test.significance != "fixed_thres":
308
+ p_aggregated = np.min(np.array([np.min(p_vals_main) * dim_x * dim_y, 1]))
309
+ else:
310
+ p_aggregated = None
311
+
312
+ return test_stats_aggregated, p_aggregated
313
+
314
+
315
+ def get_dependence_measure(self, array, xyz, data_type=None, ci_test_thres = None):
316
+
317
+ self.dep_measure, self.signif = self.calculate_dep_measure_and_significance(array = array, xyz = xyz, data_type = data_type, ci_test_thres = ci_test_thres)
318
+
319
+ return self.dep_measure
320
+
321
+ def get_analytic_significance(self, value = None, T = None, dim = None, xyz = None, data_type=None):
322
+
323
+ return self.signif
324
+
325
+ if __name__ == '__main__':
326
+
327
+ import tigramite
328
+ from tigramite.data_processing import DataFrame
329
+ import tigramite.data_processing as pp
330
+ import numpy as np
331
+ from tigramite.independence_tests.robust_parcorr import RobustParCorr
332
+ from tigramite.independence_tests.cmiknn import CMIknn
333
+ alpha = 0.05
334
+ #np.random.seed(seed = 123)
335
+ ci = PairwiseMultCI(cond_ind_test = RobustParCorr())
336
+ ci2 = RobustParCorr()
337
+ T = 100
338
+
339
+ z1 = np.random.normal(0, 1, T).reshape(T, 1)
340
+ z2 = np.random.normal(0, 1, T).reshape(T, 1)
341
+ z3 = np.random.normal(0, 1, T).reshape(T, 1)
342
+ z4 = np.random.normal(0, 1, T).reshape(T, 1)
343
+ z5 = np.random.normal(0, 1, T).reshape(T, 1)
344
+ z6 = np.random.normal(0, 1, T).reshape(T, 1)
345
+ x = np.random.normal(0, 1, T).reshape(T, 1) + z1 + z2
346
+ y = np.random.normal(0, 1, T).reshape(T, 1) + z1 + z2
347
+
348
+ #print(x)
349
+ #print(np.hstack((z1, z2, z3, z4, z5, z6)))
350
+ print("start")
351
+ print(ci.run_test_raw(x, y, np.hstack((z1, z2, z3, z4, z5, z6))))
352
+ print(ci2.run_test_raw(x, y, np.hstack((z1, z2, z3, z4, z5, z6))))
353
+ print("end")
354
+
355
+ #ci = PairwiseMultCI(cond_ind_test=RobustParCorr(significance = "fixed_thres"), fixed_thres_pre = 0.3, learn_augmented_cond_sets= True)
356
+ # ci = PairwiseMultCI(cond_ind_test=ParCorr(significance="fixed_thres"))
357
+ # ci = PairwiseMultCI(cond_ind_test=ParCorr(significance="analytic"))
358
+ T = 100
359
+ reals = 1
360
+ rate = np.zeros(reals)
361
+ #np.random.seed(1203)
362
+ '''
363
+ for t in range(reals):
364
+ # continuous example
365
+ x1 = np.random.normal(0, 1, T).reshape(T, 1)
366
+ x2 = np.random.normal(0, 1, T).reshape(T, 1)
367
+ y1 = np.random.normal(0, 1, T).reshape(T, 1)
368
+ y2 = y1 + 0.3 * np.random.normal(0, 1, T).reshape(T, 1)
369
+ z = np.random.normal(0, 1, T).reshape(T, 1)
370
+ # discrete example
371
+ #x = np.random.binomial(n=10, p=0.5, size=T).reshape(T, 1)
372
+ #y1 = np.random.binomial(n=10, p=0.5, size=T).reshape(T, 1)
373
+ #y2 = np.random.binomial(n=10, p=0.5, size=T).reshape(T, 1) + x + y1
374
+ # z = np.random.binomial(n=10, p=0.5, size=T).reshape(T, 1)
375
+
376
+ test_stat, pval, dependent = ci.run_test_raw(x = np.hstack((x1,x2)), y = np.hstack((y1,y2)), z = z, alpha_or_thres=0.9)#, alpha_or_thres=0.9)#, z = z, alpha_pre = 0.5, pre_step_sample_fraction = 0.2, cond_ind_test = base_ci)# , x_type = np.ones((T, 1)), y_type = np.ones((T, 2)) , z_type = np.zeros((T, 1)))
377
+ print(dependent)
378
+ if (pval <= alpha):
379
+ rate[t] = 1
380
+ print("test_stat ", test_stat)
381
+ print("pval ", pval)
382
+ print(np.mean(rate))
383
+ '''