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/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
|