I'm trying to analyze some spectra for finding spectroscopic peaks, I've writen this simple code to find the max Y value (the peak) between two X data by clicking before and after the peak that I want to find. This works and I can get the coordinate of the peak but I would like to automatically annotate the peak found.
import matplotlib.pyplot as plt
X=[1,2,3,4,5,6,7,8,9,10]
Y=[1,1,1,2,10,2,1,1,1,1]
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(X,Y,label="prova") #plot the function
#plt.legend(loc=1, ncol=1, shadow=True)
plt.xlim(min(X) * 0.9, max(X) * 1.1)
plt.ylim(min(Y) * 0.9, max(Y) * 1.1)
plt.ylabel(r'Y axis')
plt.xlabel(r'X axis')
Diz=dict(zip(X,Y)) #create a dictionary that associate X with Y
Interval=[] #interval where the user search for peaks
PeaksList=[] #list of peaks found
def onclick(event):
print 'First limit at =%f'%(event.xdata)
Interval.append(event.xdata)
if len(Interval)%2==0:
a=Interval[-2]
b=Interval[-1]
if b<a: #if the user select first the highest value these statements filp it!
A=b
B=a
else:
A=a
B=b
#find the max Y value: the peak!
peakY=0 #max Y value
piccoX=0 #value of the X associate to the peak
for i in [ j for j in X if A<j<B] :
if Diz[i]>peakY:
peakY=Diz[i]
piccoX=i
print "Interval: %f - %f Peak at: %f " %(a,b,piccoX)
PeaksList.append([piccoX,peakY])
ax.annotate("picco", xy=(piccoX,peakY), xycoords='data',
xytext=(-50, 30), textcoords='offset points',
arrowprops=dict(arrowstyle="->")
)
plt.show()
cid = fig.canvas.mpl_connect('button_press_event', onclick)
This is what I would like to have after the second click:
You have to redraw the figure - simply by adding a plt.draw
to the onclick method.
Moreover you have to connect the event before you show the figure.
Of course, here your annotation text is 'picco' not '5'.
Try:
import matplotlib.pyplot as plt
X=[1,2,3,4,5,6,7,8,9,10]
Y=[1,1,1,2,10,2,1,1,1,1]
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(X,Y,label="prova") #plot the function
#plt.legend(loc=1, ncol=1, shadow=True)
plt.xlim(min(X) * 0.9, max(X) * 1.1)
plt.ylim(min(Y) * 0.9, max(Y) * 1.1)
plt.ylabel(r'Y axis')
plt.xlabel(r'X axis')
Diz=dict(zip(X,Y)) #create a dictionary that associate X with Y
Interval=[] #interval where the user search for peaks
PeaksList=[] #list of peaks found
def onclick(event):
print 'First limit at =%f'%(event.xdata)
Interval.append(event.xdata)
if len(Interval)%2==0:
a=Interval[-2]
b=Interval[-1]
if b<a: #if the user select first the highest value these statements filp it!
A=b
B=a
else:
A=a
B=b
#find the max Y value: the peak!
peakY=0 #max Y value
piccoX=0 #value of the X associate to the peak
for i in [ j for j in X if A<j<B] :
if Diz[i]>peakY:
peakY=Diz[i]
piccoX=i
print "Interval: %f - %f Peak at: %f " %(a,b,piccoX)
PeaksList.append([piccoX,peakY])
ax.annotate("picco", xy=(piccoX,peakY), xycoords='data',
xytext=(-50, 30), textcoords='offset points',
arrowprops=dict(arrowstyle="->")
)
plt.draw()
cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()
Maybe visually more appealing (using the spanselector):
import matplotlib.pyplot as plt
from matplotlib.widgets import SpanSelector
X=[1,2,3,4,5,6,7,8,9,10]
Y=[1,1,1,2,10,2,1,1,1,1]
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(X,Y,label="prova") #plot the function
#plt.legend(loc=1, ncol=1, shadow=True)
plt.xlim(min(X) * 0.9, max(X) * 1.1)
plt.ylim(min(Y) * 0.9, max(Y) * 1.1)
plt.ylabel(r'Y axis')
plt.xlabel(r'X axis')
Diz=dict(zip(X,Y)) #create a dictionary that associate X with Y
Interval=[] #interval where the user search for peaks
PeaksList=[] #list of peaks found
def onclick(xmin, xmax):
print 'Interval: {0} - {1}'.format(xmin,xmax)
peakY=0 #max Y value
piccoX=0 #value of the X associate to the peak
for i in [ j for j in X if xmin<j<xmax] :
if Diz[i]>peakY:
peakY=Diz[i]
piccoX=i
print "Peak at: %f " % piccoX
PeaksList.append([piccoX,peakY])
ax.annotate("picco", xy=(piccoX,peakY), xycoords='data',
xytext=(-50, 30), textcoords='offset points',
arrowprops=dict(arrowstyle="->"))
plt.draw()
span = SpanSelector(ax, onclick, 'horizontal', useblit=True,
rectprops=dict(alpha=0.5, facecolor='blue') )
plt.show()