Skip to content

13204: Fix label border rendering issue on flat brain surfaces #13219

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

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

scrharsh
Copy link

Reference issue

Fixes #13204.

What does this implement/fix?

This pull request addresses an issue where label borders could not be rendered correctly on flat brain surfaces during 3D plotting. Attempting to render borders in this context previously led to errors or misleading visuals.

Changes include:

  • A conditional check to detect flat surfaces (is_flat).
  • Emitting a warning when borders=True on flat surfaces:
    "Label borders cannot be displayed on flat surfaces. Skipping borders."
  • Skipping border rendering entirely if the surface is flat.
  • Added a test to ensure the warning is correctly raised and handled.

Additional information

This fix improves visualization reliability and provides informative user feedback when label borders are incompatible with flat surface rendering.

@wmvanvliet
Copy link
Contributor

There seem to be other changed mixed in with the PR.

@scrharsh
Copy link
Author

There seem to be other changed mixed in with the PR.

Thanks for pointing that out! Those changes weren’t meant to be part of this PR — I’ll clean it up and push an update shortly.

Copy link
Author

@scrharsh scrharsh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the required changes are done.

test_output.edf Outdated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this file. If a file is needed for testing, we typically either create it on the fly, or incorporate it into https://github.com/mne-tools/mne-testing-data

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please guide me about this?

Comment on lines 2265 to 2267
from warnings import warn

import numpy as np
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imports must go at top of file (or if they need to be nested inside funcs/classes to avoid circular import: then at the top of the func/class def).

Please install our pre-commit hooks, they would have caught this (and other) style errors.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have commit the changes suggested.

w[-1].message
)

print("Test passed!")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no print statements in tests please.

Comment on lines 59 to 60
# Run the test
test_label_borders()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't call test functions directly; pytest does that for us.

Comment on lines 11 to 13
subjects_dir = os.path.expanduser(
"~/mne_data/MNE-sample-data/subjects"
) # Adjust the path as needed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general, don't assume the data folder is in ~; use mne.get_config("MNE_DATA").

But for built-in datasets there is the preferable mne.datasets.sample.data_path()

Comment on lines 34 to 36
warnings.warn(
"Label borders cannot be displayed on flat surfaces. Skipping borders."
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general, don't raise warnings inside a test function.

Comment on lines 2273 to 2276
warn(
"Label borders cannot be displayed on flat surfaces. Skipping borders."
)
borders = False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'd prefer to actually make it work to show borders on flat brains, rather than just warning that it's not possible!

@scrharsh scrharsh requested a review from drammock April 18, 2025 15:06
@scrharsh
Copy link
Author

@larsoner please have a look.

Copy link
Member

@drammock drammock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, if you want another review, first post a screenshot of a plot of a flat brain that shows the label borders looking as they ought to.

@@ -10,6 +10,7 @@
import warnings
from functools import partial
from io import BytesIO
from warnings import warn
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert. we have our own internal warn function (and logger) in mne.utils

@@ -51,7 +52,6 @@
logger,
use_log_level,
verbose,
warn,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert.

Comment on lines 2267 to 2292
if is_flat:
# Instead of warning, calculate and show the borders for flat surfaces
keep_idx = _mesh_borders(self.geo[hemi].faces, scalars)
show = np.zeros(scalars.size, dtype=np.int64)
if isinstance(borders, int):
for _ in range(borders):
# Refine border calculation by checking neighboring borders
keep_idx = np.isin(self.geo[hemi].faces.ravel(), keep_idx)
keep_idx.shape = self.geo[hemi].faces.shape
keep_idx = self.geo[hemi].faces[np.any(keep_idx, axis=1)]
keep_idx = np.unique(keep_idx)
show[keep_idx] = 1
scalars *= show # Apply the border filter to the scalars

else:
# For non-flat surfaces, proceed with the existing logic
keep_idx = _mesh_borders(self.geo[hemi].faces, scalars)
show = np.zeros(scalars.size, dtype=np.int64)
if isinstance(borders, int):
for _ in range(borders):
keep_idx = np.isin(self.geo[hemi].faces.ravel(), keep_idx)
keep_idx.shape = self.geo[hemi].faces.shape
keep_idx = self.geo[hemi].faces[np.any(keep_idx, axis=1)]
keep_idx = np.unique(keep_idx)
show[keep_idx] = 1
scalars *= show
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these if and else blocks are identical. How does this solve the problem?

result = brain.add_label(label, borders=borders)
assert expected in result

# Use internal projection and rendering functions to avoid vulture error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a vulture allowlist for genuine false-positives tools/vulture_allowlist.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Showing label borders is not possible on the flat brain surface
3 participants