Skip to content

Commit 39f579d

Browse files
authored
[FIX] concordant z values (#125)
* have directional z-values * modify tests * remove unused import * remove comments
1 parent eb67d0b commit 39f579d

File tree

2 files changed

+16
-17
lines changed

2 files changed

+16
-17
lines changed

Diff for: pymare/estimators/combination.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,15 @@ def fit(self, z, *args, **kwargs):
4545
p1 = ose.p_value(z, *args, **kwargs)
4646
p2 = ose.p_value(-z, *args, **kwargs)
4747
p = np.minimum(1, 2 * np.minimum(p1, p2))
48+
z_calc = ss.norm.isf(p)
49+
z_calc[p2 < p1] *= -1
4850
else:
4951
if self.mode == "undirected":
5052
z = np.abs(z)
5153
p = self.p_value(z, *args, **kwargs)
52-
self.params_ = {"p": p}
54+
z_calc = ss.norm.isf(p)
55+
56+
self.params_ = {"p": p, "z": z_calc}
5357
return self
5458

5559
def summary(self):
@@ -60,7 +64,9 @@ def summary(self):
6064
"This {} instance hasn't been fitted yet. Please "
6165
"call fit() before summary().".format(name)
6266
)
63-
return CombinationTestResults(self, self.dataset_, p=self.params_["p"])
67+
return CombinationTestResults(
68+
self, self.dataset_, z=self.params_["z"], p=self.params_["p"]
69+
)
6470

6571

6672
class StoufferCombinationTest(CombinationTest):

Diff for: pymare/tests/test_combination_tests.py

+8-15
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import numpy as np
44
import pytest
5-
import scipy.stats as ss
65

76
from pymare import Dataset
87
from pymare.estimators import FisherCombinationTest, StoufferCombinationTest
@@ -16,22 +15,21 @@
1615
(StoufferCombinationTest, _z1, "concordant", [4.55204117]),
1716
(StoufferCombinationTest, _z2, "directed", [4.69574275, -4.16803071]),
1817
(StoufferCombinationTest, _z2, "undirected", [4.87462819, 4.16803071]),
19-
(StoufferCombinationTest, _z2, "concordant", [4.55204117, 4.00717817]),
18+
(StoufferCombinationTest, _z2, "concordant", [4.55204117, -4.00717817]),
2019
(FisherCombinationTest, _z1, "directed", [5.22413541]),
2120
(FisherCombinationTest, _z1, "undirected", [5.27449962]),
2221
(FisherCombinationTest, _z1, "concordant", [5.09434911]),
2322
(FisherCombinationTest, _z2, "directed", [5.22413541, -3.30626405]),
2423
(FisherCombinationTest, _z2, "undirected", [5.27449962, 4.27572965]),
25-
(FisherCombinationTest, _z2, "concordant", [5.09434911, 4.11869468]),
24+
(FisherCombinationTest, _z2, "concordant", [5.09434911, -4.11869468]),
2625
]
2726

2827

2928
@pytest.mark.parametrize("Cls,data,mode,expected", _params)
3029
def test_combination_test(Cls, data, mode, expected):
3130
"""Test CombinationTest Estimators with numpy data."""
3231
results = Cls(mode).fit(data).params_
33-
z = ss.norm.isf(results["p"])
34-
assert np.allclose(z, expected, atol=1e-5)
32+
assert np.allclose(results["z"], expected, atol=1e-5)
3533

3634

3735
@pytest.mark.parametrize("Cls,data,mode,expected", _params)
@@ -40,8 +38,7 @@ def test_combination_test_from_dataset(Cls, data, mode, expected):
4038
dset = Dataset(y=data)
4139
est = Cls(mode).fit_dataset(dset)
4240
results = est.summary()
43-
z = ss.norm.isf(results.p)
44-
assert np.allclose(z, expected, atol=1e-5)
41+
assert np.allclose(results.z, expected, atol=1e-5)
4542

4643

4744
def test_stouffer_adjusted():
@@ -61,10 +58,9 @@ def test_stouffer_adjusted():
6158
groups = np.tile(np.array([0, 0, 1, 2, 2, 2]), (data.shape[1], 1)).T
6259

6360
results = StoufferCombinationTest("directed").fit(z=data, w=weights, g=groups).params_
64-
z = ss.norm.isf(results["p"])
6561

6662
z_expected = np.array([5.00088912, 3.70356943, 4.05465924, 5.4633001, 5.18927878])
67-
assert np.allclose(z, z_expected, atol=1e-5)
63+
assert np.allclose(results["z"], z_expected, atol=1e-5)
6864

6965
# Test with weights and no groups. Limiting cases.
7066
# Limiting case 1: all correlations are one.
@@ -74,22 +70,20 @@ def test_stouffer_adjusted():
7470
groups_l1 = np.tile(np.array([0, 0, 0, 0, 0]), (data_l1.shape[1], 1)).T
7571

7672
results_l1 = StoufferCombinationTest("directed").fit(z=data_l1, g=groups_l1).params_
77-
z_l1 = ss.norm.isf(results_l1["p"])
7873

7974
sigma_l1 = n_maps_l1 * (n_maps_l1 - 1) # Expected inflation term
8075
z_expected_l1 = n_maps_l1 * common_sample / np.sqrt(n_maps_l1 + sigma_l1)
81-
assert np.allclose(z_l1, z_expected_l1, atol=1e-5)
76+
assert np.allclose(results_l1["z"], z_expected_l1, atol=1e-5)
8277

8378
# Test with correlation matrix and groups.
8479
data_corr = data - data.mean(0)
8580
corr = np.corrcoef(data_corr, rowvar=True)
8681
results_corr = (
8782
StoufferCombinationTest("directed").fit(z=data, w=weights, g=groups, corr=corr).params_
8883
)
89-
z_corr = ss.norm.isf(results_corr["p"])
9084

9185
z_corr_expected = np.array([5.00088912, 3.70356943, 4.05465924, 5.4633001, 5.18927878])
92-
assert np.allclose(z_corr, z_corr_expected, atol=1e-5)
86+
assert np.allclose(results_corr["z"], z_corr_expected, atol=1e-5)
9387

9488
# Test with no correlation matrix and groups, but only one feature.
9589
with pytest.raises(ValueError):
@@ -101,6 +95,5 @@ def test_stouffer_adjusted():
10195

10296
# Test with correlation matrix and no groups.
10397
results1 = StoufferCombinationTest("directed").fit(z=_z1, corr=corr).params_
104-
z1 = ss.norm.isf(results1["p"])
10598

106-
assert np.allclose(z1, [4.69574], atol=1e-5)
99+
assert np.allclose(results1["z"], [4.69574], atol=1e-5)

0 commit comments

Comments
 (0)