Skip to content

Commit fca59eb

Browse files
committed
ENH add RGB functional maps
1 parent e8b4ce1 commit fca59eb

4 files changed

Lines changed: 247 additions & 48 deletions

File tree

tutorials/movies_3T/02_plot_wordnet_model.py

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -332,14 +332,15 @@
332332
###############################################################################
333333
# Here, we are only interested in the voxels with good generalization
334334
# performances. We select an arbitrary threshold of 0.05 (R^2 score).
335-
primal_coef = primal_coef[:, scores > 0.05]
335+
primal_coef_selection = primal_coef[:, scores > 0.05]
336336

337337
###############################################################################
338338
# Then, we aggregate the coefficients across the different delays.
339339

340340
# split the ridge coefficients per delays
341341
delayer = pipeline.named_steps['delayer']
342-
primal_coef_per_delay = delayer.reshape_by_delays(primal_coef, axis=0)
342+
primal_coef_per_delay = delayer.reshape_by_delays(primal_coef_selection,
343+
axis=0)
343344
print("(n_delays, n_features, n_voxels) =", primal_coef_per_delay.shape)
344345

345346
# average over delays
@@ -397,15 +398,46 @@
397398
plt.show()
398399

399400
###############################################################################
400-
# According to the authors of [1]_, "this principal component distinguishes
401+
# According to the authors of [1]_, "this principal component distinguishes
401402
# between categories with high stimulus energy (e.g. moving objects like
402403
# `person` and `vehicle`) and those with low stimulus energy (e.g. stationary
403404
# objects like `sky` and `city`)".
404405
#
405406
# Our result is slightly different than in [1]_, since we only use one subject,
406407
# and the voxel selection is slightly different. We also use a different
407408
# regularization parameter in each voxels, while in [1]_ all voxels use the
408-
# same regularization parameter.
409+
# same regularization parameter. Here, we do not aim at reproducing exactly the
410+
# results in [1]_, but we rather describe the general approach.
411+
412+
###############################################################################
413+
# To project the principal component on the cortical surface, we first need to
414+
# transform the primal weights of all voxels using the fitted PCA.
415+
416+
# split the ridge coefficients per delays
417+
primal_coef_per_delay = delayer.reshape_by_delays(primal_coef, axis=0)
418+
print("(n_delays, n_features, n_voxels) =", primal_coef_per_delay.shape)
419+
420+
# average over delays
421+
average_coef = np.mean(primal_coef_per_delay, axis=0)
422+
print("(n_features, n_voxels) =", average_coef.shape)
423+
424+
# transform with the fitted PCA
425+
average_coef_transformed = pca.transform(average_coef.T).T
426+
print("(n_components, n_voxels) =", average_coef_transformed.shape)
427+
428+
# We make sure vmin = -vmax, so that the colormap is centered on 0.
429+
vmax = np.percentile(np.abs(average_coef_transformed), 99.9)
430+
431+
# plot the primal weights projected on the first principal component.
432+
ax = plot_flatmap_from_mapper(average_coef_transformed[0], mapper_file,
433+
vmin=-vmax, vmax=vmax, cmap='coolwarm')
434+
plt.show()
435+
436+
###############################################################################
437+
# This flatmap shows in which brain regions the model has the largest
438+
# projection on the first component. Again, this result is different from the
439+
# one in [1]_, and should only be considered as reproducing the general
440+
# approach.
409441

410442
###############################################################################
411443
# Following [1]_, we also plot the next three principal components on the
@@ -416,6 +448,7 @@
416448
next_three_components = components[1:4].T
417449
node_sizes = np.linalg.norm(next_three_components, axis=1)
418450
node_colors = scale_to_rgb_cube(next_three_components)
451+
print("(n_nodes, n_channels) =", node_colors.shape)
419452

420453
plot_wordnet_graph(node_colors=node_colors, node_sizes=node_sizes)
421454
plt.show()
@@ -424,8 +457,23 @@
424457
# According to the authors of [1]_, "this graph shows that categories thought
425458
# to be semantically related (e.g. athletes and walking) are represented
426459
# similarly in the brain".
427-
#
428-
# Again, our results are slightly different than in [1]_, for the same reasons
460+
461+
###############################################################################
462+
# Finally, we project these principal components on the cortical surface.
463+
464+
from voxelwise_tutorials.viz import plot_3d_flatmap_from_mapper
465+
466+
voxel_colors = scale_to_rgb_cube(average_coef_transformed[1:4].T, clip=3).T
467+
print("(n_channels, n_voxels) =", voxel_colors.shape)
468+
469+
ax = plot_3d_flatmap_from_mapper(voxel_colors[0], voxel_colors[1],
470+
voxel_colors[2], mapper_file=mapper_file,
471+
vmin=0, vmax=1, vmin2=0, vmax2=1, vmin3=0,
472+
vmax3=1)
473+
plt.show()
474+
475+
###############################################################################
476+
# Again, our results are different from the ones in [1]_, for the same reasons
429477
# mentioned earlier.
430478

431479
###############################################################################

tutorials/notebooks/movies_3T/02_plot_wordnet_model.ipynb

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@
454454
},
455455
"outputs": [],
456456
"source": [
457-
"primal_coef = primal_coef[:, scores > 0.05]"
457+
"primal_coef_selection = primal_coef[:, scores > 0.05]"
458458
]
459459
},
460460
{
@@ -472,7 +472,7 @@
472472
},
473473
"outputs": [],
474474
"source": [
475-
"# split the ridge coefficients per delays\ndelayer = pipeline.named_steps['delayer']\nprimal_coef_per_delay = delayer.reshape_by_delays(primal_coef, axis=0)\nprint(\"(n_delays, n_features, n_voxels) =\", primal_coef_per_delay.shape)\n\n# average over delays\naverage_coef = np.mean(primal_coef_per_delay, axis=0)\nprint(\"(n_features, n_voxels) =\", average_coef.shape)"
475+
"# split the ridge coefficients per delays\ndelayer = pipeline.named_steps['delayer']\nprimal_coef_per_delay = delayer.reshape_by_delays(primal_coef_selection,\n axis=0)\nprint(\"(n_delays, n_features, n_voxels) =\", primal_coef_per_delay.shape)\n\n# average over delays\naverage_coef = np.mean(primal_coef_per_delay, axis=0)\nprint(\"(n_features, n_voxels) =\", average_coef.shape)"
476476
]
477477
},
478478
{
@@ -551,7 +551,32 @@
551551
"cell_type": "markdown",
552552
"metadata": {},
553553
"source": [
554-
"According to the authors of [1]_, \"this principal component distinguishes\nbetween categories with high stimulus energy (e.g. moving objects like\n`person` and `vehicle`) and those with low stimulus energy (e.g. stationary\nobjects like `sky` and `city`)\".\n\nOur result is slightly different than in [1]_, since we only use one subject,\nand the voxel selection is slightly different. We also use a different\nregularization parameter in each voxels, while in [1]_ all voxels use the\nsame regularization parameter.\n\n"
554+
"According to the authors of [1]_, \"this principal component distinguishes\nbetween categories with high stimulus energy (e.g. moving objects like\n`person` and `vehicle`) and those with low stimulus energy (e.g. stationary\nobjects like `sky` and `city`)\".\n\nOur result is slightly different than in [1]_, since we only use one subject,\nand the voxel selection is slightly different. We also use a different\nregularization parameter in each voxels, while in [1]_ all voxels use the\nsame regularization parameter. Here, we do not aim at reproducing exactly the\nresults in [1]_, but we rather describe the general approach.\n\n"
555+
]
556+
},
557+
{
558+
"cell_type": "markdown",
559+
"metadata": {},
560+
"source": [
561+
"To project the principal component on the cortical surface, we first need to\ntransform the primal weights of all voxels using the fitted PCA.\n\n"
562+
]
563+
},
564+
{
565+
"cell_type": "code",
566+
"execution_count": null,
567+
"metadata": {
568+
"collapsed": false
569+
},
570+
"outputs": [],
571+
"source": [
572+
"# split the ridge coefficients per delays\nprimal_coef_per_delay = delayer.reshape_by_delays(primal_coef, axis=0)\nprint(\"(n_delays, n_features, n_voxels) =\", primal_coef_per_delay.shape)\n\n# average over delays\naverage_coef = np.mean(primal_coef_per_delay, axis=0)\nprint(\"(n_features, n_voxels) =\", average_coef.shape)\n\n# transform with the fitted PCA\naverage_coef_transformed = pca.transform(average_coef.T).T\nprint(\"(n_components, n_voxels) =\", average_coef_transformed.shape)\n\n# We make sure vmin = -vmax, so that the colormap is centered on 0.\nvmax = np.percentile(np.abs(average_coef_transformed), 99.9)\n\n# plot the primal weights projected on the first principal component.\nax = plot_flatmap_from_mapper(average_coef_transformed[0], mapper_file,\n vmin=-vmax, vmax=vmax, cmap='coolwarm')\nplt.show()"
573+
]
574+
},
575+
{
576+
"cell_type": "markdown",
577+
"metadata": {},
578+
"source": [
579+
"This flatmap shows in which brain regions the model has the largest\nprojection on the first component. Again, this result is different from the\none in [1]_, and should only be considered as reproducing the general\napproach.\n\n"
555580
]
556581
},
557582
{
@@ -569,14 +594,39 @@
569594
},
570595
"outputs": [],
571596
"source": [
572-
"from voxelwise_tutorials.wordnet import scale_to_rgb_cube\n\nnext_three_components = components[1:4].T\nnode_sizes = np.linalg.norm(next_three_components, axis=1)\nnode_colors = scale_to_rgb_cube(next_three_components)\n\nplot_wordnet_graph(node_colors=node_colors, node_sizes=node_sizes)\nplt.show()"
597+
"from voxelwise_tutorials.wordnet import scale_to_rgb_cube\n\nnext_three_components = components[1:4].T\nnode_sizes = np.linalg.norm(next_three_components, axis=1)\nnode_colors = scale_to_rgb_cube(next_three_components)\nprint(\"(n_nodes, n_channels) =\", node_colors.shape)\n\nplot_wordnet_graph(node_colors=node_colors, node_sizes=node_sizes)\nplt.show()"
598+
]
599+
},
600+
{
601+
"cell_type": "markdown",
602+
"metadata": {},
603+
"source": [
604+
"According to the authors of [1]_, \"this graph shows that categories thought\nto be semantically related (e.g. athletes and walking) are represented\nsimilarly in the brain\".\n\n"
605+
]
606+
},
607+
{
608+
"cell_type": "markdown",
609+
"metadata": {},
610+
"source": [
611+
"Finally, we project these principal components on the cortical surface.\n\n"
612+
]
613+
},
614+
{
615+
"cell_type": "code",
616+
"execution_count": null,
617+
"metadata": {
618+
"collapsed": false
619+
},
620+
"outputs": [],
621+
"source": [
622+
"from voxelwise_tutorials.viz import plot_3d_flatmap_from_mapper\n\nvoxel_colors = scale_to_rgb_cube(average_coef_transformed[1:4].T, clip=3).T\nprint(\"(n_channels, n_voxels) =\", voxel_colors.shape)\n\nax = plot_3d_flatmap_from_mapper(voxel_colors[0], voxel_colors[1],\n voxel_colors[2], mapper_file=mapper_file,\n vmin=0, vmax=1, vmin2=0, vmax2=1, vmin3=0,\n vmax3=1)\nplt.show()"
573623
]
574624
},
575625
{
576626
"cell_type": "markdown",
577627
"metadata": {},
578628
"source": [
579-
"According to the authors of [1]_, \"this graph shows that categories thought\nto be semantically related (e.g. athletes and walking) are represented\nsimilarly in the brain\".\n\nAgain, our results are slightly different than in [1]_, for the same reasons\nmentioned earlier.\n\n"
629+
"Again, our results are different from the ones in [1]_, for the same reasons\nmentioned earlier.\n\n"
580630
]
581631
},
582632
{

0 commit comments

Comments
 (0)