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

Deprecating markers, annotations, fill, rectangles properties of the Plot class #25117

Merged
merged 8 commits into from
May 11, 2023

Conversation

Davide-sd
Copy link
Contributor

@Davide-sd Davide-sd commented May 8, 2023

References to other Issues or PRs

NOTEs:

  1. this is the first PR related to Issue Merging of a new plotting module into SymPy #23036 .
  2. The first PRs (this one included) will address the necessary backwards incompatible changes.
  3. The aforementioned issue will be used as a log with all PRs of the merging process.

Brief description of what is fixed or changed

The properties markers, annotations, fill, rectangles of the Plot class (containing user-provided numerical data to be added on a plot) are deprecated. The new implementation saves user-provided numerical data into a new data series, GenericDataSeries, which can easily be processed by MatplotlibBackend. This makes the properties unnecessary. It also means that user-provided numerical data is taken into consideration when combining multiple plots with the extend and append methods (previously, they were disregarded).

Instead of setting those properties directly, users should pass the homonym keyword arguments to the plotting functions.

Motivation for this deprecation: the implementation of the Plot class suggests that it is ok to add attributes and hard-coded if-statements in the MatplotlibBackend class to provide more and more functionalities for user-provided numerical data (e.g. adding horizontal lines, or vertical lines, or bar plots, etc). However, in doing so one would reinvent the wheel: plotting libraries already implement the necessary API. There is no need to hard code these things in this plotting module.

The plotting module should facilitate the visualization of symbolic expressions. Then, the best way to add custom numerical data is to retrieve the figure created by the plotting module and use the API of a particular plotting library. For example, with Matplotlib we would write:

from sympy import *
var("x")
# visualize a symbolic expression
p = plot(cos(x))
# retrieve Matplotlib's figure and axes
fig, ax = p._backend.fig, p._backend.ax[0]
# add custom numerical data
ax.plot([0, 1, 2], [0, 1, -1], "*")
ax.axhline(0.5)
# visualize the figure
fig

Other comments

Release Notes

  • plotting
    • DEPRECATION: Deprecating markers, annotations, fill, rectangles properties of the Plot class. These can still be provided as keyword arguments to the plot function but setting the attributes on the returned Plot object is now deprecated.

…Plot class

The properties ``markers, annotations, fill, rectangles`` (containing
user-provided numerical data to be added on a plot) are deprecated.
The new implementation saves user-provided numerical data into a new data
series, `GenericSeries`, which can easily be processed by ``MatplotlibBackend``.
This means that user-provided numerical data is also taken into consideration
when combining multiple plots with the ``extend`` and ``append`` methods.

Instead of setting those properties directly, users should pass the homonym
keyword arguments to the plotting functions.

**Motivation for this deprecation:** the implementation of the ``Plot`` class
suggests that it is ok to add attributes and hard-coded if-statements in the
``MatplotlibBackend`` class to provide more and more functionalities for
user-provided numerical data (e.g. adding horizontal lines, or vertical
lines, or bar plots, etc). However, in doing so one would reinvent the wheel:
plotting libraries already implements the necessary API. There is no need to
hard code these things.

The plotting module should facilitate the visualization
of symbolic expressions. The best way to add custom numerical data is to
retrieve the figure created by the plotting module and use the API of a
particular plotting library. For example:

```py
p = plot(cos(x))
fig, ax = p._backend.fig, p._backend.ax[0]
ax.plot([0, 1, 2], [0, 1, -1], "*")
ax.axhline(0.5)
fig
```
@sympy-bot
Copy link

sympy-bot commented May 8, 2023

Hi, I am the SymPy bot. I'm here to help you write a release notes entry. Please read the guide on how to write release notes.

Your release notes are in good order.

Here is what the release notes will look like:

  • plotting
    • DEPRECATION: Deprecating markers, annotations, fill, rectangles properties of the Plot class. These can still be provided as keyword arguments to the plot function but setting the attributes on the returned Plot object is now deprecated. (#25117 by @Davide-sd)

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.13.

Click here to see the pull request description that was parsed.
#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234" (see
https://tinyurl.com/auto-closing for more information). Also, please
write a comment on that issue linking back to this pull request once it is
open. -->

**NOTEs**:

1. this is the first PR related to Issue #23036 .
2. The first PRs (this one included) will address the necessary backwards incompatible changes.
3. The aforementioned issue will be used as a log with all PRs of the merging process.

#### Brief description of what is fixed or changed

The properties ``markers, annotations, fill, rectangles`` of the ``Plot`` class  (containing user-provided numerical data to be added on a plot) are deprecated. The new implementation saves user-provided numerical data into a new data series, `GenericDataSeries`, which can easily be processed by ``MatplotlibBackend``. This makes the properties unnecessary. It also means that user-provided numerical data is taken into consideration when combining multiple plots with the ``extend`` and ``append`` methods (previously, they were disregarded).

Instead of setting those properties directly, users should pass the homonym keyword arguments to the plotting functions.

**Motivation for this deprecation:** the implementation of the ``Plot`` class suggests that it is ok to add attributes and hard-coded if-statements in the ``MatplotlibBackend`` class to provide more and more functionalities for user-provided numerical data (e.g. adding horizontal lines, or vertical lines, or bar plots, etc). However, in doing so one would reinvent the wheel: plotting libraries already implement the necessary API. There is no need to hard code these things in this plotting module.

The plotting module should facilitate the visualization of symbolic expressions. Then, the best way to add custom numerical data is to retrieve the figure created by the plotting module and use the API of a particular plotting library. For example, with Matplotlib we would write:

```py
from sympy import *
var("x")
# visualize a symbolic expression
p = plot(cos(x))
# retrieve Matplotlib's figure and axes
fig, ax = p._backend.fig, p._backend.ax[0]
# add custom numerical data
ax.plot([0, 1, 2], [0, 1, -1], "*")
ax.axhline(0.5)
# visualize the figure
fig
```

#### Other comments


#### Release Notes

<!-- Write the release notes for this release below between the BEGIN and END
statements. The basic format is a bulleted list with the name of the subpackage
and the release note for this PR. For example:

* solvers
  * Added a new solver for logarithmic equations.

* functions
  * Fixed a bug with log of integers. Formerly, `log(-x)` incorrectly gave `-log(x)`.

* physics.units
  * Corrected a semantical error in the conversion between volt and statvolt which
    reported the volt as being larger than the statvolt.

or if no release note(s) should be included use:

NO ENTRY

See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
information on how to write release notes. The bot will check your release
notes automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->

* plotting
  * DEPRECATION: Deprecating `markers`, `annotations`, `fill`, `rectangles` properties of the `Plot` class. These can still be provided as keyword arguments to the `plot` function but setting the attributes on the returned `Plot` object is now deprecated.

<!-- END RELEASE NOTES -->

Update

The release notes on the wiki have been updated.

@oscarbenjamin
Copy link
Collaborator

I haven't checked this very closely as I am not too familiar with any potential complex usage of the plotting module (using markers etc already goes beyond my own usage). That being said I think this broadly looks good.

The release note should say DEPRECATION rather than BREAKING CHANGE unless I have misunderstood something. The difference is that with DEPRECATION the old code continues to work but emits a warning. A BREAKING CHANGE means that the old code will not work any more. Typically the process is that something is deprecated and then later removed. At the point when t is removed that would be the breaking change.

The deprecation description in the docs could be a little clearer by giving an explicit example of old usage that is now considered deprecated and exactly what that specific example should be replaced by.

Also if the suggestion is to do plot(..., markers=....) is that something that would work in previous versions of sympy as well? If so then it would be good to clearly say what style of code can be used both in older and newer versions of sympy without emitting any deprecation warning.

@Davide-sd
Copy link
Contributor Author

Thanks Oscar, great suggestions!

The release note should say DEPRECATION rather than BREAKING CHANGE unless I have misunderstood something.

Ok, I was following this deprecation guide which clearly should be updated :)

# plot symbolic expression
p = plot(cos(x))
# retrieve Matplotlib's figure and axes object
fig, ax = p._backend.fig, p._backend.ax[0]
Copy link
Member

@sylee957 sylee957 May 8, 2023

Choose a reason for hiding this comment

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

I don't think that it is good to encourage users to use implementation details like _backend though.
Maybe it is better to develop a public function, like to_backend, and encourage users that if you start to use backend directly, sympy is not responsible with any context you keep working with the backend.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, that will come on a future PR!

@sylee957
Copy link
Member

sylee957 commented May 9, 2023

You need to fix the author tests

@github-actions
Copy link

github-actions bot commented May 9, 2023

Benchmark results from GitHub Actions

Lower numbers are good, higher numbers are bad. A ratio less than 1
means a speed up and greater than 1 means a slowdown. Green lines
beginning with + are slowdowns (the PR is slower then master or
master is slower than the previous release). Red lines beginning
with - are speedups.

Significantly changed benchmark results (PR vs master)

Significantly changed benchmark results (master vs previous release)

       before           after         ratio
     [8059df73]       [8cf07e36]
     <sympy-1.12^0>                 
-      85.5±0.4ms       54.7±0.3ms     0.64  integrate.TimeIntegrationRisch02.time_doit(10)
-      83.8±0.3ms       53.5±0.2ms     0.64  integrate.TimeIntegrationRisch02.time_doit_risch(10)

Full benchmark results can be found as artifacts in GitHub Actions
(click on checks at the top of the PR).

@oscarbenjamin
Copy link
Collaborator

Looks good to me.

@oscarbenjamin
Copy link
Collaborator

@Davide-sd I edited the release note. Let me know if it looks incorrect.

This looks good so I'll merge it.

@oscarbenjamin oscarbenjamin merged commit 13276ca into sympy:master May 11, 2023
@Davide-sd
Copy link
Contributor Author

Looks good, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants