4

Trying to draw a simple arrow in Matplotlib using the following:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.arrow(1, 1, 1, 1)
plt.show()

which results in an empty plot.

If the arrow specifications are changed to ax.arrow(0, 0, 1, 1) then I do see an arrow in the final plot. So I suspected that it is probably an issue with the scaling of the axes, so I modified the code based on recommendations in Matplotlib autoscale to the following:

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.arrow(1, 1, 1, 1)
ax.relim()
ax.autoscale_view()
plt.show()

which also does not work.

I found that manually setting the limits as in the following works

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.arrow(1, 1, 1, 1)
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)
plt.show()

Strange also was my discovery that ax.set_xlim() alone or ax.set_ylim() alone do not work I have to set both the limits for the arrow to become visible.

Questions:

  • Does ax.arrow require special handling?
  • Am I missing some commands apart from ax.relim() and ax.autoscale_view()?
  • Why do I have to set both xlim and ylim?

Versions:

  • Python: 3.5.1
  • Matplotlib: 1.5.1
  • Linux: 64 bit Archlinux
awhan
  • 510
  • 6
  • 13
  • Looks like a bug or unspecified behavior to me. Adding no arrow gives the same x/y-scales when autoscaling. Your arrow starts at 1,1 and moves 1 up and 1 right, therefore you need to both xlim and ylim. If you set only xlim to 0,5 your window will x:0,5 and y:0,1 and the arrow will be still outside your frame. – Maximilian Peters Jun 19 '16 at 14:54
  • @Ashafix thanks, your explanation as to why both `xlim` and `ylim` are needed makes sense. – awhan Jun 19 '16 at 15:58

1 Answers1

3

The problem persists on Windows 10 and Ubuntu 14 with the latest version of matplotlib and Python 3.4/3.5. A simple workaround is to create a helper function arrow_ which creates two invisible points at the beginning and end of the arrow.

import matplotlib.pyplot as plt
fig, ax = plt.subplots()

def arrow_(ax, plt, x, y, dx, dy, **kwargs):
    ax.arrow(x, y, dx, dy, **kwargs)
    plt.plot([x, x + dx + 0.1], [y, y + dx + 0.1], alpha=0)

arrow_(ax, plt, 1, 1, 1, 1)
ax.relim()
#plt.plot([1.8], [1.5], 'ro')
ax.autoscale_view()
plt.show()
  • The commented line is just to demonstrate that the invisible dots don't interfere with the rest of the graph.
  • The added value of 0.1 is just to compensate for the arrow head.
Maximilian Peters
  • 30,348
  • 12
  • 86
  • 99
  • Coming to this answer after a few years. I don't think this bug has been resolved? I was trying to plot an arrow doing this `ax.arrow(10,50,12,3)` and the figure shows nothing and limits to only 1.0 and 1.0 on both axes. – Abhishek Jul 17 '19 at 17:40
  • yeah I have the same issue – mattator Aug 22 '19 at 07:23