Skip to content

format error saving eps figure using custom linestyle #14996

Closed

Description

@Mahdi-Hosseinali

Bug report

Bug summary

When the linestyle is changed from a predefined value to on-off tuple, the resulting figure cannot be saved as eps file format.

Code for reproduction

    import numpy as np
    import matplotlib.pyplot as plt
    x = y = np.linspace(-5, 5)
    x, y = np.meshgrid(x, y)
    z = x**2 + y**2 - 10
    
    plt.rcParams['contour.negative_linestyle'] = [7.0, 7.0]
    f = plt.figure()
    plt.contour(x, y, z, colors='k', levels=20)
    f.savefig('test.eps')

Actual outcome

Traceback (most recent call last):

  File "<ipython-input-12-d73b5c362b1b>", line 1, in <module>
    f.savefig('test.eps')

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\figure.py", line 2180, in savefig
    self.canvas.print_figure(fname, **kwargs)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backends\backend_qt5agg.py", line 88, in print_figure
    super().print_figure(*args, **kwargs)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backend_bases.py", line 2082, in print_figure
    **kwargs)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backends\backend_ps.py", line 842, in print_eps
    return self._print_ps(outfile, 'eps', *args, **kwargs)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backends\backend_ps.py", line 871, in _print_ps
    **kwargs)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backends\backend_ps.py", line 966, in _print_figure
    self.figure.draw(renderer)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\figure.py", line 1709, in draw
    renderer, self, artists, self.suppressComposite)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\image.py", line 135, in _draw_list_compositing_images
    a.draw(renderer)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 2647, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\image.py", line 135, in _draw_list_compositing_images
    a.draw(renderer)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\collections.py", line 329, in draw
    self._offset_position)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backends\backend_ps.py", line 492, in draw_path_collection
    offset_position)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backend_bases.py", line 245, in draw_path_collection
    self.draw_path(gc0, path, transform, rgbFace)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backends\backend_ps.py", line 414, in draw_path
    self._draw_ps(ps, gc, rgbFace)

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backends\backend_ps.py", line 759, in _draw_ps
    self.set_linedash(*gc.get_dashes())

  File "C:\Users\mhossein\Anaconda3\lib\site-packages\matplotlib\backends\backend_ps.py", line 276, in set_linedash
    s = "[%s] %d setdash\n" % (_nums_to_str(*seq), offset)

TypeError: %d format: a number is required, not NoneType

Expected outcome

The above snippet works when png extension is used, or when [7.0, 7.0] is replaced with 'dashed'

Matplotlib version

  • Operating system: windows 7.0
  • Matplotlib version: 3.1.1
  • Matplotlib backend (print(matplotlib.get_backend())): Qt5Agg
  • Python version: 3.7.1
  • Jupyter version (if applicable):
  • Other libraries:

Activity

  1. ImportanceOfBeingErnest commented on Aug 7, 2019

    @ImportanceOfBeingErnest
    Member

    Funnily, it seems to work fine if you use plt.rcParams['lines.linestyle'] = [7.0, 7.0]. Though this is probably a bug in itself - since it should either make all lines that linestyle, or none of them.

  2. added this to the v3.2.0 milestone on Aug 7, 2019
  3. Mahdi-Hosseinali commented on Aug 7, 2019

    @Mahdi-Hosseinali
    Author

    It doesn't! plt.rcParams['lines.linestyle'] = [7.0, 7.0] affects plots not contour lines. For example, the following code throws the same error with what you suggested.

    plt.rcParams['lines.linestyle'] = [7.0, 7.0]
    f = plt.figure()
    plt.plot(np.random.randn(300))
    f.savefig('test.eps')
  4. ImportanceOfBeingErnest commented on Aug 7, 2019

    @ImportanceOfBeingErnest
    Member

    Ok, seems we need to update #11797 with some more cases.

  5. ImportanceOfBeingErnest commented on Aug 8, 2019

    @ImportanceOfBeingErnest
    Member

    I see a bit clearer now. The linestyles argument of contour also does not take any on-off patern as input. So the fact that it works for some backend is an untested coincidence.

    The intended way to change the pattern is via the 'lines.dashed_pattern' parameter. So your code would need to look like this:

    import numpy as np
    import matplotlib.pyplot as plt
    x = y = np.linspace(-5, 5)
    x, y = np.meshgrid(x, y)
    z = x**2 + y**2 - 10
    
    plt.rcParams['contour.negative_linestyle'] = "dashed"
    plt.rcParams['lines.dashed_pattern'] = (7, 1)
    
    f = plt.figure()
    plt.contour(x, y, z, colors="k", levels=20)
    f.savefig('test.eps')
    plt.show()
    
  6. modified the milestones: v3.2.0, v3.3.0 on Sep 1, 2019
  7. tacaswell commented on Sep 1, 2019

    @tacaswell
    Member

    Pushing to 3.3 as there is a way to avoid this problem and tightening up the API will likely require some careful thought.

  8. anntzer commented on Jan 21, 2020

    @anntzer
    Contributor

    This would be fixed by #15828 (which basically mentions this case in the first message re: passing None instead of zero).

  9. added and removed
    API: consistencyConsistency of the matplotlib API, including naming, behavior, defaults, …
    on Jan 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions