Skip to content
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

Passing negative values as threshold for plotting #4340

Open
Remi-Gau opened this issue Mar 24, 2024 · 9 comments · May be fixed by #4338
Open

Passing negative values as threshold for plotting #4340

Remi-Gau opened this issue Mar 24, 2024 · 9 comments · May be fixed by #4338
Assignees
Labels
Bug for bug reports Plotting The issue is related to plotting functionalities.

Comments

@Remi-Gau
Copy link
Collaborator

Remi-Gau commented Mar 24, 2024

Note passing a negative values as threshold is ignored and does not throw warnings:

"""Test plotting asymmetric color bar."""

import matplotlib.pyplot as plt
import numpy as np

from nilearn import datasets, plotting, surface
from nilearn.image import threshold_img

vmin = None
vmax = None
symmetric_cbar = False
threshold = -0.5 

stat_img = datasets.load_sample_motor_activation_image()

fsaverage = datasets.fetch_surf_fsaverage()

curv_right = surface.load_surf_data(fsaverage.curv_right)
curv_right_sign = np.sign(curv_right)

texture = surface.vol_to_surf(stat_img, fsaverage.pial_right)

engine = "matplotlib"

plotting.plot_surf_stat_map(
    fsaverage.infl_right,
    texture,
    hemi="right",
    title="Surface right hemisphere",
    colorbar=True,
    threshold=threshold,
    bg_map=curv_right_sign,
    engine=engine,
    symmetric_cbar=False,
    cmap="black_red",
    vmin = vmin,
    vmax = vmax
)
plt.show()

gives

Figure_1

Where as I would expect the same as for threshold = 0.5 given that the threshold is supposed to act on absolute value according to the doc.

Figure_2

Originally posted by @Remi-Gau in #4296 (comment)

@Remi-Gau
Copy link
Collaborator Author

@bthirion said:

It's unclear to me whether the threshold has "one-tail" or "two-tail" behavior. The doc implies that is it two-tail, but we cold have cases where a one-tail behavior is expected ?

@Remi-Gau
Copy link
Collaborator Author

It's unclear to me whether the threshold has "one-tail" or "two-tail" behavior. The doc implies that is it two-tail, but we cold have cases where a one-tail behavior is expected ?

That was why I was testing this. Less common but visualizing "deactivations" only may be something users want to do.

I'd be in favor of doing this in another PR after #4338 (even it means reverting it) just to make sure that we first align doc and behavior with the minimum amount of changes to the code.

@Remi-Gau
Copy link
Collaborator Author

@bthirion I created a separate issue to make discussions easier.
Moved your comment here.

@Remi-Gau
Copy link
Collaborator Author

Remi-Gau commented Mar 25, 2024

In relation to #4338 (comment)

I'm wondering whether this is right. You could be in situations where you want to keep everything that's above -1, no ?
Why not leave the responsibility to the user ?

Tried to see what the plotting behavior is at the moment:

top row the image is unthresholded before plotting, bottom row it is threshold is one tail thresholded at -1
left column: plotting threshold is -1 and right column it is 1

import matplotlib.pyplot as plt

from nilearn import datasets, plotting,
from nilearn.image import threshold_img

stat_img = datasets.load_sample_motor_activation_image()

thresholded_img = threshold_img(
    stat_img,
    threshold=-1,
    cluster_threshold=0,
    two_sided=False,
    copy=True,
)

fig, axes = plt.subplots(
    2,
    2,
    figsize=(20, 10),
)
for i, image in enumerate([stat_img, thresholded_img]):
    for j ,threshold in enumerate([-1, 1]):
        txt = "unthresholded"
        if image == thresholded_img:
            txt = "thresholded at -1"
        plotting.plot_stat_map(
        image,
        colorbar=True,
        threshold=threshold,
        symmetric_cbar=False,
        cmap="black_red",
        title=f"image {txt}; plotting threshold: {threshold}",
        axes = axes[i,j]
    )
plt.show()

Figure_1

OK so we do want to make sure that people can plot things like in the bottom left (only see things above a negative threshold). As #4338 goes it would prevent this and for users to only be able to get what's in the bottom right.

At the same time, the top left is very unclear as to what one would expect to see.

@bthirion
Copy link
Member

To me it makes sense: it means that the plotting threshold is a property of the colorbar, not of the image.

@Remi-Gau
Copy link
Collaborator Author

To me it makes sense: it means that the plotting threshold is a property of the colorbar, not of the image.

So this would be "just" a color bar bug for you? That seems fair.

@Remi-Gau Remi-Gau added the Bug for bug reports label Mar 25, 2024
@bthirion
Copy link
Member

Can you clarify what the bug is in the above example ?

@Remi-Gau
Copy link
Collaborator Author

Can you clarify what the bug is in the above example ?

bottom left (image thresholded at -1; plotting threshold: -1)

The doc says:

If a number is given, it is used to threshold the image: values below the threshold (in absolute value) are plotted as transparent.

So I would not expect to see anything between -1 and 1.

I understand that some people may want to see values that are > -1, but I would not expect the code to be able to do that given the doc.

top left (image unthresholded; plotting threshold: -1)

  • I would expect the colorbar to show the region between -1 and 1 as grey.

@Remi-Gau Remi-Gau added the Plotting The issue is related to plotting functionalities. label Mar 28, 2024
@bthirion
Copy link
Member

OK, so when the threshold is negative, there another behavior that the one documented. We need to decide whether we are please with it. In any case, we need to revise the doc.

@Remi-Gau Remi-Gau self-assigned this Apr 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug for bug reports Plotting The issue is related to plotting functionalities.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants