Description
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:
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.