nimare 0.4.2rc4__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 (119) hide show
  1. benchmarks/__init__.py +0 -0
  2. benchmarks/bench_cbma.py +57 -0
  3. nimare/__init__.py +45 -0
  4. nimare/_version.py +21 -0
  5. nimare/annotate/__init__.py +21 -0
  6. nimare/annotate/cogat.py +213 -0
  7. nimare/annotate/gclda.py +924 -0
  8. nimare/annotate/lda.py +147 -0
  9. nimare/annotate/text.py +75 -0
  10. nimare/annotate/utils.py +87 -0
  11. nimare/base.py +217 -0
  12. nimare/cli.py +124 -0
  13. nimare/correct.py +462 -0
  14. nimare/dataset.py +685 -0
  15. nimare/decode/__init__.py +33 -0
  16. nimare/decode/base.py +115 -0
  17. nimare/decode/continuous.py +462 -0
  18. nimare/decode/discrete.py +753 -0
  19. nimare/decode/encode.py +110 -0
  20. nimare/decode/utils.py +44 -0
  21. nimare/diagnostics.py +510 -0
  22. nimare/estimator.py +139 -0
  23. nimare/extract/__init__.py +19 -0
  24. nimare/extract/extract.py +466 -0
  25. nimare/extract/utils.py +295 -0
  26. nimare/generate.py +331 -0
  27. nimare/io.py +635 -0
  28. nimare/meta/__init__.py +39 -0
  29. nimare/meta/cbma/__init__.py +6 -0
  30. nimare/meta/cbma/ale.py +951 -0
  31. nimare/meta/cbma/base.py +947 -0
  32. nimare/meta/cbma/mkda.py +1361 -0
  33. nimare/meta/cbmr.py +970 -0
  34. nimare/meta/ibma.py +1683 -0
  35. nimare/meta/kernel.py +501 -0
  36. nimare/meta/models.py +1199 -0
  37. nimare/meta/utils.py +494 -0
  38. nimare/nimads.py +492 -0
  39. nimare/reports/__init__.py +24 -0
  40. nimare/reports/base.py +664 -0
  41. nimare/reports/default.yml +123 -0
  42. nimare/reports/figures.py +651 -0
  43. nimare/reports/report.tpl +160 -0
  44. nimare/resources/__init__.py +1 -0
  45. nimare/resources/atlases/Harvard-Oxford-LICENSE +93 -0
  46. nimare/resources/atlases/HarvardOxford-cort-maxprob-thr25-2mm.nii.gz +0 -0
  47. nimare/resources/database_file_manifest.json +142 -0
  48. nimare/resources/english_spellings.csv +1738 -0
  49. nimare/resources/filenames.json +32 -0
  50. nimare/resources/neurosynth_laird_studies.json +58773 -0
  51. nimare/resources/neurosynth_stoplist.txt +396 -0
  52. nimare/resources/nidm_pain_dset.json +1349 -0
  53. nimare/resources/references.bib +541 -0
  54. nimare/resources/semantic_knowledge_children.txt +325 -0
  55. nimare/resources/semantic_relatedness_children.txt +249 -0
  56. nimare/resources/templates/MNI152_2x2x2_brainmask.nii.gz +0 -0
  57. nimare/resources/templates/tpl-MNI152NLin6Asym_res-01_T1w.nii.gz +0 -0
  58. nimare/resources/templates/tpl-MNI152NLin6Asym_res-01_desc-brain_mask.nii.gz +0 -0
  59. nimare/resources/templates/tpl-MNI152NLin6Asym_res-02_T1w.nii.gz +0 -0
  60. nimare/resources/templates/tpl-MNI152NLin6Asym_res-02_desc-brain_mask.nii.gz +0 -0
  61. nimare/results.py +225 -0
  62. nimare/stats.py +276 -0
  63. nimare/tests/__init__.py +1 -0
  64. nimare/tests/conftest.py +229 -0
  65. nimare/tests/data/amygdala_roi.nii.gz +0 -0
  66. nimare/tests/data/data-neurosynth_version-7_coordinates.tsv.gz +0 -0
  67. nimare/tests/data/data-neurosynth_version-7_metadata.tsv.gz +0 -0
  68. nimare/tests/data/data-neurosynth_version-7_vocab-terms_source-abstract_type-tfidf_features.npz +0 -0
  69. nimare/tests/data/data-neurosynth_version-7_vocab-terms_vocabulary.txt +100 -0
  70. nimare/tests/data/neurosynth_dset.json +2868 -0
  71. nimare/tests/data/neurosynth_laird_studies.json +58773 -0
  72. nimare/tests/data/nidm_pain_dset.json +1349 -0
  73. nimare/tests/data/nimads_annotation.json +1 -0
  74. nimare/tests/data/nimads_studyset.json +1 -0
  75. nimare/tests/data/test_baseline.txt +2 -0
  76. nimare/tests/data/test_pain_dataset.json +1278 -0
  77. nimare/tests/data/test_pain_dataset_multiple_contrasts.json +1242 -0
  78. nimare/tests/data/test_sleuth_file.txt +18 -0
  79. nimare/tests/data/test_sleuth_file2.txt +10 -0
  80. nimare/tests/data/test_sleuth_file3.txt +5 -0
  81. nimare/tests/data/test_sleuth_file4.txt +5 -0
  82. nimare/tests/data/test_sleuth_file5.txt +5 -0
  83. nimare/tests/test_annotate_cogat.py +32 -0
  84. nimare/tests/test_annotate_gclda.py +86 -0
  85. nimare/tests/test_annotate_lda.py +27 -0
  86. nimare/tests/test_dataset.py +99 -0
  87. nimare/tests/test_decode_continuous.py +132 -0
  88. nimare/tests/test_decode_discrete.py +92 -0
  89. nimare/tests/test_diagnostics.py +168 -0
  90. nimare/tests/test_estimator_performance.py +385 -0
  91. nimare/tests/test_extract.py +46 -0
  92. nimare/tests/test_generate.py +247 -0
  93. nimare/tests/test_io.py +240 -0
  94. nimare/tests/test_meta_ale.py +298 -0
  95. nimare/tests/test_meta_cbmr.py +295 -0
  96. nimare/tests/test_meta_ibma.py +240 -0
  97. nimare/tests/test_meta_kernel.py +209 -0
  98. nimare/tests/test_meta_mkda.py +234 -0
  99. nimare/tests/test_nimads.py +21 -0
  100. nimare/tests/test_reports.py +110 -0
  101. nimare/tests/test_stats.py +101 -0
  102. nimare/tests/test_transforms.py +272 -0
  103. nimare/tests/test_utils.py +200 -0
  104. nimare/tests/test_workflows.py +221 -0
  105. nimare/tests/utils.py +126 -0
  106. nimare/transforms.py +907 -0
  107. nimare/utils.py +1367 -0
  108. nimare/workflows/__init__.py +14 -0
  109. nimare/workflows/base.py +189 -0
  110. nimare/workflows/cbma.py +165 -0
  111. nimare/workflows/ibma.py +108 -0
  112. nimare/workflows/macm.py +77 -0
  113. nimare/workflows/misc.py +65 -0
  114. nimare-0.4.2rc4.dist-info/LICENSE +21 -0
  115. nimare-0.4.2rc4.dist-info/METADATA +124 -0
  116. nimare-0.4.2rc4.dist-info/RECORD +119 -0
  117. nimare-0.4.2rc4.dist-info/WHEEL +5 -0
  118. nimare-0.4.2rc4.dist-info/entry_points.txt +2 -0
  119. nimare-0.4.2rc4.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