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/meta/kernel.py ADDED
@@ -0,0 +1,501 @@
1
+ """Kernel transformers for CBMA algorithms.
2
+
3
+ Methods for estimating thresholded cluster maps from neuroimaging contrasts
4
+ (Contrasts) from sets of foci and optional additional information (e.g., sample
5
+ size and test statistic values).
6
+ """
7
+
8
+ from __future__ import division
9
+
10
+ import logging
11
+
12
+ import nibabel as nib
13
+ import numpy as np
14
+ import pandas as pd
15
+ from joblib import Memory
16
+
17
+ from nimare.base import NiMAREBase
18
+ from nimare.meta.utils import compute_ale_ma, compute_kda_ma, get_ale_kernel
19
+ from nimare.utils import _add_metadata_to_dataframe, mm2vox
20
+
21
+ LGR = logging.getLogger(__name__)
22
+
23
+
24
+ class KernelTransformer(NiMAREBase):
25
+ """Base class for modeled activation-generating methods in :mod:`~nimare.meta.kernel`.
26
+
27
+ .. versionchanged:: 0.2.1
28
+
29
+ - Add return_type='summary_array' option to transform method.
30
+
31
+ .. versionchanged:: 0.0.13
32
+
33
+ - Remove "dataset" `return_type` option.
34
+
35
+ Coordinate-based meta-analyses leverage coordinates reported in
36
+ neuroimaging papers to simulate the thresholded statistical maps from the
37
+ original analyses. This generally involves convolving each coordinate with
38
+ a kernel (typically a Gaussian or binary sphere) that may be weighted based
39
+ on some additional measure, such as statistic value or sample size.
40
+
41
+ Parameters
42
+ ----------
43
+ memory : instance of :class:`joblib.Memory`, :obj:`str`, or :class:`pathlib.Path`
44
+ Used to cache the output of a function. By default, no caching is done.
45
+ If a :obj:`str` is given, it is the path to the caching directory.
46
+ memory_level : :obj:`int`, default=0
47
+ Rough estimator of the amount of memory used by caching.
48
+ Higher value means more memory for caching. Zero means no caching.
49
+
50
+ Notes
51
+ -----
52
+ All extra (non-ijk) parameters for a given kernel should be overridable as
53
+ parameters to __init__, so we can access them with get_params() and also
54
+ apply them to datasets with missing data.
55
+ """
56
+
57
+ def __init__(self, memory=Memory(location=None, verbose=0), memory_level=0):
58
+ self.memory = memory
59
+ self.memory_level = memory_level
60
+
61
+ def _infer_names(self, **kwargs):
62
+ """Determine filename pattern and image type.
63
+
64
+ The parameters used to construct the filenames come from the transformer's
65
+ parameters (attributes saved in ``__init__()``).
66
+
67
+ Parameters
68
+ ----------
69
+ **kwargs
70
+ Additional key/value pairs to incorporate into the image name.
71
+ A common example is the hash for the target template's affine.
72
+
73
+ Attributes
74
+ ----------
75
+ filename_pattern : str
76
+ Filename pattern for images.
77
+ image_type : str
78
+ Name of the corresponding column in the Dataset.images DataFrame.
79
+ """
80
+ params = self.get_params()
81
+ params = dict(**params, **kwargs)
82
+
83
+ # Determine names for kernel-specific files
84
+ keys = sorted(params.keys())
85
+ param_str = "_".join(f"{k}-{str(params[k])}" for k in keys)
86
+ self.filename_pattern = (
87
+ f"study-[[id]]_{param_str}_{self.__class__.__name__}.nii.gz".replace(
88
+ "[[", "{"
89
+ ).replace("]]", "}")
90
+ )
91
+ self.image_type = f"{param_str}_{self.__class__.__name__}"
92
+
93
+ def transform(self, dataset, masker=None, return_type="image"):
94
+ """Generate modeled activation images for each Contrast in dataset.
95
+
96
+ Parameters
97
+ ----------
98
+ dataset : :obj:`~nimare.dataset.Dataset` or :obj:`pandas.DataFrame`
99
+ Dataset for which to make images. Can be a DataFrame if necessary.
100
+ masker : img_like or None, optional
101
+ Mask to apply to MA maps. Required if ``dataset`` is a DataFrame.
102
+ If None (and ``dataset`` is a Dataset), the Dataset's masker attribute will be used.
103
+ Default is None.
104
+ return_type : {'sparse', 'array', 'image', 'summary_array'}, optional
105
+ Whether to return a sparse matrix ('sparse'), a numpy array ('array'),
106
+ or a list of niimgs ('image').
107
+ Default is 'image'.
108
+
109
+ Returns
110
+ -------
111
+ imgs : (C x V) :class:`numpy.ndarray` or :obj:`list` of :class:`nibabel.Nifti1Image` \
112
+ or :class:`~nimare.dataset.Dataset`
113
+ If return_type is 'sparse', a 4D sparse array (E x S), where E is
114
+ the number of unique experiments, and the remaining 3 dimensions are
115
+ equal to `shape` of the images.
116
+ If return_type is 'array', a 2D numpy array (C x V), where C is
117
+ contrast and V is voxel.
118
+ If return_type is 'summary_array', a 1D numpy array (V,) containing
119
+ a summary measure for each voxel that has been combined across experiments.
120
+ If return_type is 'image', a list of modeled activation images
121
+ (one for each of the Contrasts in the input dataset).
122
+
123
+ Attributes
124
+ ----------
125
+ filename_pattern : str
126
+ Filename pattern for MA maps. If :meth:`_infer_names` is executed.
127
+ image_type : str
128
+ Name of the corresponding column in the Dataset.images DataFrame.
129
+ If :meth:`_infer_names` is executed.
130
+ """
131
+ if return_type not in ("sparse", "array", "image", "summary_array"):
132
+ raise ValueError(
133
+ 'Argument "return_type" must be "image", "array", "summary_array", "sparse".'
134
+ )
135
+
136
+ if isinstance(dataset, pd.DataFrame):
137
+ assert (
138
+ masker is not None
139
+ ), "Argument 'masker' must be provided if dataset is a DataFrame."
140
+ mask = masker.mask_img
141
+ coordinates = dataset
142
+
143
+ # Calculate IJK. Must assume that the masker is in same space,
144
+ # but has different affine, from original IJK.
145
+ coordinates[["i", "j", "k"]] = mm2vox(dataset[["x", "y", "z"]], mask.affine)
146
+ else:
147
+ masker = dataset.masker if not masker else masker
148
+ mask = masker.mask_img
149
+ coordinates = dataset.coordinates.copy()
150
+
151
+ # Calculate IJK
152
+ if not np.array_equal(mask.affine, dataset.masker.mask_img.affine):
153
+ LGR.warning("Mask affine does not match Dataset affine. Assuming same space.")
154
+
155
+ coordinates[["i", "j", "k"]] = mm2vox(coordinates[["x", "y", "z"]], mask.affine)
156
+
157
+ # Add any metadata the Transformer might need to the coordinates DataFrame
158
+ # This approach is probably inferior to one which uses a _required_inputs attribute
159
+ # (like the MetaEstimators), but it should work just fine as long as individual
160
+ # requirements are written in here.
161
+ if (
162
+ hasattr(self, "sample_size")
163
+ and (self.sample_size is None)
164
+ and ("sample_size" not in coordinates.columns)
165
+ ):
166
+ coordinates = _add_metadata_to_dataframe(
167
+ dataset,
168
+ coordinates,
169
+ metadata_field="sample_sizes",
170
+ target_column="sample_size",
171
+ filter_func=np.mean,
172
+ )
173
+
174
+ if return_type == "array":
175
+ mask_data = mask.get_fdata().astype(bool)
176
+ elif return_type == "image":
177
+ dtype = type(self.value) if hasattr(self, "value") else float
178
+ mask_data = mask.get_fdata().astype(dtype)
179
+
180
+ # Generate the MA maps
181
+ if return_type == "summary_array" or return_type == "sparse":
182
+ args = (mask, coordinates, return_type)
183
+ else:
184
+ args = (mask, coordinates)
185
+
186
+ transformed_maps = self._cache(self._transform, func_memory_level=2)(*args)
187
+
188
+ if return_type == "sparse" or return_type == "summary_array":
189
+ return transformed_maps[0]
190
+
191
+ imgs = []
192
+ # Loop over exp ids since sparse._coo.core.COO is not iterable
193
+ for i_exp, _ in enumerate(transformed_maps[1]):
194
+ kernel_data = transformed_maps[0][i_exp].todense()
195
+
196
+ if return_type == "array":
197
+ img = kernel_data[mask_data]
198
+ imgs.append(img)
199
+ elif return_type == "image":
200
+ kernel_data *= mask_data
201
+ img = nib.Nifti1Image(kernel_data, mask.affine, dtype=kernel_data.dtype)
202
+ imgs.append(img)
203
+
204
+ del kernel_data, transformed_maps
205
+
206
+ if return_type == "array":
207
+ return np.vstack(imgs)
208
+ elif return_type == "image":
209
+ return imgs
210
+
211
+ def _transform(self, mask, coordinates, return_type="sparse"):
212
+ """Apply the kernel's unique transformer.
213
+
214
+ Parameters
215
+ ----------
216
+ mask : niimg-like
217
+ Mask image. Should contain binary-like integer data.
218
+ coordinates : pandas.DataFrame
219
+ DataFrame containing IDs and coordinates.
220
+ The DataFrame must have the following columns: "id", "i", "j", "k".
221
+ Additionally, individual kernels may require other columns
222
+ (e.g., "sample_size" for ALE).
223
+ return_type : {'sparse', 'summary_array'}, optional
224
+ Whether to return a 4D sparse matrix ('sparse') where each contrast map is
225
+ saved separately or a 1D numpy array ('summary_array') where the contrast maps
226
+ are combined.
227
+ Default is 'sparse'.
228
+
229
+ Returns
230
+ -------
231
+ transformed_maps : N-length list of (3D array, str) tuples or (4D array, 1D array) tuple
232
+ Transformed data, containing one element for each study.
233
+
234
+ - Case 1: A kernel that is not an (M)KDAKernel
235
+ Each list entry is composed of a 3D array (the MA map) and the study's ID.
236
+
237
+ - Case 2: (M)KDAKernel
238
+ There is a length-2 tuple with a 4D numpy array of the shape (N, X, Y, Z),
239
+ containing all of the MA maps, and a numpy array of shape (N,) with the study IDs.
240
+
241
+ - Case 3: A kernel with return_type='summary_array'.
242
+ The transformed data is a 1D numpy array of shape (X, Y, Z) containing the
243
+ summary measure for each voxel.
244
+ """
245
+ pass
246
+
247
+
248
+ class ALEKernel(KernelTransformer):
249
+ """Generate ALE modeled activation images from coordinates and sample size.
250
+
251
+ By default (if neither ``fwhm`` nor ``sample_size`` is provided), the FWHM of the kernel
252
+ will be determined on a study-wise basis based on the sample sizes available in the input,
253
+ via the method described in :footcite:t:`eickhoff2012activation`.
254
+
255
+ .. versionchanged:: 0.2.1
256
+
257
+ - New parameters: ``memory`` and ``memory_level`` for memory caching.
258
+
259
+ .. versionchanged:: 0.0.13
260
+
261
+ - Remove "dataset" `return_type` option.
262
+
263
+ .. versionchanged:: 0.0.12
264
+
265
+ * Remove low-memory option in favor of sparse arrays for kernel transformers.
266
+
267
+ Parameters
268
+ ----------
269
+ fwhm : :obj:`float`, optional
270
+ Full-width half-max for Gaussian kernel, if you want to have a
271
+ constant kernel across Contrasts. Mutually exclusive with
272
+ ``sample_size``.
273
+ sample_size : :obj:`int`, optional
274
+ Sample size, used to derive FWHM for Gaussian kernel based on
275
+ formulae from Eickhoff et al. (2012). This sample size overwrites
276
+ the Contrast-specific sample sizes in the dataset, in order to hold
277
+ kernel constant across Contrasts. Mutually exclusive with ``fwhm``.
278
+ memory : instance of :class:`joblib.Memory`, :obj:`str`, or :class:`pathlib.Path`
279
+ Used to cache the output of a function. By default, no caching is done.
280
+ If a :obj:`str` is given, it is the path to the caching directory.
281
+ memory_level : :obj:`int`, default=0
282
+ Rough estimator of the amount of memory used by caching.
283
+ Higher value means more memory for caching. Zero means no caching.
284
+
285
+ References
286
+ ----------
287
+ .. footbibliography::
288
+ """
289
+
290
+ def __init__(
291
+ self,
292
+ fwhm=None,
293
+ sample_size=None,
294
+ memory=Memory(location=None, verbose=0),
295
+ memory_level=0,
296
+ ):
297
+ if fwhm is not None and sample_size is not None:
298
+ raise ValueError('Only one of "fwhm" and "sample_size" may be provided.')
299
+ self.fwhm = fwhm
300
+ self.sample_size = sample_size
301
+ super().__init__(memory=memory, memory_level=memory_level)
302
+
303
+ def _transform(self, mask, coordinates, return_type="sparse"):
304
+ ijks = coordinates[["i", "j", "k"]].values
305
+ exp_idx = coordinates["id"].values
306
+
307
+ use_dict = True
308
+ kernel = None
309
+ if self.sample_size is not None:
310
+ sample_sizes = self.sample_size
311
+ use_dict = False
312
+ elif self.fwhm is None:
313
+ sample_sizes = coordinates["sample_size"].values
314
+ else:
315
+ sample_sizes = None
316
+
317
+ if self.fwhm is not None:
318
+ assert np.isfinite(self.fwhm), "FWHM must be finite number"
319
+ _, kernel = get_ale_kernel(mask, fwhm=self.fwhm)
320
+ use_dict = False
321
+
322
+ transformed = compute_ale_ma(
323
+ mask,
324
+ ijks,
325
+ kernel=kernel,
326
+ exp_idx=exp_idx,
327
+ sample_sizes=sample_sizes,
328
+ use_dict=use_dict,
329
+ )
330
+
331
+ exp_ids = np.unique(exp_idx)
332
+ return transformed, exp_ids
333
+
334
+ def _generate_description(self):
335
+ """Generate a description of the fitted KernelTransformer.
336
+
337
+ Returns
338
+ -------
339
+ str
340
+ Description of the KernelTransformer.
341
+ """
342
+ if self.sample_size is not None:
343
+ fwhm_str = (
344
+ "with a full-width at half max corresponding to a sample size of "
345
+ f"{self.sample_size}, according to the formulae provided in "
346
+ "\\cite{eickhoff2012activation}"
347
+ )
348
+ elif self.fwhm is not None:
349
+ fwhm_str = f"with a full-width at half max of {self.fwhm}"
350
+ else:
351
+ fwhm_str = (
352
+ "with full-width at half max values determined on a study-wise basis based on the "
353
+ "study sample sizes according to the formulae provided in "
354
+ "\\cite{eickhoff2012activation}"
355
+ )
356
+
357
+ description = (
358
+ "An ALE kernel \\citep{eickhoff2012activation} was used to generate study-wise "
359
+ "modeled activation maps from coordinates. "
360
+ "In this kernel method, each coordinate is convolved with a Gaussian kernel "
361
+ f"{fwhm_str}. "
362
+ "For voxels with overlapping kernels, the maximum value was retained."
363
+ )
364
+ return description
365
+
366
+
367
+ class KDAKernel(KernelTransformer):
368
+ """Generate KDA modeled activation images from coordinates.
369
+
370
+ .. versionchanged:: 0.2.1
371
+
372
+ - Add new parameter ``return_type`` to transform method.
373
+
374
+ .. versionchanged:: 0.0.13
375
+
376
+ - Add new parameter ``memory`` to cache modeled activation (MA) maps.
377
+
378
+ .. versionchanged:: 0.0.13
379
+
380
+ - Remove "dataset" `return_type` option.
381
+
382
+ .. versionchanged:: 0.0.12
383
+
384
+ * Remove low-memory option in favor of sparse arrays for kernel transformers.
385
+
386
+ Parameters
387
+ ----------
388
+ r : :obj:`int`, default=10
389
+ Sphere radius, in mm.
390
+ value : :obj:`int`, default=1
391
+ Value for sphere.
392
+ memory : instance of :class:`joblib.Memory`, :obj:`str`, or :class:`pathlib.Path`
393
+ Used to cache the output of a function. By default, no caching is done.
394
+ If a :obj:`str` is given, it is the path to the caching directory.
395
+ memory_level : :obj:`int`, default=0
396
+ Rough estimator of the amount of memory used by caching.
397
+ Higher value means more memory for caching. Zero means no caching.
398
+ """
399
+
400
+ _sum_overlap = True
401
+
402
+ def __init__(
403
+ self,
404
+ r=10,
405
+ value=1,
406
+ memory=Memory(location=None, verbose=0),
407
+ memory_level=0,
408
+ ):
409
+ self.r = float(r)
410
+ self.value = value
411
+ super().__init__(memory=memory, memory_level=memory_level)
412
+
413
+ def _transform(self, mask, coordinates, return_type="sparse"):
414
+ """Return type can either be sparse or summary_array."""
415
+ ijks = coordinates[["i", "j", "k"]].values
416
+ exp_idx = coordinates["id"].values
417
+ if return_type == "sparse":
418
+ sum_across_studies = False
419
+ elif return_type == "summary_array":
420
+ sum_across_studies = True
421
+ else:
422
+ raise ValueError('Argument "return_type" must be "sparse" or "summary_array".')
423
+
424
+ transformed = compute_kda_ma(
425
+ mask,
426
+ ijks,
427
+ self.r,
428
+ self.value,
429
+ exp_idx,
430
+ sum_overlap=self._sum_overlap,
431
+ sum_across_studies=sum_across_studies,
432
+ )
433
+ exp_ids = np.unique(exp_idx)
434
+ return transformed, exp_ids
435
+
436
+ def _generate_description(self):
437
+ """Generate a description of the fitted KernelTransformer.
438
+
439
+ Returns
440
+ -------
441
+ str
442
+ Description of the KernelTransformer.
443
+ """
444
+ description = (
445
+ "A KDA kernel \\citep{wager2003valence,wager2004neuroimaging} was used to generate "
446
+ "study-wise modeled activation maps from coordinates. "
447
+ "In this kernel method, each coordinate is convolved with a sphere with a radius of "
448
+ f"{self.r} and a value of {self.value}. "
449
+ "These spheres are then summed within each study to produce the study's MA map."
450
+ )
451
+ return description
452
+
453
+
454
+ class MKDAKernel(KDAKernel):
455
+ """Generate MKDA modeled activation images from coordinates.
456
+
457
+ .. versionchanged:: 0.2.1
458
+
459
+ - New parameters: ``memory`` and ``memory_level`` for memory caching.
460
+ - Add new parameter ``return_type`` to transform method.
461
+
462
+ .. versionchanged:: 0.0.13
463
+
464
+ - Remove "dataset" `return_type` option.
465
+
466
+ .. versionchanged:: 0.0.12
467
+
468
+ * Remove low-memory option in favor of sparse arrays for kernel transformers.
469
+
470
+ Parameters
471
+ ----------
472
+ r : :obj:`int`, default=10
473
+ Sphere radius, in mm.
474
+ value : :obj:`int`, default=1
475
+ Value for sphere.
476
+ memory : instance of :class:`joblib.Memory`, :obj:`str`, or :class:`pathlib.Path`
477
+ Used to cache the output of a function. By default, no caching is done.
478
+ If a :obj:`str` is given, it is the path to the caching directory.
479
+ memory_level : :obj:`int`, default=0
480
+ Rough estimator of the amount of memory used by caching.
481
+ Higher value means more memory for caching. Zero means no caching.
482
+ """
483
+
484
+ _sum_overlap = False
485
+
486
+ def _generate_description(self):
487
+ """Generate a description of the fitted KernelTransformer.
488
+
489
+ Returns
490
+ -------
491
+ str
492
+ Description of the KernelTransformer.
493
+ """
494
+ description = (
495
+ "An MKDA kernel \\citep{wager2007meta} was used to generate "
496
+ "study-wise modeled activation maps from coordinates. "
497
+ "In this kernel method, each coordinate is convolved with a sphere with a radius of "
498
+ f"{self.r} and a value of {self.value}. "
499
+ "For voxels with overlapping spheres, the maximum value was retained."
500
+ )
501
+ return description