nimare 0.4.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.
- benchmarks/__init__.py +0 -0
- benchmarks/bench_cbma.py +57 -0
- nimare/__init__.py +45 -0
- nimare/_version.py +21 -0
- nimare/annotate/__init__.py +21 -0
- nimare/annotate/cogat.py +213 -0
- nimare/annotate/gclda.py +924 -0
- nimare/annotate/lda.py +147 -0
- nimare/annotate/text.py +75 -0
- nimare/annotate/utils.py +87 -0
- nimare/base.py +217 -0
- nimare/cli.py +124 -0
- nimare/correct.py +462 -0
- nimare/dataset.py +685 -0
- nimare/decode/__init__.py +33 -0
- nimare/decode/base.py +115 -0
- nimare/decode/continuous.py +462 -0
- nimare/decode/discrete.py +753 -0
- nimare/decode/encode.py +110 -0
- nimare/decode/utils.py +44 -0
- nimare/diagnostics.py +510 -0
- nimare/estimator.py +139 -0
- nimare/extract/__init__.py +19 -0
- nimare/extract/extract.py +466 -0
- nimare/extract/utils.py +295 -0
- nimare/generate.py +331 -0
- nimare/io.py +667 -0
- nimare/meta/__init__.py +39 -0
- nimare/meta/cbma/__init__.py +6 -0
- nimare/meta/cbma/ale.py +951 -0
- nimare/meta/cbma/base.py +947 -0
- nimare/meta/cbma/mkda.py +1361 -0
- nimare/meta/cbmr.py +970 -0
- nimare/meta/ibma.py +1683 -0
- nimare/meta/kernel.py +501 -0
- nimare/meta/models.py +1199 -0
- nimare/meta/utils.py +494 -0
- nimare/nimads.py +492 -0
- nimare/reports/__init__.py +24 -0
- nimare/reports/base.py +664 -0
- nimare/reports/default.yml +123 -0
- nimare/reports/figures.py +651 -0
- nimare/reports/report.tpl +160 -0
- nimare/resources/__init__.py +1 -0
- nimare/resources/atlases/Harvard-Oxford-LICENSE +93 -0
- nimare/resources/atlases/HarvardOxford-cort-maxprob-thr25-2mm.nii.gz +0 -0
- nimare/resources/database_file_manifest.json +142 -0
- nimare/resources/english_spellings.csv +1738 -0
- nimare/resources/filenames.json +32 -0
- nimare/resources/neurosynth_laird_studies.json +58773 -0
- nimare/resources/neurosynth_stoplist.txt +396 -0
- nimare/resources/nidm_pain_dset.json +1349 -0
- nimare/resources/references.bib +541 -0
- nimare/resources/semantic_knowledge_children.txt +325 -0
- nimare/resources/semantic_relatedness_children.txt +249 -0
- nimare/resources/templates/MNI152_2x2x2_brainmask.nii.gz +0 -0
- nimare/resources/templates/tpl-MNI152NLin6Asym_res-01_T1w.nii.gz +0 -0
- nimare/resources/templates/tpl-MNI152NLin6Asym_res-01_desc-brain_mask.nii.gz +0 -0
- nimare/resources/templates/tpl-MNI152NLin6Asym_res-02_T1w.nii.gz +0 -0
- nimare/resources/templates/tpl-MNI152NLin6Asym_res-02_desc-brain_mask.nii.gz +0 -0
- nimare/results.py +225 -0
- nimare/stats.py +276 -0
- nimare/tests/__init__.py +1 -0
- nimare/tests/conftest.py +229 -0
- nimare/tests/data/amygdala_roi.nii.gz +0 -0
- nimare/tests/data/data-neurosynth_version-7_coordinates.tsv.gz +0 -0
- nimare/tests/data/data-neurosynth_version-7_metadata.tsv.gz +0 -0
- nimare/tests/data/data-neurosynth_version-7_vocab-terms_source-abstract_type-tfidf_features.npz +0 -0
- nimare/tests/data/data-neurosynth_version-7_vocab-terms_vocabulary.txt +100 -0
- nimare/tests/data/neurosynth_dset.json +2868 -0
- nimare/tests/data/neurosynth_laird_studies.json +58773 -0
- nimare/tests/data/nidm_pain_dset.json +1349 -0
- nimare/tests/data/nimads_annotation.json +1 -0
- nimare/tests/data/nimads_studyset.json +1 -0
- nimare/tests/data/test_baseline.txt +2 -0
- nimare/tests/data/test_pain_dataset.json +1278 -0
- nimare/tests/data/test_pain_dataset_multiple_contrasts.json +1242 -0
- nimare/tests/data/test_sleuth_file.txt +18 -0
- nimare/tests/data/test_sleuth_file2.txt +10 -0
- nimare/tests/data/test_sleuth_file3.txt +5 -0
- nimare/tests/data/test_sleuth_file4.txt +5 -0
- nimare/tests/data/test_sleuth_file5.txt +5 -0
- nimare/tests/test_annotate_cogat.py +32 -0
- nimare/tests/test_annotate_gclda.py +86 -0
- nimare/tests/test_annotate_lda.py +27 -0
- nimare/tests/test_dataset.py +99 -0
- nimare/tests/test_decode_continuous.py +132 -0
- nimare/tests/test_decode_discrete.py +92 -0
- nimare/tests/test_diagnostics.py +168 -0
- nimare/tests/test_estimator_performance.py +385 -0
- nimare/tests/test_extract.py +46 -0
- nimare/tests/test_generate.py +247 -0
- nimare/tests/test_io.py +294 -0
- nimare/tests/test_meta_ale.py +298 -0
- nimare/tests/test_meta_cbmr.py +295 -0
- nimare/tests/test_meta_ibma.py +240 -0
- nimare/tests/test_meta_kernel.py +209 -0
- nimare/tests/test_meta_mkda.py +234 -0
- nimare/tests/test_nimads.py +21 -0
- nimare/tests/test_reports.py +110 -0
- nimare/tests/test_stats.py +101 -0
- nimare/tests/test_transforms.py +272 -0
- nimare/tests/test_utils.py +200 -0
- nimare/tests/test_workflows.py +221 -0
- nimare/tests/utils.py +126 -0
- nimare/transforms.py +907 -0
- nimare/utils.py +1367 -0
- nimare/workflows/__init__.py +14 -0
- nimare/workflows/base.py +189 -0
- nimare/workflows/cbma.py +165 -0
- nimare/workflows/ibma.py +108 -0
- nimare/workflows/macm.py +77 -0
- nimare/workflows/misc.py +65 -0
- nimare-0.4.2.dist-info/LICENSE +21 -0
- nimare-0.4.2.dist-info/METADATA +124 -0
- nimare-0.4.2.dist-info/RECORD +119 -0
- nimare-0.4.2.dist-info/WHEEL +5 -0
- nimare-0.4.2.dist-info/entry_points.txt +2 -0
- nimare-0.4.2.dist-info/top_level.txt +2 -0
nimare/correct.py
ADDED
@@ -0,0 +1,462 @@
|
|
1
|
+
"""Multiple comparisons correction methods."""
|
2
|
+
|
3
|
+
import inspect
|
4
|
+
import logging
|
5
|
+
from abc import abstractproperty
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
from pymare.stats import bonferroni, fdr
|
9
|
+
|
10
|
+
from nimare.base import NiMAREBase
|
11
|
+
from nimare.results import MetaResult
|
12
|
+
from nimare.transforms import p_to_z
|
13
|
+
|
14
|
+
LGR = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
|
17
|
+
class Corrector(NiMAREBase):
|
18
|
+
"""Base class for multiple comparison correction methods in :mod:`~nimare.correct`.
|
19
|
+
|
20
|
+
.. versionadded:: 0.0.3
|
21
|
+
|
22
|
+
"""
|
23
|
+
|
24
|
+
# The name of the method that must be implemented in an Estimator class
|
25
|
+
# in order to override the default correction method.
|
26
|
+
_correction_method = None
|
27
|
+
|
28
|
+
# Maps that must be available in the MetaResult instance
|
29
|
+
_required_maps = ("p",)
|
30
|
+
|
31
|
+
def __init__(self):
|
32
|
+
pass
|
33
|
+
|
34
|
+
@abstractproperty
|
35
|
+
def _name_suffix(self):
|
36
|
+
"""Identify parameters in a string, to be added to generated filenames."""
|
37
|
+
pass
|
38
|
+
|
39
|
+
@classmethod
|
40
|
+
def _get_corrector_methods(cls):
|
41
|
+
"""List correction methods implemented within the Corrector."""
|
42
|
+
method_name_str = f"correct_{cls._correction_method}_"
|
43
|
+
corr_methods = inspect.getmembers(cls, predicate=inspect.isfunction)
|
44
|
+
corr_methods = [meth[0] for meth in corr_methods if meth[0].startswith(method_name_str)]
|
45
|
+
corr_methods = [meth.replace(method_name_str, "") for meth in corr_methods]
|
46
|
+
return corr_methods
|
47
|
+
|
48
|
+
@classmethod
|
49
|
+
def _get_estimator_methods(cls, estimator):
|
50
|
+
"""List correction methods implemented in an Estimator."""
|
51
|
+
method_name_str = f"correct_{cls._correction_method}_"
|
52
|
+
est_methods = inspect.getmembers(estimator, predicate=inspect.ismethod)
|
53
|
+
est_methods = [meth[0] for meth in est_methods]
|
54
|
+
est_methods = [meth for meth in est_methods if meth.startswith(method_name_str)]
|
55
|
+
est_methods = [meth.replace(method_name_str, "") for meth in est_methods]
|
56
|
+
return est_methods
|
57
|
+
|
58
|
+
def _collect_inputs(self, result):
|
59
|
+
"""Check that inputs and options are valid.
|
60
|
+
|
61
|
+
Parameters
|
62
|
+
----------
|
63
|
+
result : :obj:`~nimare.results.MetaResult`
|
64
|
+
The MetaResult to validate.
|
65
|
+
"""
|
66
|
+
if not isinstance(result, MetaResult):
|
67
|
+
raise ValueError(
|
68
|
+
"First argument to transform() must be an instance of class MetaResult, not "
|
69
|
+
f"{type(result)}."
|
70
|
+
)
|
71
|
+
|
72
|
+
# Get generic Corrector methods
|
73
|
+
corr_methods = self._get_corrector_methods()
|
74
|
+
|
75
|
+
# Get Estimator correction methods
|
76
|
+
est_methods = self._get_estimator_methods(result.estimator)
|
77
|
+
|
78
|
+
# Check requested method against available methods
|
79
|
+
if self.method not in corr_methods + est_methods:
|
80
|
+
raise ValueError(
|
81
|
+
f"Unsupported {self._correction_method} correction method '{self.method}'\n"
|
82
|
+
f"\tAvailable native methods: {', '.join(corr_methods)}\n"
|
83
|
+
f"\tAvailable estimator methods: {', '.join(est_methods)}"
|
84
|
+
)
|
85
|
+
# Check required maps
|
86
|
+
# for cbmr approach, we have customized name for groupwise p maps
|
87
|
+
p_map_cbmr = tuple(
|
88
|
+
[m for m in result.maps.keys() if m.startswith("p_") and "_corr-" not in m]
|
89
|
+
)
|
90
|
+
if len(p_map_cbmr) > 0:
|
91
|
+
self._required_maps = p_map_cbmr
|
92
|
+
for rm in self._required_maps:
|
93
|
+
if result.maps.get(rm) is None:
|
94
|
+
raise ValueError(
|
95
|
+
f"{type(self)} requires '{rm}' maps to be present in the MetaResult, "
|
96
|
+
"but none were found."
|
97
|
+
)
|
98
|
+
|
99
|
+
def _generate_secondary_maps(self, result, corr_maps, rm):
|
100
|
+
"""Generate corrected version of z and log-p maps if they exist."""
|
101
|
+
p = corr_maps[rm]
|
102
|
+
|
103
|
+
if rm == "p":
|
104
|
+
z_map_name, logp_map_name = "z", "logp"
|
105
|
+
else:
|
106
|
+
z_map_name, logp_map_name = rm.replace("p_", "z_"), rm.replace("p_", "logp_")
|
107
|
+
if z_map_name in result.maps:
|
108
|
+
corr_maps[z_map_name] = p_to_z(p) * np.sign(result.maps[z_map_name])
|
109
|
+
|
110
|
+
if logp_map_name in result.maps:
|
111
|
+
corr_maps[logp_map_name] = -np.log10(p)
|
112
|
+
|
113
|
+
return corr_maps
|
114
|
+
|
115
|
+
@classmethod
|
116
|
+
def inspect(cls, result):
|
117
|
+
"""Identify valid 'method' values for a MetaResult object.
|
118
|
+
|
119
|
+
In addition to returning a list of valid values, this method will also print out those
|
120
|
+
values, divided by the value type (Estimator or generic).
|
121
|
+
|
122
|
+
Parameters
|
123
|
+
----------
|
124
|
+
result : :obj:`~nimare.results.MetaResult`
|
125
|
+
Object for which valid correction methods (i.e., 'method' values) will be identified.
|
126
|
+
|
127
|
+
Returns
|
128
|
+
-------
|
129
|
+
:obj:`list`
|
130
|
+
List of valid 'method' values for the Corrector+Estimator combination, including
|
131
|
+
both non-specific methods and Estimator-specific ones.
|
132
|
+
"""
|
133
|
+
# Get generic Corrector methods
|
134
|
+
corr_methods = cls._get_corrector_methods()
|
135
|
+
|
136
|
+
# Get Estimator correction methods
|
137
|
+
est_methods = cls._get_estimator_methods(result.estimator)
|
138
|
+
|
139
|
+
all_methods = sorted(list(set(corr_methods + est_methods)))
|
140
|
+
|
141
|
+
# Flag any methods implemented in both.
|
142
|
+
# The Estimator method takes priority and the Corrector method is overridden.
|
143
|
+
duplicate_methods = list(set(corr_methods) & set(est_methods))
|
144
|
+
for duplicate_method in duplicate_methods:
|
145
|
+
if duplicate_method in corr_methods:
|
146
|
+
corr_methods[corr_methods.index(duplicate_method)] = (
|
147
|
+
f"{duplicate_method} (overridden)"
|
148
|
+
)
|
149
|
+
|
150
|
+
LGR.info(
|
151
|
+
f"Available non-specific methods: {', '.join(corr_methods)}\n"
|
152
|
+
f"Available Estimator-specific methods: {', '.join(est_methods)}"
|
153
|
+
)
|
154
|
+
return all_methods
|
155
|
+
|
156
|
+
def transform(self, result):
|
157
|
+
"""Apply the multiple comparisons correction method to a MetaResult object.
|
158
|
+
|
159
|
+
Parameters
|
160
|
+
----------
|
161
|
+
result : :obj:`~nimare.results.MetaResult`
|
162
|
+
MetaResult generated by an Estimator to be corrected for multiple comparisons.
|
163
|
+
|
164
|
+
Returns
|
165
|
+
-------
|
166
|
+
result : :obj:`~nimare.results.MetaResult`
|
167
|
+
MetaResult with new corrected maps, tables, and description added.
|
168
|
+
"""
|
169
|
+
correction_method = f"correct_{self._correction_method}_{self.method}"
|
170
|
+
|
171
|
+
# Make sure we return a copy of the MetaResult
|
172
|
+
result = result.copy()
|
173
|
+
|
174
|
+
# Also operate on a copy of the estimator
|
175
|
+
est = result.estimator
|
176
|
+
|
177
|
+
# If a correction method with the same name exists in the current Estimator, use it.
|
178
|
+
# Otherwise fall back on _transform, and the Corrector methods.
|
179
|
+
# In case a method is present in both the Estimator and the Corrector, the Estimator's
|
180
|
+
# implementation takes precedence.
|
181
|
+
if hasattr(est, correction_method):
|
182
|
+
LGR.info(
|
183
|
+
"Using correction method implemented in Estimator: "
|
184
|
+
f"{est.__class__.__module__}.{est.__class__.__name__}.{correction_method}."
|
185
|
+
)
|
186
|
+
corr_maps, corr_tables, description = getattr(est, correction_method)(
|
187
|
+
result, **self.parameters
|
188
|
+
)
|
189
|
+
else:
|
190
|
+
self._collect_inputs(result)
|
191
|
+
corr_maps, corr_tables, description = self._transform(result, method=correction_method)
|
192
|
+
|
193
|
+
# Update corrected map names and add them to maps dict
|
194
|
+
corr_maps = {(k + self._name_suffix): v for k, v in corr_maps.items()}
|
195
|
+
result.maps.update(corr_maps)
|
196
|
+
result.description_ += " " + description
|
197
|
+
|
198
|
+
corr_tables = {(k + self._name_suffix): v for k, v in corr_tables.items()}
|
199
|
+
result.tables.update(corr_tables)
|
200
|
+
|
201
|
+
# Update the estimator as well, in order to retain updated null distributions
|
202
|
+
result.estimator = est
|
203
|
+
|
204
|
+
# Save the corrected maps
|
205
|
+
result.corrector = self
|
206
|
+
|
207
|
+
return result
|
208
|
+
|
209
|
+
def _transform(self, result, method):
|
210
|
+
"""Implement the correction procedure and return a dictionary of arrays.
|
211
|
+
|
212
|
+
This was originally an abstract method, with FWECorrector and FDRCorrector having their
|
213
|
+
own implementations, but those implementations were exactly the same.
|
214
|
+
|
215
|
+
Parameters
|
216
|
+
----------
|
217
|
+
result : :obj:`~nimare.results.MetaResult`
|
218
|
+
MetaResult object from which to extract the p value map and Estimator.
|
219
|
+
method : :obj:`str`
|
220
|
+
The correction method to use. This name must match a method in the Corrector,
|
221
|
+
according to the pattern "correct_[FWE|FDR]_[method]".
|
222
|
+
|
223
|
+
Returns
|
224
|
+
-------
|
225
|
+
corr_maps : :obj:`dict`
|
226
|
+
A dictionary of new maps that will be added to the MetaResult's ``maps`` attribute,
|
227
|
+
where keys are map names and values are the arrays.
|
228
|
+
|
229
|
+
The map names must _not_ include the ``_name_suffix``:, as that will be added in
|
230
|
+
``transform()`` (i.e., return "p" not "p_corr-FDR_q-0.05_method-indep").
|
231
|
+
corr_tables : :obj:`dict`
|
232
|
+
An empty dictionary meant to contain any tables (pandas DataFrames) produced by the
|
233
|
+
correction procedure.
|
234
|
+
description_ : :obj:`str`
|
235
|
+
A description of the correction procedure.
|
236
|
+
"""
|
237
|
+
# Create a dictionary of the corrected results
|
238
|
+
corr_maps = {}
|
239
|
+
for rm in self._required_maps:
|
240
|
+
p = result.maps[rm]
|
241
|
+
|
242
|
+
# Find NaNs in the p value map, and mask them out
|
243
|
+
nonnan_mask = ~np.isnan(p)
|
244
|
+
p_corr = np.empty_like(p)
|
245
|
+
p_no_nans = p[nonnan_mask]
|
246
|
+
|
247
|
+
# Call the correction method
|
248
|
+
p_corr_no_nans, tables, description = getattr(self, method)(p_no_nans)
|
249
|
+
|
250
|
+
# Unmask the corrected p values based on the NaN mask
|
251
|
+
p_corr[nonnan_mask] = p_corr_no_nans
|
252
|
+
|
253
|
+
# Create a dictionary of the corrected results
|
254
|
+
corr_maps[rm] = p_corr
|
255
|
+
self._generate_secondary_maps(result, corr_maps, rm)
|
256
|
+
|
257
|
+
return corr_maps, tables, description
|
258
|
+
|
259
|
+
|
260
|
+
class FWECorrector(Corrector):
|
261
|
+
"""Perform family-wise error rate correction on a meta-analysis.
|
262
|
+
|
263
|
+
Parameters
|
264
|
+
----------
|
265
|
+
method : {'bonferoni', 'montecarlo'}
|
266
|
+
The FWE correction to use. Note that the 'montecarlo' method is only available for
|
267
|
+
a subset of Estimators. To determine what methods are available for the Estimator you're
|
268
|
+
using, use :meth:`inspect`.
|
269
|
+
voxel_thresh : :obj:`float`, optional
|
270
|
+
Only used if ``method='montecarlo'``. The uncorrected voxel-level threshold to use.
|
271
|
+
n_iters : :obj:`int`, default=5000
|
272
|
+
Number of iterations to use for Monte Carlo correction.
|
273
|
+
Default varies by Estimator.
|
274
|
+
For publication-quality results, 5000 or more iterations are recommended.
|
275
|
+
n_cores : :obj:`int`, default=1
|
276
|
+
Number of cores to use for Monte Carlo correction. Default is 1.
|
277
|
+
**kwargs
|
278
|
+
Keyword arguments to be used by the FWE correction implementation.
|
279
|
+
"""
|
280
|
+
|
281
|
+
_correction_method = "fwe"
|
282
|
+
|
283
|
+
def __init__(self, method="bonferroni", n_iters=None, n_cores=1, **kwargs):
|
284
|
+
if method not in ("bonferroni", "montecarlo"):
|
285
|
+
raise ValueError(f"Unsupported FWE correction method '{method}'")
|
286
|
+
|
287
|
+
if method == "montecarlo":
|
288
|
+
kwargs.update({"n_iters": n_iters, "n_cores": n_cores})
|
289
|
+
|
290
|
+
self.method = method
|
291
|
+
self.parameters = kwargs
|
292
|
+
|
293
|
+
@property
|
294
|
+
def _name_suffix(self):
|
295
|
+
return f"_corr-FWE_method-{self.method}"
|
296
|
+
|
297
|
+
def correct_fwe_bonferroni(self, p):
|
298
|
+
"""Perform Bonferroni FWE correction.
|
299
|
+
|
300
|
+
This correction is based on the one described in :footcite:t:`bonferroni1936teoria` and
|
301
|
+
:footcite:t:`shaffer1995multiple`.
|
302
|
+
|
303
|
+
.. warning::
|
304
|
+
Do not call this method directly. Call :meth:`transform` with ``method='bonferroni'``
|
305
|
+
instead.
|
306
|
+
|
307
|
+
.. versionadded:: 0.0.12
|
308
|
+
|
309
|
+
Parameters
|
310
|
+
----------
|
311
|
+
p : :obj:`numpy.ndarray`
|
312
|
+
A 1D array of p values.
|
313
|
+
|
314
|
+
Returns
|
315
|
+
-------
|
316
|
+
p_corr : :obj:`numpy.ndarray`
|
317
|
+
A 1D array of adjusted p values.
|
318
|
+
tables : :obj:`dict`
|
319
|
+
A dictionary of DataFrames with summary information from the correction.
|
320
|
+
This correction method does not produce any tables, so it will be an empty dict.
|
321
|
+
description_ : :obj:`str`
|
322
|
+
A description of the correction procedure.
|
323
|
+
|
324
|
+
References
|
325
|
+
----------
|
326
|
+
.. footbibliography::
|
327
|
+
|
328
|
+
See Also
|
329
|
+
--------
|
330
|
+
nimare.stats.bonferroni
|
331
|
+
"""
|
332
|
+
description = (
|
333
|
+
"Family-wise error rate correction was performed with the Bonferroni correction "
|
334
|
+
"procedure \\citep{bonferroni1936teoria,shaffer1995multiple}."
|
335
|
+
)
|
336
|
+
return bonferroni(p), {}, description
|
337
|
+
|
338
|
+
|
339
|
+
class FDRCorrector(Corrector):
|
340
|
+
"""Perform false discovery rate correction on a meta-analysis.
|
341
|
+
|
342
|
+
Parameters
|
343
|
+
----------
|
344
|
+
method : :obj:`str`, default='indep'
|
345
|
+
The FDR correction to use.
|
346
|
+
Either 'indep' (for independent or positively correlated values) or 'negcorr'
|
347
|
+
(for general or negatively correlated tests).
|
348
|
+
Default is 'indep'.
|
349
|
+
alpha : :obj:`float`, default=0.05
|
350
|
+
The FDR correction rate to use. Default is 0.05.
|
351
|
+
|
352
|
+
Notes
|
353
|
+
-----
|
354
|
+
This corrector supports a small number of internal FDR correction methods, but can also use
|
355
|
+
special methods implemented within individual Estimators.
|
356
|
+
To determine what methods are available for the Estimator you're using, use :meth:`inspect`.
|
357
|
+
Estimators have special methods following the naming convention
|
358
|
+
``correct_[correction-type]_[method]``
|
359
|
+
(e.g., :class:`~nimare.meta.mkda.MKDAChi2.correct_fdr_indep`).
|
360
|
+
"""
|
361
|
+
|
362
|
+
_correction_method = "fdr"
|
363
|
+
|
364
|
+
def __init__(self, method="indep", alpha=0.05, **kwargs):
|
365
|
+
self.alpha = alpha
|
366
|
+
self.method = method
|
367
|
+
self.parameters = kwargs
|
368
|
+
|
369
|
+
@property
|
370
|
+
def _name_suffix(self):
|
371
|
+
return f"_corr-FDR_method-{self.method}"
|
372
|
+
|
373
|
+
def correct_fdr_indep(self, p):
|
374
|
+
"""Perform Benjamini-Hochberg FDR correction.
|
375
|
+
|
376
|
+
This correction is based on the one described in :footcite:t:`benjamini1995controlling`.
|
377
|
+
This method is not universally appropriate. It works well for tests that are independent,
|
378
|
+
or which are positively correlated.
|
379
|
+
|
380
|
+
.. warning::
|
381
|
+
Do not call this method directly. Call :meth:`transform` with ``method='indep'``
|
382
|
+
instead.
|
383
|
+
|
384
|
+
.. versionadded:: 0.0.12
|
385
|
+
|
386
|
+
Parameters
|
387
|
+
----------
|
388
|
+
p : :obj:`numpy.ndarray`
|
389
|
+
A 1D array of p values.
|
390
|
+
|
391
|
+
Returns
|
392
|
+
-------
|
393
|
+
p_corr : :obj:`numpy.ndarray`
|
394
|
+
A 1D array of adjusted p values.
|
395
|
+
tables : :obj:`dict`
|
396
|
+
A dictionary of DataFrames with summary information from the correction.
|
397
|
+
This correction method does not produce any tables, so it will be an empty dict.
|
398
|
+
description_ : :obj:`str`
|
399
|
+
A description of the correction procedure.
|
400
|
+
|
401
|
+
References
|
402
|
+
----------
|
403
|
+
.. footbibliography::
|
404
|
+
|
405
|
+
See Also
|
406
|
+
--------
|
407
|
+
pymare.stats.fdr
|
408
|
+
"""
|
409
|
+
description = (
|
410
|
+
"False discovery rate correction was performed with the Benjamini-Hochberg procedure "
|
411
|
+
"\\citep{benjamini1995controlling}."
|
412
|
+
)
|
413
|
+
return fdr(p, q=self.alpha, method="bh"), {}, description
|
414
|
+
|
415
|
+
def correct_fdr_negcorr(self, p):
|
416
|
+
"""Perform Benjamini-Yekutieli FDR correction.
|
417
|
+
|
418
|
+
This correction is based on the one described in :footcite:t:`benjamini2001control`.
|
419
|
+
It is most appropriate for tests that are negatively correlated.
|
420
|
+
|
421
|
+
.. warning::
|
422
|
+
Do not call this method directly. Call :meth:`transform` with ``method='negcorr'``
|
423
|
+
instead.
|
424
|
+
|
425
|
+
.. versionadded:: 0.0.12
|
426
|
+
|
427
|
+
Parameters
|
428
|
+
----------
|
429
|
+
p : :obj:`numpy.ndarray`
|
430
|
+
A 1D array of p values.
|
431
|
+
|
432
|
+
Returns
|
433
|
+
-------
|
434
|
+
p_corr : :obj:`numpy.ndarray`
|
435
|
+
A 1D array of adjusted p values.
|
436
|
+
tables : :obj:`dict`
|
437
|
+
A dictionary of DataFrames with summary information from the correction.
|
438
|
+
This correction method does not produce any tables, so it will be an empty dict.
|
439
|
+
description_ : :obj:`str`
|
440
|
+
A description of the correction procedure.
|
441
|
+
|
442
|
+
Notes
|
443
|
+
-----
|
444
|
+
The difference between the Benjamini-Yekutieli and Benjamini-Hochberg methods is that
|
445
|
+
Benjamini-Yekutieli includes an additional term, ``c(m)``.
|
446
|
+
When the tests are independent or positively correlated, ``c(m)`` is 1 (and thus has no
|
447
|
+
effect).
|
448
|
+
In cases of other forms of dependence, ``c(m)`` has an effect.
|
449
|
+
|
450
|
+
References
|
451
|
+
----------
|
452
|
+
.. footbibliography::
|
453
|
+
|
454
|
+
See Also
|
455
|
+
--------
|
456
|
+
pymare.stats.fdr
|
457
|
+
"""
|
458
|
+
description = (
|
459
|
+
"False discovery rate correction was performed with the Benjamini-Yekutieli procedure "
|
460
|
+
"\\citep{benjamini2001control}."
|
461
|
+
)
|
462
|
+
return fdr(p, q=self.alpha, method="by"), {}, description
|