Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Support customizing antialiasing for text and annotation #25775

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

Merged
merged 4 commits into from
Jun 2, 2023

Conversation

stevezhang1999
Copy link
Contributor

@stevezhang1999 stevezhang1999 commented Apr 26, 2023

PR Summary

Closes #25675

Change overview: now text objects and annotation objects support parameter 'antialiased'.
When antialiased is not specified, it will use the value from rcParams instead.
Examples are

mpl.text.Text(.5, .5, "foo\nbar", antialiased=True)
plt.text(0.5, 0.5, '6 inches x 2 inches', antialiased=True)
ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5), antialiased=False)

how it is done

It's realized by changing how antialiased is set in backends - draw_text() in backend_agg.py.
Now we use GraphicsContext.get_antialiased() instead of rcParams['text.antialiased']
GraphicsContext object is retrieved and updated by Text and Annotation objects when draw() is called

limitations

Currently, it's only supported by Agg and Cairo backend. For all other backends, I didn't see they are checking rcParams['text.antialiased'] to customize text antialiasing.

Note that to set antialiasing for math expressions, the only way is still using rcParams['text.antialiased'], as the process is a bit different from normal text (including annotation)

notes for tests

Unit tests ensure that getter/setter in Text and Annotation objects works well. I didn't include the tests for the whole pipeline because it may require uploading images.

The integration test code is below - we are expected to see texts without antialiasing. The code below is for Agg. If we wnat to test with Cairo, please replace 'TkAgg' with 'GTK3Cairo' in line 14

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import sys
def is_venv():
    return (hasattr(sys, 'real_prefix') or
            (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix))

print("Inside venv: ", is_venv())
mpl.use('TkAgg')
print("backend: ", mpl.rcParams['backend'])

print("*"*10, "simple unit test", "*"*10)
txt2 = mpl.text.Text(.5, .5, "foo\nbar", antialiased=True)
print("txt2.get_antialiased(): ", txt2.get_antialiased())
print("*"*35)

print("Test: plt.text")
mpl.rcParams['text.antialiased'] = True
text_kwargs = dict(ha='center', va='center', fontsize=28, color='C1', antialiased=False)
plt.subplots(figsize=(6, 2))
plt.text(0.5, 0.5, '6 inches x 2 inches', **text_kwargs)
plt.show()

fig, ax = plt.subplots(figsize=(3, 3))
t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = ax.plot(t, s, lw=2)

print("Test: ax.annotate")
mpl.rcParams['text.antialiased'] = True
ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5),
            arrowprops=dict(facecolor='black', shrink=0.05), antialiased=False)
ax.set_ylim(-2, 2)
plt.show()

PR Checklist

Linked Issue

  • Added "closes #0000" in the PR description to link it to the original issue.

Documentation and Tests

  • Has pytest style unit tests (and pytest passes)
    units tests for new getter and setter for attribute "antialiased"
    integrate tests for run the whole thing, please see the scripts at the end
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).
    N/A - no doc added
  • New plotting related features are documented with examples.
    N/A - docstring already have antialiased, modification is not needed

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a while, please feel free to ping @matplotlib/developers or anyone who has commented on the PR. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join us on gitter for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide

We strive to be a welcoming and open project. Please follow our Code of Conduct.

@tacaswell
Copy link
Member

I'm not sure that anti-aliasing really makes sense for the vector backends (as we are not doing the rasterization the next program down the chain is).

@tacaswell tacaswell added this to the v3.8.0 milestone Apr 27, 2023
@stevezhang1999
Copy link
Contributor Author

I'm not sure that anti-aliasing really makes sense for the vector backends (as we are not doing the rasterization the next program down the chain is).

Thanks for the suggestion! Could you talk more about what backends should be supported? Based on my understanding, Agg is raster and Cairo is raster or vector, according to https://matplotlib.org/stable/users/explain/backends.html. I have completed this feature in both Agg and Cairo.


Parameters
----------
b : bool or None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should either cast to bool or interpret None as "reset to default". Letting the None leak through seems like the worst of our options here.

Copy link
Contributor Author

@stevezhang1999 stevezhang1999 Apr 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your suggestion. I will make it interpret None as "reset to default". What about don't allow None as input, like Line2D.set_antialiased() ?

@tacaswell
Copy link
Member

This is probably going to require an API change note. Previously you could globally control the anti-aliasing the text by changing the rcparam at draw time, now the value of the rcparam is attached to the text at Text creation time. That is


# previously this was a no-op, now it is what works
with rccontext(text.antialiased=False):
    fig, ax = plt.subplots()


# previously this had an effect, now this is a no-op
with rccontext(text.antialiased=False):
    fig.savefig('/tmp/test.png')

I don't see any good way to warn on this, so I think we just have to document it very well. The best work around is probably to make sure that if you are using contexts both the creation and save are in the same context as that will work both forwards and backwards.

@tacaswell
Copy link
Member

I have completed this feature in both Agg and Cairo.

