Last active
August 23, 2022 12:55
-
-
Save alekseygenerozov/7d34c4e11e67919d0960fe53696c3826 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
# from matplotlib.dates import date2num | |
# from datetime import datetime | |
import math | |
from math import atan2 | |
OFFDEF=0.05 | |
ALDEF=True | |
#Label line with line2D label data | |
def labelLine(line, x, label, ang=None, align=ALDEF, y_offset=OFFDEF, **kwargs): | |
ax = line.axes | |
xdata = line.get_xdata() | |
ydata = line.get_ydata() | |
order=np.argsort(xdata) | |
xdata=xdata[order] | |
ydata=ydata[order] | |
# print(xdata[0],xdata[-1]) | |
if (x < xdata[0]) or (x > xdata[-1]): | |
print('x label location is outside data range!') | |
return | |
axis_to_data = ax.transAxes + ax.transData.inverted() | |
data_to_axis = axis_to_data.inverted() | |
##Transforming to axis coordinates | |
ax_dat=data_to_axis.transform(np.transpose([xdata, ydata])) | |
xdata2=ax_dat[:,0] | |
ydata2=ax_dat[:,0] | |
x2=data_to_axis.transform([x,0])[0] | |
#Find corresponding y co-ordinate and angle of the | |
ip = 1 | |
for i in range(len(xdata)): | |
if x < xdata[i]: | |
ip = i | |
break | |
y = (ydata[ip-1] + (ydata[ip]-ydata[ip-1])*(x-xdata[ip-1])/(xdata[ip]-xdata[ip-1])) | |
y = axis_to_data.transform([0, data_to_axis.transform([0,y])[1]+y_offset])[1] | |
if not label: | |
label = line.get_label() | |
if align and not ang: | |
#Compute the slope | |
sp1 = ax.transData.transform_point((xdata[ip+1], ydata[ip+1])) | |
sp2 = ax.transData.transform_point((xdata[ip], ydata[ip])) | |
ang = math.degrees(atan2(sp1[1]-sp2[1],sp1[0]-sp2[0])) | |
#Transform to screen co-ordinates | |
#pt = np.array([x,y]).reshape((1,2)) | |
trans_angle = ang | |
elif align: | |
#Transform to screen co-ordinates | |
pt = np.array([x,y]).reshape((1,2)) | |
trans_angle = ang | |
else: | |
trans_angle = 0 | |
#print trans_angle | |
#Set a bunch of keyword arguments | |
if 'color' not in kwargs: | |
kwargs['color'] = line.get_color() | |
if ('horizontalalignment' not in kwargs) and ('ha' not in kwargs): | |
kwargs['ha'] = 'left' | |
if ('verticalalignment' not in kwargs) and ('va' not in kwargs): | |
kwargs['va'] = 'center' | |
if 'backgroundcolor' not in kwargs: | |
kwargs['backgroundcolor'] = ax.get_facecolor() | |
if 'clip_on' not in kwargs: | |
kwargs['clip_on'] = False | |
if 'zorder' not in kwargs: | |
kwargs['zorder'] = 2.5 | |
t=ax.text(x,y,label,rotation=trans_angle, rotation_mode='anchor',**kwargs) | |
#t=ax.text(x,y*y_offset,label,rotation=trans_angle, **kwargs) | |
t.set_bbox(dict(facecolor='white', alpha=0.1, edgecolor='white')) | |
def labelLines(lines, xvals=None, y_offset=OFFDEF, align=ALDEF, **kwargs): | |
''' | |
labelLines--Labels all of the lines in matplotlib plot | |
Lines:list | |
xvals (Array-like or None) None--x-axis locations of line labels. If this is None (default), the x-positions | |
are evenly spaced. The number of elements in xvals must equal the number of lines. | |
y_offset (Float) 0.05 -- Offset between each label and line in axis coordinates (which go from 0 to 1 for both x and y) | |
align (Boolean) True -- Whether to rotate label to be aligned with the line | |
''' | |
ax = lines[0].axes | |
labLines = [] | |
labels = [] | |
axis_to_data = ax.transAxes + ax.transData.inverted() | |
#Take only the lines which have labels other than the default ones | |
for line in lines: | |
label = line.get_label() | |
if "_line" not in label: | |
labLines.append(line) | |
labels.append(label) | |
##By default line-labels are evenly spaced in x. | |
if xvals is None: | |
xvals = np.linspace(0, 1,len(labLines)+2)[1:-1] | |
dat = axis_to_data.transform([[xx,0] for xx in xvals]) | |
xvals = dat[:,0] | |
y_offset=np.atleast_1d(y_offset) | |
tmp=0 | |
for line,x,label in zip(labLines,xvals,labels): | |
labelLine(line,x,label=label,align=align,y_offset=y_offset[tmp%len(y_offset)],**kwargs) | |
tmp+=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import labelLine | |
import matplotlib.pyplot as plt | |
import numpy as np | |
fig,ax=plt.subplots(figsize=(10,9)) | |
ords=np.arange(0.,2.*np.pi,2.*np.pi/1000.0) | |
l1,=plt.plot(ords,np.sin(ords),label="Sin(x)") | |
l2,=plt.plot(ords,np.cos(ords),label="Cos(x)") | |
labelLine.labelLines([l1,l2]) | |
fig.savefig("label1.png") | |
#--------------------------------------------------------------------------------------------------_# | |
##Log-linear plot/Experiments with label off-set and alignment. | |
fig,ax=plt.subplots(figsize=(10,9)) | |
ords=np.arange(0.,2.*np.pi,2.*np.pi/1000.0) | |
l1,=plt.semilogy(ords,np.exp(ords),label=r"$e^x$") | |
# l2,=plt.plot(ords,np.cos(ords),label="Cos(x)") | |
labelLine.labelLines([l1], y_offset=[0.15], align=False) | |
l1,=plt.semilogy(ords,np.exp(ords),label=r"$e^x$", color="Red",linestyle='--') | |
labelLine.labelLines([l1], xvals=[2]) | |
fig.savefig("label2.png") | |
#--------------------------------------------------------------------------------------------------_# | |
##Log-log plots | |
fig,ax=plt.subplots(figsize=(10,9)) | |
ords=np.arange(0.,2.*np.pi,2.*np.pi/1000.0) | |
l1,=plt.loglog(ords,ords**3.0,label=r"$x^3$") | |
l2,=plt.loglog(ords,ords**2.0,label=r"$x^2$", color="Red",linestyle='--') | |
labelLine.labelLines([l1, l2]) | |
fig.savefig("label3.png") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment