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

No heatmap shown with seaborn and %matplotlib widget #391

Open
dominiquesydow opened this issue Nov 10, 2021 · 16 comments
Open

No heatmap shown with seaborn and %matplotlib widget #391

dominiquesydow opened this issue Nov 10, 2021 · 16 comments

Comments

@dominiquesydow
Copy link

Describe the issue

Thank you very much for providing this tool!

I have an apparently seaborn-related problem with showing widgets; I am posting this here first. Please let me know if you think this problem is rather on seaborn's end and I'll repost it there.


The problem: seaborn figures are not shown in JupyterLab with %matplotlib widget (they do show up with %matplotlib inline):

%matplotlib widget
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.DataFrame([[10, 20, 30, 40], [50, 30, 8, 15],
                   [25, 14, 41, 8], [7, 14, 21, 28]])
sns.heatmap(df, cmap='RdYlGn', linewidths=0.30, annot=True)

image

%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.DataFrame([[10, 20, 30, 40], [50, 30, 8, 15],
                   [25, 14, 41, 8], [7, 14, 21, 28]])
sns.heatmap(df, cmap='RdYlGn', linewidths=0.30, annot=True)

image


No problem with matplotlib:

%matplotlib widget
import matplotlib.pyplot as plt

plt.plot([[1, 2], [0, 0]])

image

Versions

ipympl version: 0.8.2
Selected Jupyter core packages...
IPython          : 7.29.0
ipykernel        : 6.4.2
ipywidgets       : 7.6.5
jupyter_client   : 7.0.6
jupyter_core     : 4.9.1
jupyter_server   : 1.11.2
jupyterlab       : 3.2.2
nbclient         : 0.5.5
nbconvert        : 6.2.0
nbformat         : 5.1.3
notebook         : 6.4.5
qtconsole        : not installed
traitlets        : 5.1.1
Known nbextensions:
  config dir: /home/dominique/.jupyter/nbconfig
    notebook section
      nbextensions_configurator/config_menu/main  enabled 
      - Validating: problems found:
        - require?  X nbextensions_configurator/config_menu/main
      contrib_nbextensions_help_item/main  enabled 
      - Validating: OK
      spellchecker/main  enabled 
      - Validating: OK
      gist_it/main  enabled 
      - Validating: OK
    tree section
      nbextensions_configurator/tree_tab/main  enabled 
      - Validating: problems found:
        - require?  X nbextensions_configurator/tree_tab/main
  config dir: /home/dominique/.local/miniconda/envs/test/etc/jupyter/nbconfig
    notebook section
      jupyter-matplotlib/extension  enabled 
      - Validating: OK
      jupyter-js-widgets/extension  enabled 
      - Validating: OK
JupyterLab v3.2.2
/home/dominique/.local/miniconda/envs/test/share/jupyter/labextensions
        jupyter-matplotlib v0.10.2 enabled OK
        @jupyter-widgets/jupyterlab-manager v3.0.1 enabled OK (python, jupyterlab_widgets)

Installed from conda-forge

mamba create -n test matplotlib pandas seaborn jupyterlab ipympl -y -c conda-forge

More versions:

# Name                    Version                   Build  Channel
matplotlib                3.4.3            py39hf3d152e_1    conda-forge
matplotlib-base           3.4.3            py39h2fa2bec_1    conda-forge
matplotlib-inline         0.1.3              pyhd8ed1ab_0    conda-forge
pandas                    1.3.4            py39hde0f152_1    conda-forge
seaborn                   0.11.2               hd8ed1ab_0    conda-forge
seaborn-base              0.11.2             pyhd8ed1ab_0    conda-forge

Do you have an idea why this is happening?

@ianhi
Copy link
Collaborator

ianhi commented Nov 10, 2021

This worked in ipympl 0.8.0 but not in 0.8.2 so this may be something to do with the new display logic. Although interestingly just calling plt.gca (which is what seaborn does) seems to work.

@ianhi
Copy link
Collaborator

ianhi commented Nov 10, 2021

@mwaskom do you have any insight? it seems like you just call plt.gca() but I suppose something that's happening in plotter.plot is making things go poorly.

@mwaskom
Copy link

mwaskom commented Nov 11, 2021

I think I'd want to know a few things

  • Is this a "seaborn" problem or a "seaborn.heatmap" problem?
  • If the latter, does a reasonably similar plot made only in matplotlib (i.e., pcolormesh with some texts on it) work?
  • If you can make a similar matplotlib plot with no issues, can you get the heatmap to work if you boil it down to the simplest version of what seaborn can draw? (i.e. no annotations, no colorbar, and disable the automatic selection of tick label density)

@dominiquesydow
Copy link
Author

dominiquesydow commented Nov 11, 2021

Thanks a lot for getting back to me so quickly!
Let me try to apply your suggestions.


it seems like you just call plt.gca() but I suppose something that's happening in plotter.plot is making things go poorly.

Do you mean like this?

%matplotlib widget
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.DataFrame([[10, 20, 30, 40], [50, 30, 8, 15], 
                   [25, 14, 41, 8], [7, 14, 21, 28]])
ax = plt.gca()
sns.heatmap(df, ax=ax)

image


  • If the latter, does a reasonably similar plot made only in matplotlib (i.e., pcolormesh with some texts on it) work?

Yes, it seems that works.

%matplotlib widget
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.DataFrame([[10, 20, 30, 40], [50, 30, 8, 15], 
                   [25, 14, 41, 8], [7, 14, 21, 28]])

plt.pcolormesh(df)

for y in range(df.shape[0]):
    for x in range(df.shape[1]):
        plt.text(
            x + 0.5, y + 0.5, "%.1f" % df.iloc[x, y],
            horizontalalignment="center",
            verticalalignment="center",
        )

image


  • If you can make a similar matplotlib plot with no issues, can you get the heatmap to work if you boil it down to the simplest version of what seaborn can draw? (i.e. no annotations, no colorbar, and disable the automatic selection of tick label density)
%matplotlib widget
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.DataFrame([[10, 20, 30, 40], [50, 30, 8, 15], 
                   [25, 14, 41, 8], [7, 14, 21, 28]])
sns.heatmap(df)

image

The same behaviour with

sns.heatmap(df, xticklabels=False, yticklabels=False)

and

sns.heatmap(df, xticklabels=True, yticklabels=True)

assuming this is what was meant with

disable the automatic selection of tick label density

@mwaskom
Copy link

mwaskom commented Nov 11, 2021

Yes that's right about the tick labels. But you could also try isolating the colorbar: it's on by default in the seaborn plot, so you could try turning it off there (cbar=False and turning it on for the matplotlib plot (plt.colorbar).

But I think that doesn't answer the other question which is ... can you use other seaborn functions, or is this an issue specific to heatmap?

@ianhi
Copy link
Collaborator

ianhi commented Nov 11, 2021

A crucial thing in these tests is probably to always start with plt.close('all') so that the behavior of plt.gca is consistent

@ianhi
Copy link
Collaborator

ianhi commented Nov 11, 2021

Also @dominiquesydow can you please post the code snippets as text so that they are copy-pasteable - thanks!

@dominiquesydow
Copy link
Author

Hi @ianhi,

Also @dominiquesydow can you please post the code snippets as text so that they are copy-pasteable - thanks!

I have updated my comment with copy-pasteable code.

Also, I have tried to investigate your initial question (my apologies for not getting to at first)

  • Is this a "seaborn" problem or a "seaborn.heatmap" problem?

I set up this notebook; below a summary:

  • Other seaborn plots seem fine to me.
  • I tried two versions that show the same behaviour
    • (1) Define figure and axes (fig, ax = plt.subplots(nrows=1, ncols=1)) and pass axis to seaborn functions (ax parameter)
    • (2) Close all axes and then get current axis (plt.close('all') followed by ax = plt.gca())
  • Interesting observation: Maybe the seaborn heatmap tries to draw to the axis before the current axis (see the end of the posted notebook)
    • Procedure: 1. I draw e.g. a scatter plot, 2. I draw heatmap without clearing axes
    • Result: The heatmap is drawn on top of the previous plot.
  • Note: I see the same behaviour with Jupyter Lab and Jupyter Notebook
  • Note: I do not see any plots when running all cells at once; I have to run cell-by-cell

@mwaskom
Copy link

mwaskom commented Nov 18, 2021

That behavior all looks correct to me. If you don't provide seaborn with an Axes target, it plots on the "current" Axes (creating it if necessary). The Jupyter inline backend calls plt.close behind the scenes after it executes every cell, but ipyml doesn't (so e.g. you can create a plot in one cell then update it by doing something in another one).

@01baftb
Copy link

01baftb commented Nov 19, 2021

I am having similar issue #60 (comment)

@dominiquesydow
Copy link
Author

dominiquesydow commented Nov 19, 2021

Hi @mwaskom,

Thanks for getting back to me.
I am showing a minimal example here to show what is still confusing me.

# First cell
%matplotlib widget
import matplotlib.pyplot as plt
import seaborn as sns
tips = sns.load_dataset("tips")

fig, ax = plt.subplots(nrows=1, ncols=1)
sns.scatterplot(data=tips, x="total_bill", y="tip", hue="time", ax=ax)

This works nicely, I get the plot:
image

Then, I call plt.close as you suggested:

# Second cell
plt.close()

Then, I try to plot sns.heatmap and get an empty plot:

# Third cell
import numpy as np

uniform_data = np.random.rand(10, 12)

fig, ax = plt.subplots(nrows=1, ncols=1)
sns.heatmap(uniform_data, ax=ax)

image

Do you have an idea on how to make the last plot appear?

If you don't provide seaborn with an Axes target, it plots on the "current" Axes (creating it if necessary). The Jupyter inline backend calls plt.close behind the scenes after it executes every cell, but ipyml doesn't (so e.g. you can create a plot in one cell then update it by doing something in another one).

With ax=ax, I am providing sns.heatmap with an Axes target (at least I think I am); I was expecting ipympl to use that Axes as well.

@mwaskom
Copy link

mwaskom commented Nov 19, 2021

I'm confused about how what you're describing there is not represented in the notebook you shared? You seem to be plotting heatmap just fine there?

@dominiquesydow
Copy link
Author

My apologies, apparently uploading the notebook to GH makes the heatmap appear... running the same notebook locally shows the behaviour discussed in this comment.

For the time being, I will pin ipympl to 0.8.0; here the seaborn heatmaps still appear as expected.

@dominiquesydow dominiquesydow changed the title No figures shown with seaborn and %matplotlib widget No heatmap shown with seaborn and %matplotlib widget Nov 19, 2021
@mwaskom
Copy link

mwaskom commented Nov 19, 2021

Oh that's interesting! I'd say this sounds like an issue on the ipympl side of things. I wish I could offer a hypothesis based on the fact that it seems to happen with heatmaps, but nothing comes immediately to mind beyond what I suggested above.

@dominiquesydow
Copy link
Author

Thanks for taking the time to discuss this issue with me.

Although I cannot offer a solution with the latest ipympl version, downgrading to 0.8.0 helped; I am therefore closing this issue. Please re-open if more discussion is needed for a solution for the latest version.

@ianhi
Copy link
Collaborator

ianhi commented Nov 30, 2021

Please re-open if more discussion is needed for a solution for the latest version.

Yes this is definitely a bug than needs fixing - thanks for finding it!

@ianhi ianhi reopened this Nov 30, 2021
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

No branches or pull requests

4 participants