|
2 | 2 | .. _metas_cbmr: |
3 | 3 | .. _metas_voxelwise_cbmr: |
4 | 4 |
|
5 | | -============================================================ |
6 | | -Coordinate-based meta-regression with moderator-effect modes |
7 | | -============================================================ |
| 5 | +==================================================================== |
| 6 | +Coordinate-based meta-regression with global and voxelwise moderators |
| 7 | +==================================================================== |
8 | 8 |
|
9 | 9 | A tour of coordinate-based meta-regression (CBMR) in NiMARE. |
10 | 10 |
|
11 | 11 | CBMR is a generative framework for estimating smooth activation intensity |
12 | | -functions from coordinate-based meta-analytic data. The same |
13 | | -:class:`~nimare.meta.cbmr.CBMREstimator` can parameterize moderator effects in |
14 | | -three ways: |
| 12 | +functions from coordinate-based meta-analytic data. The current |
| 13 | +:class:`~nimare.meta.cbmr.CBMREstimator` implementation exposes one public API |
| 14 | +for three moderator-effect parameterizations: |
15 | 15 |
|
16 | 16 | * ``moderator_effect="global"`` estimates one scalar coefficient per moderator. |
17 | 17 | This assumes the effect of the moderator has a global effect across the entire brain. |
18 | | -* ``moderator_effect="voxelwise"`` estimates a scalar coefficient _per voxel_ per moderator. |
19 | | - This assumes the effect of the moderator differentially impacts voxels throughout the brain. |
20 | | - This is likely a more accurate assumption, but requires a lot more data for estimation. |
| 18 | +* ``moderator_effect="voxelwise"`` estimates a smooth spatial coefficient map |
| 19 | + for each moderator and group. This allows the moderator effect to vary across |
| 20 | + the brain, but requires more data for stable estimation. |
21 | 21 | * ``moderator_effect="mixed"`` estimates scalar coefficients for selected |
22 | 22 | ``global_moderators`` and spatially varying coefficients for selected |
23 | 23 | ``voxelwise_moderators`` in one model. |
24 | 24 |
|
25 | | -This tutorial fits all three versions to the same simulated Studyset with the |
26 | | -same groups and standardized moderators, then compares their outputs. |
| 25 | +This tutorial fits all three versions to the same simulated Studyset, shows how |
| 26 | +to inspect fitted CBMR results, and demonstrates the result-centered inference |
| 27 | +helpers added around :class:`~nimare.meta.cbmr.CBMRInference`. |
27 | 28 | """ |
28 | 29 |
|
29 | 30 | import numpy as np |
|
39 | 40 | # Load Studyset-compatible data |
40 | 41 | # ----------------------------------------------------------------------------- |
41 | 42 | # We simulate a coordinate-based Studyset with reported foci, sample sizes, |
42 | | -# diagnosis labels, drug-status labels, and continuous moderators. |
43 | | -# The example uses a moderate number of studies and coarse B-spline spacing so |
44 | | -# that both global and voxelwise CBMR fits run quickly. |
| 43 | +# diagnosis labels, drug-status labels, and continuous moderators. The example |
| 44 | +# uses a moderate number of studies and coarse B-spline spacing so that global, |
| 45 | +# voxelwise, and mixed CBMR fits run quickly. |
45 | 46 |
|
46 | 47 | _, studyset = create_coordinate_studyset( |
47 | 48 | foci=10, |
48 | 49 | sample_size=(20, 40), |
49 | 50 | n_studies=200, |
| 51 | + seed=100, |
50 | 52 | ) |
51 | 53 |
|
52 | 54 | annotations_df = studyset.annotations_df.copy() |
53 | 55 | n_rows = annotations_df.shape[0] |
54 | | -annotations_df["diagnosis"] = [ |
55 | | - "schizophrenia" if i % 2 == 0 else "depression" for i in range(n_rows) |
| 56 | +group_pattern = [ |
| 57 | + ("schizophrenia", "Yes"), |
| 58 | + ("schizophrenia", "No"), |
| 59 | + ("depression", "Yes"), |
| 60 | + ("depression", "No"), |
| 61 | +] |
| 62 | +annotations_df[["diagnosis", "drug_status"]] = [ |
| 63 | + group_pattern[i % len(group_pattern)] for i in range(n_rows) |
56 | 64 | ] |
57 | | -annotations_df["drug_status"] = ["Yes" if i % 2 == 0 else "No" for i in range(n_rows)] |
58 | | -annotations_df["drug_status"] = annotations_df["drug_status"].sample(frac=1).reset_index(drop=True) |
59 | 65 | annotations_df["sample_sizes"] = [studyset.metadata.sample_sizes[i][0] for i in range(n_rows)] |
60 | 66 | annotations_df["avg_age"] = np.arange(n_rows) |
61 | 67 | studyset.annotations_df = annotations_df |
|
83 | 89 | lr=1e-1, |
84 | 90 | tol=1e3, # a reasonable analysis choice is 1e-2; 1e3 is for speed |
85 | 91 | device="cpu", # use "cuda" if you have a GPU |
| 92 | + random_state=100, |
86 | 93 | ) |
87 | 94 | global_results = global_cbmr.fit(dataset=studyset) |
88 | 95 |
|
|
235 | 242 | damping=1.0, |
236 | 243 | compute_nll=False, |
237 | 244 | device="cpu", # the full backend also accepts "cuda" if a GPU is available |
| 245 | + random_state=100, |
238 | 246 | ) |
239 | 247 | voxelwise_results = voxelwise_cbmr.fit(dataset=studyset) |
240 | 248 |
|
|
275 | 283 | # ----------------------------------------------------------------------------- |
276 | 284 | # A fitted :class:`~nimare.meta.cbmr.CBMRInference` object can generate Relative |
277 | 285 | # Intensity (RI) and Intensity Difference (ID) diagnostic maps showing how a |
278 | | -# user-defined moderator-unit change affects spatial intensity. The updated |
279 | | -# helper accepts the same moderator/group selectors as the inference methods and |
280 | | -# returns a CBMRResult copy with named RI and ID maps. Users can keep those maps |
281 | | -# for downstream diagnosis or plot RI inside an ID-defined region of interest. |
282 | | -# If no ID threshold is provided, the median absolute ID value is used. |
| 286 | +# user-defined moderator-unit change affects spatial intensity. The helper |
| 287 | +# accepts the same moderator/group selectors as the inference methods and returns |
| 288 | +# a CBMRResult copy with named RI and ID maps. Users can keep those maps for |
| 289 | +# downstream diagnosis or plot RI inside an ID-defined region of interest. If no |
| 290 | +# ID threshold is provided, the median absolute ID value is used. |
283 | 291 |
|
284 | 292 | voxelwise_inference = voxelwise_results.get_inference( |
285 | 293 | method="FI", |
|
397 | 405 | group_categories=group_categories, |
398 | 406 | global_moderators=["standardized_sample_sizes"], |
399 | 407 | voxelwise_moderators=["standardized_avg_age"], |
| 408 | + backend="full", |
400 | 409 | spline_spacing=100, # a reasonable analysis choice is 10 or 5; 100 is for speed |
401 | 410 | n_iter=10, |
402 | 411 | lr=1e-1, |
403 | 412 | tol=1e3, # a reasonable analysis choice is 1e-4; 1e3 is for speed |
404 | 413 | device="cpu", # use "cuda" if you have a GPU |
| 414 | + random_state=100, |
405 | 415 | ) |
406 | 416 | mixed_results = mixed_cbmr.fit(dataset=studyset) |
407 | 417 |
|
|
0 commit comments