I think this is the correct backends that need this.

@tacaswell
Copy link
Member

Could you add a check_figures_equal test where one side uses the rcparam and the other side "manually" sets the anti-alisaing state?

@stevezhang1999

This comment was marked as resolved.

@stevezhang1999

This comment was marked as resolved.

@stevezhang1999 stevezhang1999 requested a review from tacaswell May 3, 2023 05:54
@stevezhang1999
Copy link
Contributor Author

stevezhang1999 commented May 3, 2023

I believe we have finished.

Now Text._antialiased is either True or False. That means, even if user didn't specify antialiased when they created the figure and text (including the coordinate axes), the user can no longer change it - this will be set by mpl.rcParams['text.antialiased'] at the time Text object is initialized.

An alternative solution is to allow Text._antialiased to be None and when Text.get_antialiased() is called, mpl.rcParams['text.antialiased'] will be returned. Doing so will make how users were doing continue working.

For the issue mentioned and crossed out above, we may want to provide a way to customize the antialiasing states for figure or subplot, which is not the job of Text.

We want to make the APIs consistent. Other APIs like Line2D and Patches will make the antialiasing state fixed at the creation and don't allow None.

@stevezhang1999
Copy link
Contributor Author

This is probably going to require an API change note. Previously you could globally control the anti-aliasing the text by changing the rcparam at draw time, now the value of the rcparam is attached to the text at Text creation time. That is


# previously this was a no-op, now it is what works
with rccontext(text.antialiased=False):
    fig, ax = plt.subplots()


# previously this had an effect, now this is a no-op
with rccontext(text.antialiased=False):
    fig.savefig('/tmp/test.png')

I don't see any good way to warn on this, so I think we just have to document it very well. The best work around is probably to make sure that if you are using contexts both the creation and save are in the same context as that will work both forwards and backwards.

I include this under /api_changes


plt.text(0.5, 0.25, r"$I'm \sqrt{x}$", antialiased=False)

Also note that antialiasing for coordinate axes will be set with ``rcParams['text.antialiased']`` when they are created and cannot be changed afterwards.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Also note that antialiasing for coordinate axes will be set with ``rcParams['text.antialiased']`` when they are created and cannot be changed afterwards.
Also note that antialiasing for tick labeles will be set with ``rcParams['text.antialiased']`` when they are created and cannot be changed afterwards.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Axes vs axis have very specific meaning in Matplotlib (matplotlib.axes.Axes vs matplotlib.axis.Axis). I think tick labels (our name for the text on the ticks), see https://matplotlib.org/stable/gallery/showcase/anatomy.html for the very particular names we use for things.

@tacaswell
Copy link
Member

Good to talk to you on the call today and I apologize for being slow to review!

I think this is getting very close, just the finishing details on the docs.

@stevezhang1999 stevezhang1999 requested a review from tacaswell May 25, 2023 10:37
@tacaswell
Copy link
Member

@stevezhang1999 Would you be willing to squash this to one or two commits?

@stevezhang1999 stevezhang1999 force-pushed the text-object-antialias branch from aedbdf2 to 8890c34 Compare May 26, 2023 02:01
@stevezhang1999
Copy link
Contributor Author

stevezhang1999 commented May 26, 2023

@stevezhang1999 Would you be willing to squash this to one or two commits?

@tacaswell Great to talk to you yesterday! Now we have only one commit for this.

I also added a one-sentence note under Text.set_antialiased, for the limitation that we cannot customizing antialiasing with mathtext with parameter antialiased. As far as I'm concerned, we may need to modify lots of classes (including Text, mathtext, backends and more) to make antialiased have an effect - so maybe I (as well as other contributors) can investigate this separately later.

@stevezhang1999 stevezhang1999 requested a review from anntzer May 28, 2023 00:52
@anntzer
Copy link
Contributor

anntzer commented May 28, 2023

test failure seems unrelated.

@stevezhang1999

This comment was marked as resolved.

@stevezhang1999
Copy link
Contributor Author

@tacaswell would like to know if this is ready to be merged since we have two approvals or there is other things we should look at? This could help me manage the git things for the work built on top of this PR.

@tacaswell
Copy link
Member

@stevezhang1999 Could you rebase this again to pick up the CI fix?

@stevezhang1999 stevezhang1999 force-pushed the text-object-antialias branch from 98f397a to 5e5a03d Compare June 2, 2023 07:58
@stevezhang1999
Copy link
Contributor Author

@stevezhang1999 Could you rebase this again to pick up the CI fix?

@tacaswell Done!

@stevezhang1999 stevezhang1999 requested a review from oscargus June 2, 2023 12:08
@oscargus
Copy link
Member

oscargus commented Jun 2, 2023

Thanks @stevezhang1999 and congratulations to your first merged PR in Matplotlib! Hope to see you around!

@oscargus oscargus merged commit 74c0cd0 into matplotlib:main Jun 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

[ENH]: Add get/set_antialiased to Text objects
5 participants