Phlya / adjustText

A small library for automatically adjustment of text position in matplotlib plots to minimize overlaps.
https://adjusttext.readthedocs.io/
MIT License
1.49k stars 87 forks source link

Texts may fly away in v0.8.0 when `savefig` directly #138

Closed YDX-2147483647 closed 1 year ago

YDX-2147483647 commented 1 year ago

Example

Note: Save it as a script (*.py). There's no such issue when in Jupyter Notebook.

from adjustText import adjust_text
from matplotlib.pyplot import subplots

fig, ax = subplots()

x = 1.04
ax.plot([x], [0], marker=".")
texts = [ax.text(x=x, y=0, s="text")]

# fig.savefig("output-original.png")

adjust_text(texts)
fig.savefig("output.png")

output

Further Details

Flying away

If you let x ranges from 1 to 1.04 or 0 to 0.03, you'll find the text is drawn, but at a wrong position.

More `output.png` ![output-1 000](https://user-images.githubusercontent.com/73375426/220334887-d19c41fb-4295-45af-a1fb-e6d6bf5676f9.png) ![output-1 010](https://user-images.githubusercontent.com/73375426/220334894-5c0e785f-79ce-499e-8c56-68d1e0d39d95.png) ![output-1 020](https://user-images.githubusercontent.com/73375426/220334898-0bf8f110-e536-4831-86eb-fa0e2b2b2672.png) ![output-1 030](https://user-images.githubusercontent.com/73375426/220334901-ab468a17-67b4-4c17-bb63-49b1691bd86e.png)

Arrows

Arrows are not drawn correctly either. (e.g.: adjust_text(texts, arrowprops=dict(arrowstyle="-", color="gray")))

output

Workaround

Uncomment fig.savefig("output-original.png"), and it works again.

output-original.png: output-original

output.png: output

Additional information

I met this issue in a complicated plot after upgrading from v0.7.3.1. git bisect (+ editable install adjustText + manually ax.axesPatchax.patch) there tells the first bad commit is from #64, in which the coordinate system was changed from axes to display.

I can reproduce the issue in a fresh venv, but I didn't git bisect again.

Phlya commented 1 year ago

Mh... Does this only happen with a single point coordinate?

Can try calling plt.autoscale() before adjust_text?

YDX-2147483647 commented 1 year ago

Does this only happen with a single point coordinate?

No. The above is only a MWE.

output

autoscale() before adjust_text()

No, but ax.autoscale_view() works.

Phlya commented 1 year ago

Interesting, thank you! Maybe this call should just be added to the beginning of adjust_text() together with plt.draw(). Any reason not to?

YDX-2147483647 commented 1 year ago

Wait… autoscale_view() fix the MWE, but not my complicated plot: texts are nicely placed, but arrows are still crazy…

(I need some time to debug, as the plot has cutomized scale, transforms, etc.)

Phlya commented 1 year ago

Mh... Sorry to hear that.

I want to mention, I am working on a complete rewrite of the engine for all overlap calculations that would make everything super-mega fast (compared to super-mega slow at the moment). So while it would make it easier to debug everything, actually if there are issues with the coordinate transformations in some cases, they also need to be solved independently, and I find it quite confusing myself... So for the next version would be great if you want to look into it a bit.

YDX-2147483647 commented 1 year ago

I see… Is there an issue / draft PR (for the rewrite) that I can subscribe to?

(I'll close this issue because autoscale_view() resolves that problem.)


The following is another MWE. (I believe it'll be fixed after the rewrite, so you can ignore it.)

from adjustText import adjust_text
from matplotlib.pyplot import subplots

fig, ax = subplots()

xs = [120, 140, 190]
ys = [-2, 40, -30]

for x, y in zip(xs, ys):
    ax.plot([x], [y], marker=".")

# texts = [ax.text(x=x, y=y, s=f"({x}, {y})") for x, y in zip(xs, ys)]
texts = [ax.annotate(xy=(x, y), text=f"({x}, {y})") for x, y in zip(xs, ys)]

# fig.savefig("output-original.png")  # fix all
ax.autoscale_view()  # fix texts

adjust_text(texts, arrowprops=dict(arrowstyle="-", color="gray"))
fig.savefig("output.png")

output

Solutions:

  1. ax.annotate()ax.text() as mentioned in https://github.com/Phlya/adjustText/issues/136#issuecomment-1434261718. (fix MWE but not my plot)
  2. savefig()-twice. (again)