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] Colorbar ticks at threshold values #2887
[ENH] Colorbar ticks at threshold values #2887
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2887 +/- ##
==========================================
+ Coverage 91.81% 91.83% +0.01%
==========================================
Files 144 144
Lines 16173 16209 +36
Branches 3360 3373 +13
==========================================
+ Hits 14850 14886 +36
Misses 781 781
Partials 542 542
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
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, thx !
- If we have an symmetric colorbar, don't we want the same behavior: on tick at the unique threshold value ?
- What about view_img ?
either that or removing the 0? |
I implemented something alike which swaps the closest tick with the threshold value. So if the threshold is closer to zero, zero will be replaced by the threshold value: Example: import nibabel as nib
import numpy as np
import matplotlib.pyplot as plt
from nilearn import plotting
# Create some fake data going from 0 to 10
img_data = np.zeros((10, 10, 10))
img_data[4:6, 2:4, 4:6] = 5
img_data[5:7, 3:7, 3:6] = 10
img = nib.Nifti1Image(img_data, affine=np.eye(4))
fig, axs = plt.subplots(4, 2)
fig.set_size_inches((15, 10))
for i,threshold in enumerate([0, 0.1, 1.3, 2.5, 4.9, 7.5, 8, 9.9]):
plotting.plot_stat_map(img, threshold=threshold,
title=f"threshold = {threshold}",
axes=axs[i//2,i%2])
plt.savefig("out.jpeg")
Indeed, I need to look at other plotting functions with thresholded colorbars which don't rely on the |
Thx. In the example above, the case with threshold=8 is weird: the colormap is clipped at 8 ? |
c180e71
to
685bfb2
Compare
At least it looks good now. Are the codecov warning serious ? |
9c4e826
to
eca1f35
Compare
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, thx.
92aafdc
to
fcd2637
Compare
@NicolasGensollen what is the status of this one? after having a quick look it looks like it could be merged before the next release? |
It's not clear to me why this was never merged. Did it get blocked by something? is this behavior still desriable? |
To check: increase of warnings?
|
TODO:
|
@michellewang |
I did some (basic) manual tests with some of the surface plotting functions. The threshold ticks seem to work for from nilearn import datasets
from nilearn import plotting
stat_img = datasets.load_sample_motor_activation_image()
plotting.plot_img_on_surf(
stat_img,
views=['lateral', 'medial'],
hemispheres=['left', 'right'],
colorbar=True,
vmin=-5,
vmax=10,
symmetric_cbar=False,
threshold=2,
cmap='viridis',
) That's because in def plot_img_on_surf(...
cbar_tick_format='%i', # ADD new parameter with default tick format
...):
...
# around line 1464
if colorbar:
sm = _colorbar_from_array(
image.get_data(stat_map),
vmin,
vmax,
threshold,
symmetric_cbar=symmetric_cbar,
cmap=plt.get_cmap(cmap),
)
cbar_grid = gridspec.GridSpecFromSubplotSpec(3, 3, grid[-1, :])
cbar_ax = fig.add_subplot(cbar_grid[1])
axes.append(cbar_ax)
# ADD: get custom ticks
ticks = _get_ticks_matplotlib(vmin, vmax, cbar_tick_format, threshold)
# UPDATE: set ticks and format when making the colorbar
fig.colorbar(sm, cax=cbar_ax, orientation='horizontal', ticks=ticks, format=cbar_tick_format)
... Plot with modified code: This branch doesn't include the changes I made in #3993 yet, but the new colorbar ticks work for I also checked the test failures, I don't think they're directly related to anything I added, but I think I figured out why they failed.
This is a weird one. Running the code manually shows that the two colorbars correspond to each other well (see below, left is Matplotlib, right is Plotly). But the Matplotlib plot has the smallest This can be fixed by changing the test so that it uses something like if len(ticks) > 0 and ticks[0] < vmin:
ticks[0] = vmin
^ This one failed for the same reason as the previous one.
I think this one can be fixed by making sure that |
Co-authored-by: Michelle Wang <tomichellewang@gmail.com>
Co-authored-by: Michelle Wang <tomichellewang@gmail.com>
I think it's good for merging now. |
Agreed |
Fixes #2833
This PR proposes to display the threshold on the colorbar when plotting statistical maps.
The proposed solutions impacts only symmetrical colorbars and works with any odd number of ticks (5 was hardcoded prior to this PR).
Example