0

I am "annotating" many arrows of a certain color to add data to the graph (where events occurred). (example code). Is there a way to add it to the legend? One answer might be to add them manually as I show in the code below, but I guess it is always the last resort. What is the "right" way to do it? (bonus for also having a small arrow mark in the legend)

Here is an example, but really, the example is for ease of use, the question is just how to add label for line.axes.annotate

Here is a code which is almost identical to the one in the link: A function to add arrows to

def add_arrow(line, position=None, direction='right', size=15, color=None, length=None):
    """
    add an arrow to a line.

    line:       Line2D object
    position:   x-position of the arrow. If None, mean of xdata is taken
    direction:  'left' or 'right'
    size:       size of the arrow in fontsize points
    color:      if None, line color is taken.
    length:     the number of points in the graph the arrow will consider, leave None for automatic choice
    """
    if color is None:
        color = line.get_color()

    xdata = line.get_xdata()
    ydata = line.get_ydata()

    if not length:
        length = max(1, len(xdata) // 1500)
    if position is None:
        position = xdata.mean()
    # find closest index
    start_ind = np.argmin(np.absolute(xdata - position))
    if direction == 'right':
        end_ind = start_ind + length
    else:
        end_ind = start_ind - length
    if end_ind == len(xdata):
        print("skipped arrow, arrow should appear after the line")
    else:
        line.axes.annotate('',
                           xytext=(xdata[start_ind], ydata[start_ind]),
                           xy=(xdata[end_ind], ydata[end_ind]),
                           arrowprops=dict(
                               arrowstyle="Fancy,head_width=" + str(size / 150), color=color),
                           size=size
                           )

A function that uses it

def add_arrows(line, xs, direction='right', size=15, color=None, name=None):
    if name:
        if color is None:
            color = line.get_color()
        patch = mpatches.Patch(color=color, label=name, marker="->")
        plt.legend(handles=[patch])
    for x in xs:
        add_arrow(line, x, color=color)

An example to what line is

x,y = [i for i in range(10000)], [i for i in range(10000)] 
line = plt.plot(x, y, label="class days")[0]
add_arrows(line, (x,y))
plt.show()
borgr
  • 20,175
  • 6
  • 25
  • 35
  • Please include relevant code in question. – Julien Aug 31 '18 at 04:35
  • @Julien added, thanks for the help – borgr Aug 31 '18 at 04:45
  • Might be good to also explain why you are not happy with your current code... Current figure vs desired result... – Julien Aug 31 '18 at 04:51
  • As I wrote, I have the desired result (well i'll be happy for a small arrow in the legened but that is not the reason for the question), it is a question of writing good code. I am using a manual walkaround. – borgr Aug 31 '18 at 04:54
  • 1
    ok but then add that result here so we can have an idea of what you want to achieve in one glance rather than guessing by reading your code... – Julien Aug 31 '18 at 04:57
  • indeed, the code in the question does not show how `add_arrows` is used. So even if someone wanted to dive into this and actually run to code to get an idea of the desired output, they wouldn't know which arguments to put into `add_arrows`. – ImportanceOfBeingErnest Aug 31 '18 at 10:23

0 Answers0