Skip to content

Specifying a Marker as a Tuple seems broken in 3.2 #16811

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

Closed
Erotemic opened this issue Mar 17, 2020 · 2 comments
Closed

Specifying a Marker as a Tuple seems broken in 3.2 #16811

Erotemic opened this issue Mar 17, 2020 · 2 comments
Milestone

Comments

@Erotemic
Copy link

Bug report

Bug summary

In matplotlib 3.2 setting a line marker=(3, 2, 0.0) (which should be an asterisk style marker with 3 sides and 0 degrees of rotation) causes an error.

AttributeError: 'IdentityTransform' object has no attribute 'scale'

In version 3.1.2, this error does not occur. It looks like

Code for reproduction

def main():
    import matplotlib.pyplot as plt
    fig = plt.figure()
    fig.add_axes()
    ax = fig.gca()
    ax.plot([0, 1, 2], [0, 1, 2], marker=(3, 2, 0.0))
    fig.savefig('foo.png')


if __name__ == '__main__':
    main()

This results in the error:

Traceback (most recent call last):
  File "/home/joncrall/code/kwplot/dev/mwe_markerstye.py", line 15, in <module>
    main()
  File "/home/joncrall/code/kwplot/dev/mwe_markerstye.py", line 7, in main
    fig.savefig('foo.png')
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/figure.py", line 2203, in savefig
    self.canvas.print_figure(fname, **kwargs)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/backends/backend_qt5agg.py", line 94, in print_figure
    super().print_figure(*args, **kwargs)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/backend_bases.py", line 2086, in print_figure
    result = print_method(
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 514, in print_png
    FigureCanvasAgg.draw(self)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 393, in draw
    self.figure.draw(self.renderer)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/figure.py", line 1735, in draw
    mimage._draw_list_compositing_images(
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/image.py", line 137, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/axes/_base.py", line 2630, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/image.py", line 137, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/joncrall/.local/conda/envs/py38/lib/python3.8/site-packages/matplotlib/lines.py", line 866, in draw
    marker_trans = marker_trans.scale(w)
AttributeError: 'IdentityTransform' object has no attribute 'scale'

While the 3.1.2 version results in a nice plot:

image

Matplotlib version

  • Operating system: Linux
  • Matplotlib version: 3.2 (via pip)
  • Matplotlib backend: tried agg and pyqt5
  • Python version: 3.7 and 3.8

I've identified a possible solution. The main difference seems to be in the _set_tuple_marker function. In 3.1.2 it was:

    def _set_tuple_marker(self):
        marker = self._marker
        if isinstance(marker[0], Number):
            if len(marker) == 2:
                numsides, rotation = marker[0], 0.0
            elif len(marker) == 3:
                numsides, rotation = marker[0], marker[2]
            symstyle = marker[1]
            if symstyle == 0:
                self._path = Path.unit_regular_polygon(numsides)
                self._joinstyle = 'miter'
            elif symstyle == 1:
                self._path = Path.unit_regular_star(numsides)
                self._joinstyle = 'bevel'
            elif symstyle == 2:
                self._path = Path.unit_regular_asterisk(numsides)
                self._filled = False
                self._joinstyle = 'bevel'
            elif symstyle == 3:
                cbook.warn_deprecated(
                    "3.0", message="Setting a circle marker using `(..., 3)` "
                    "is deprecated since Matplotlib 3.0, and support for it "
                    "will be removed in 3.2.  Directly pass 'o' instead.")
                self._path = Path.unit_circle()
            self._transform = Affine2D().scale(0.5).rotate_deg(rotation)
        else:
            cbook.warn_deprecated(
                "3.0", message="Passing vertices as `(verts, 0)` is "
                "deprecated since Matplotlib 3.0, and support for it will be "
                "removed in 3.2.  Directly pass `verts` instead.")
            verts = np.asarray(marker[0])
            path = Path(verts)
            self._set_custom_marker(path)

and in 3.2 it was cleaned up to:

    def _set_tuple_marker(self):
        marker = self._marker
        print('marker = {!r}'.format(marker))
        if len(marker) == 2:
            numsides, rotation = marker[0], 0.0
        elif len(marker) == 3:
            numsides, rotation = marker[0], marker[2]
        symstyle = marker[1]
        if symstyle == 0:
            self._path = Path.unit_regular_polygon(numsides)
            self._joinstyle = 'miter'
        elif symstyle == 1:
            self._path = Path.unit_regular_star(numsides)
            self._joinstyle = 'bevel'
        elif symstyle == 2:
            self._path = Path.unit_regular_asterisk(numsides)
            self._filled = False
            self._joinstyle = 'bevel'
        else:
            raise ValueError(f"Unexpected tuple marker: {marker}")

However, notice that in the second version self._transform is never set. Also note that in the 3.2 version the rotation param is never used. I expect that the self._transform = Affine2D().scale(0.5).rotate_deg(rotation) line was supposed to be ported, but never was. Adding it back in seems to fix the issue.

I noticed it when looking in the lines.py draw method. I saw most markers had an AffineTransform, but the ones I made using the tuple method of initialization has IdentityTransforms.

@Erotemic
Copy link
Author

Erotemic commented Mar 17, 2020

Looks like this issue was already fixed in master (via #16791).

@tacaswell
Copy link
Member

Thank you for the through bug report! Sorry we broke you.

@QuLogic QuLogic added this to the v3.2.1 milestone Jun 16, 2020
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

3 participants