posit-dev / positron

Positron, a next-generation data science IDE
https://positron.posit.co
Other
2.83k stars 91 forks source link

plot window hides elements in a matplotlib chart #5068

Open JosephBARBIERDARNAL opened 1 month ago

JosephBARBIERDARNAL commented 1 month ago

System details:

Positron and OS details:

Positron Version: 2024.08.0 (Universal) build 48 Code - OSS Version: 1.91.0 Commit: ed616b36655fb24d116108bdd833f1321704315b Date: 2024-08-19T04:26:51.868Z Electron: 29.4.0 Chromium: 122.0.6261.156 Node.js: 20.9.0 V8: 12.2.281.27-electron.0 OS: Darwin arm64 23.6.0

Interpreter details:

Python 3.12.5

Describe the issue:

For example, when I add an annotation to a matplotlib graph, if its position is outside certain values, it will not be displayed in the plot window.

The values in question appear to be outside 0 and 1 in the coordinates of the figure for the x and y axis.

Steps to reproduce the issue:

pip install matplotlib==3.9.2
import matplotlib.pyplot as plt

# not visible
fig, ax = plt.subplots()
fig.text(
    x=0.5, y=1, s='title'
)
plt.show()

# visible
fig, ax = plt.subplots()
fig.text(
    x=0.5, y=0.9, s='title'
)
plt.show()

Image

Expected or desired behavior:

Ideally, the plot window should zoom out (or similar) to ensure that it fits all the elements of the matplotlib figure.

testlabauto commented 1 month ago

Hi! Thanks for using Positron.

I am not 100% sure if this is an issue with Positron or perhaps just an issue with usage. Could you try this and see if it meets your needs?

import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot()

ax1.title.set_text('Title')

plt.show()

I ask because when i try to repro your original snippet outside Positron, I get the same result and with the snippet I provided, the title looks good.

A larger example: https://stackoverflow.com/questions/25239933/how-to-add-a-title-to-each-subplot

JosephBARBIERDARNAL commented 1 month ago

It's strange that this works when adding a title, but not when using text().

To be clearer about what I meant in the first place, ideally I should see on the plot window what I would see in a normal notebook or if I saved the plot as a png.

For example, this:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
fig.text(
    x=0.5, y=1, s='title', size=20
)
plt.tight_layout()
plt.savefig('positron.png', bbox_inches='tight')
plt.show()

gives me 2 differents results. positron.png (or what I would have had in a notebook) looks like:

Image

But in positron the plot window gives me:

Image

JosephBARBIERDARNAL commented 1 month ago

Interestingly, this works perfectly:

import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot()

ax1.set_title('title', y=1.3) # higher position

plt.show()

Image

testlabauto commented 1 month ago

Thank you for the additional example! I do see what you mean when comparing to a notebook (with the savefig line commented out).

I will move this issue to triage for prioritization.

jmcphers commented 1 month ago

Triage: @JosephBARBIERDARNAL does this repro with the latest release of Positron for you? https://github.com/posit-dev/positron/releases

JosephBARBIERDARNAL commented 1 month ago

Triage: @JosephBARBIERDARNAL does this repro with the latest release of Positron for you? https://github.com/posit-dev/positron/releases

I installed it a few days before opening my issue, so yes!

seeM commented 6 days ago

This issue is a result of our chosen defaults to try to work around limitations in matplotlib's layout system. I posted more in-depth about the limitations and our decisions in the Layout section of this comment but let me try to summarise what's relevant here.

In short, in matplotlib we can only choose one of the following default behaviors:

  1. Produce an image of the exact requested pixel size.
  2. Produce an image that contains all of the figure elements.

We originally opted for 1, but I'm wondering if we should use 2 when the intrinsic sizing policy is used (i.e. "Matplotlib (6in x 4in)" is selected). It would mean that our plots exactly match Jupyter Notebooks in that case. @petetronic curious to hear your thoughts.

EDIT: One consequence of going with the 2nd approach: If we don't have guarantees about the pixel size it might complicate what we show in the save plot modal when "Use intrinsic size" is checked. We could try to get the actual pixel size of the produced image? Might be confusing where that comes from.

JosephBARBIERDARNAL commented 6 days ago

I’m not sure if this will help, but here are a few things that matter (or don’t) to me as a heavy user of Matplotlib who really likes Positron, and ideally plans to continue using it in the future:

seeM commented 6 days ago

@JosephBARBIERDARNAL thank you very much for sharing, this is very helpful!

I think the correct move is to update our matplotlib backend to produce images that match those produced via the Jupyter Notebook matplotlib backend when the intrinsic size is used, using whichever layout engine / bbox_inches setting is required for that.