New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ENH] Improve plotting contours for PlotlySurfaceFigure
objects by adding add_contours
method
#3949
base: main
Are you sure you want to change the base?
Conversation
👋 @psadil Thanks for creating a PR! Until this PR is ready for review, you can include the [WIP] tag in its title, or leave it as a github draft. Please make sure it is compliant with our contributing guidelines. In particular, be sure it checks the boxes listed below.
For new features:
For bug fixes:
We will review it as quick as possible, feel free to ping us with questions if needed. |
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #3949 +/- ##
==========================================
+ Coverage 91.77% 91.80% +0.03%
==========================================
Files 134 134
Lines 15751 15822 +71
Branches 3283 3298 +15
==========================================
+ Hits 14455 14526 +71
Misses 752 752
Partials 544 544
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
@psadil thanks for getting started on this! Will try to start a review this week |
PlotlySurfaceFigure
objects by adding add_contours
method
Tests added! Do these seem like they're on the right track? |
Thanks!!
Had a very quick look: it does help also understand how these methods are used, so definitely useful |
Co-authored-by: Remi Gau <remi_gau@hotmail.com>
Co-authored-by: Remi Gau <remi_gau@hotmail.com>
Co-authored-by: Remi Gau <remi_gau@hotmail.com>
Thanks @psadil for the updates! Here is the built example: https://output.circle-artifacts.com/output/job/9e7e0100-bdac-4eaf-99d5-b5d2f512e8bd/artifacts/0/dev/auto_examples/01_plotting/plot_3d_map_to_surface_projection.html#sphx-glr-auto-examples-01-plotting-plot-3d-map-to-surface-projection-py It looks good! There is a small skip that I see in the postcentral gyrus contour. Idk if that can be improved further. And the other contour is hard to see but I guess that is to showcase the line width feature. Also the API reference looks good: https://output.circle-artifacts.com/output/job/9e7e0100-bdac-4eaf-99d5-b5d2f512e8bd/artifacts/0/dev/modules/generated/nilearn.plotting.displays.PlotlySurfaceFigure.html#nilearn.plotting.displays.PlotlySurfaceFigure |
BTW while checking this I noticed that in the same example where |
Oh dear, thanks. I think this might be a rendering issue. But let me find a way to either confirm or fix. Aiming for the next couple of days. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM besides the last glitch mentioned by @ymzayek
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly small doc stuff. I think this is in a good enough state and we can merge after addressing these. A follow-up PR can be done to address the small skip to close the contour. I don't think it should block this
@@ -134,11 +134,15 @@ | |||
############################################################################## | |||
# Display outlines of the regions of interest on top of a statistical map | |||
# ----------------------------------------------------------------------- | |||
# | |||
# Regions can be outlined using both engines. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a line clarifying that for the default matplotlib engine used by plot_surf_stat_map
, plotting.plot_surf_contours
is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes me also think we should raise an error in plot_surf_contours
if plotly object is passed. Now we get the error AttributeError: 'PlotlySurfaceFigure' object has no attribute 'axes'
but it would be better to raise one specifying that plot_surf_contours
only works with matplotlib. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes a more explicit error message would be a good thing for users
# Note that the contours are added with a method of the object that is | ||
# returned by :func:`~nilearn.plotting.plot_surf_stat_map`: | ||
# :meth:`~nilearn.plotting.displays.PlotlySurfaceFigure.add_contours`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Note that the contours are added with a method of the object that is | |
# returned by :func:`~nilearn.plotting.plot_surf_stat_map`: | |
# :meth:`~nilearn.plotting.displays.PlotlySurfaceFigure.add_contours`. | |
# Note that the contours are added with | |
# :meth:`~nilearn.plotting.displays.PlotlySurfaceFigure.add_contours` | |
# method of a :class:`~nilearn.plotting.displays.PlotlySurfaceFigure` object | |
# that is returned by :func:`~nilearn.plotting.plot_surf_stat_map` | |
# when engine is set to "plotly". |
""" | ||
Draw boundaries around roi. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for consistency
""" | |
Draw boundaries around roi. | |
"""Draw boundaries around roi. |
The value at each vertex one inside the ROI and zero inside ROI, | ||
or an :obj:`int` giving the label number for atlases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
??
The value at each vertex one inside the ROI and zero inside ROI, | |
or an :obj:`int` giving the label number for atlases. | |
The value at each vertex is one inside the ROI and zero outside | |
the ROI, or an :obj:`int` giving the label number for atlases. |
""" | ||
Identify which vertices lie on the outer edge of a parcellation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
""" | |
Identify which vertices lie on the outer edge of a parcellation. | |
"""Identify which vertices lie on the outer edge of a parcellation. |
|
||
Returns | ||
------- | ||
data : :class:`numpy.ndarray` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
data : :class:`numpy.ndarray` | |
sorted_vertices : :class:`numpy.ndarray` |
Oh can you also add a whatsnew entry in |
Just to give an update, I'm now suspecting a bug, though I'm not sure of the source. Plotting the So, I'm hoping to sort this out before the pull request is merged. |
I see in that case we'll hold off until that is resolved. Thanks @psadil |
Here's a wireframe view of the surface to help clarify the situation: Vertices in the roi are marked with circles. The circles are orange when they are on the edge of the boundary (defined as a vertex of a triangle inside the roi and on a face with only two vertices in the roi) and otherwise purple. Building up the boundary edge by sequentially selecting the next closest vertex ends up skipping the orange vertex that is lowest in the figure (the one with only one orange neighbor). Is there an expectation for how to trace this boundary? I see these options
|
@psadil first thought would be to go with the third option since it seems most conservative, however the visual consequence of overlapping boundaries is not clear. We'd need to test it. |
Sorry, but hoping to check another implementation detail. I wonder how to handle drawing handle regions that do not share an edge with another vertex in the roi. For example, this region has 2 isolated vertices. Should I follow the matplotlib approach? I think that would mean ignoring the isolated vertices. |
@psadil thanks for checking that. I think then it would be best to stay consistent with the matplotlib approach and ignore isolated vertices. That would then be more like the 2nd option you describe in #3949 (comment)? |
It wouldn't quite be the 2nd option, because it looks like the current matplotlib approach colors the faces around vertices that share only one edge with another vertex in the ROI. For example, here is the post-central gyrus contour in matplotlib In the plotly implementation, I think that a comparable boundary could be the one traced by the purple line in the following (the vertex with only one shared edge is included in the contour) |
I don't know if there are conventions somewhere that explain what is best. If there aren't I would go for the easiest and most maintainable solution (and possibly a warning if some vertices have to be missed). |
Thanks for all the input. I'll work on something that tries to match the matplotlib approach (unless someone encounters another convention in the meanwhile). FWIW, the behavior of plot_surf_roi includes isolated vertices. But hopefully a clear explanation of how the contours are generated (and warnings about when an isolated vertex is excluded) will avoid too much confusion. |
@psadil would you have the bandwidth to finish this in the next month or two? It would be great to include it in the major release we are planning for January. Thanks for all your work on this! |
Changes proposed in this pull request:
add_contours
method toPlotlySurfaceFigure
, increasing customizability of contour lines.