import matplotlib.pyplot as plt
import numpy as np
import math
def label_line(line, label_text, near_i=None, near_x=None, near_y=None, rotation_offset=0, offset=(0,0)):
    """call 
        l, = plt.loglog(x, y)
        label_line(l, "text", near_x=0.32)
    """
    def put_label(i):
        """put label at given index"""
        i = min(i, len(x)-2)
        dx = sx[i+1] - sx[i]
        dy = sy[i+1] - sy[i]
        rotation = np.rad2deg(math.atan2(dy, dx)) + rotation_offset
        pos = [(x[i] + x[i+1])/2. + offset[0], (y[i] + y[i+1])/2 + offset[1]]
        plt.text(pos[0], pos[1], label_text, size=20, rotation=rotation, color = line.get_color(),
        ha="center", va="center", bbox = dict(ec='1',fc='1'))

    x = line.get_xdata()
    y = line.get_ydata()
    ax = line.get_axes()
    if ax.get_xscale() == 'log':
        sx = np.log10(x)    # screen space
    else:
        sx = x
    if ax.get_yscale() == 'log':
        sy = np.log10(y)
    else:
        sy = y

    # find index
    if near_i is not None:
        i = near_i
        if i < 0: # sanitize negative i
            i = len(x) + i
        put_label(i)
    elif near_x is not None:
        for i in range(len(x)-2):
            if (x[i] < near_x and x[i+1] >= near_x) or (x[i+1] < near_x and x[i] >= near_x):
                put_label(i)
    elif near_y is not None:
        for i in range(len(y)-2):
            if (y[i] < near_y and y[i+1] >= near_y) or (y[i+1] < near_y and y[i] >= near_y):
                put_label(i)
    else:
        raise ValueError("Need one of near_i, near_x, near_y")



values=np.linspace(0.,100.,10000)


plt.plot(values,values,'k-')

errs=[1.1,1.3,1.5]
fmts=["--","-.",":"]
for idx in range(len(errs)):
  l1,=plt.plot(values,values*errs[idx],fmts[idx],color="gray")
  l2,=plt.plot(values*errs[idx],values,fmts[idx],color="gray")
  label_line(l1, "%i %%"%((errs[idx]-1)*100), near_i=None, near_x=None, near_y=70, rotation_offset=0, offset=(0,0))
  label_line(l2, "%i %%"%((errs[idx]-1)*100), near_i=None, near_x=70, near_y=None, rotation_offset=0, offset=(0,0))

plt.xlim(1,100)
plt.ylim(1,100)
#plt.yscale("log")
#plt.xscale("log")

plt.show()
