Nilearn.plotting.plot_surf_stat_map: What does it plot?

It seems it doesn’t plot the input data but instead it computes some function (average?) of the vertices within a face (triangle), then displays that value assigned to the face, as opposed to colors being painted in a gradient along the edges (which is what we’d expect).

Is this right? Then how to change this behavior so that the colors are applied to the vertices using the original (actual) values, not averaged?

Thanks!

why do you expect that, can you point to a reference or another software that does this kind of plot without assigning a color to every face?

in nilearn you cannot control this

Hi Jerome,

Thank you for commenting.

Yes, FreeSurfer and SurfIce, for example, do color data per vertex, which is truthful to the actual data. I care quite a lot about this because it makes a difference on whether one wants to show facewise or vertexwise data – please see Figure 12 of my (and others’) 2012 Neuroimage paper: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3641659/

Since opening the post I have confirmed that what Nilearn plots is the average of the 3 vertices, which is then used to color each face. It’s problematic: say x_i is the value in vertex i, and y_i = f(x_i) is some non-linear function of that value. Let “c” denote the index of some cutoff vertex. Then a map of x_i > x_c should be the same as a map of y_i > y_c. But because of the averaging that happens in the middle, this guarantee is lost, and the maps can differ.

Another example of a problem: say you discover that you have an outlier value in some vertex. Then you make a figure to see where it’s located. Because of the averaging, the difference that was extreme has now been reduced by an expected factor of 2/3, so that original outlier may now appear as a quite reasonable value, and spread across the faces that have that vertex in common, maybe even undistinguishable from the other values in the map.

It’d be great if in the future this behavior could be changed. We know it’s possible because the surface rendered as underlay (with the sulcal morphology in gray) does have its shades colored correctly or, at least, not in a triangle-wise manner. So there is surely a way to do it, even if not available to the user at the moment.

Thanks!

All the best,

Anderson

Hello, thanks for the clarification. very interesting paper!
indeed with the plot_surf... nilearn functions you cannot change this, because it is done by matplotlib’s plot_trisurf which expects one color per face. this is the case both for the stat map and the background.

you can use nilearn.plotting.view_surf which I think does what you want

import numpy as np
from nilearn.plotting import view_surf

coords = np.asarray([[0, 1, 0], [0, 0, 1], [0, 0, 0]])
stat = np.asarray([0, 1, 2])
triangles = np.asarray([[0, 1, 2]])

view_surf((coords, triangles), stat).open_in_browser()

Excellent, many thanks. Sounds like that’s what we need. Thanks!
Anderson

This was an interesting exchange. I think that we could improve the documentation of both functions.

Anderson, would you mind doing a pull request for this?

Thanks!!

I could do, but I don’t know where or how to fix, so someone else would need to do it…