3 """a library of helping functions for spotting force spectroscopy peaks.
8 def conv_dx(data,vect):
10 Returns the right-centered convolution of data with vector vect
19 for k in range(window):
20 temparr[j]+=data[j+k]*vect[k]
26 Calculates the absolute deviation of a vector
36 def noise_absdev(data,positive=False,maxcut=0.2,stable=0.005):
38 Returns the standard deviation of the noise.
39 The logic is: we cut the most negative (or positive) data points until the absolute deviation
40 becomes stable (it doesn't vary more than 0.005) or we have cut more than maxcut*len(data) points.
41 Then calculate the absolute deviation.
43 If positive=True we cut the most positive data points, False=we cut the negative ones.
45 out=[item for item in data] #we copy just to be sure...
50 temp_absdev=absdev(out)
52 for index in range(len(out)):
54 cut_absdev=absdev(out[cutindex:]) #we jump five points after five points...
55 if 1-(cut_absdev/temp_absdev) < stable and cutindex<(maxcut*len(out)):
56 temp_absdev=cut_absdev
62 def abovenoise(convoluted,noise_level,cut_index=0,abs_devs=4):
64 Generates a vector which is 0 where the vector is less than abs_devs*noise_level ; 1 if not (spike).
66 #calculate absolute noise deviation
67 #noise_level=noise_absdev(convoluted[cut_index:])
71 for index in range(len(convoluted)):
75 #FIXME: should calculate the *average* (here we assume that convolution mean is 0, which is FALSE!)
76 if convoluted[index] < -1*noise_level*abs_devs:
77 above.append(convoluted[index])
82 def find_peaks(above, seedouble=10):
84 Finds individual peak location.
85 abovenoise() finds all points above a given threshold in the convolution. This point is often not unique
86 but there is a "cluster" of points above a threshold.
87 Here we obtain only the coordinates of the largest *convolution* spike for each cluster.
89 above=vector obtained from abovenoise()
90 seedouble=value at which we want to "delete" double peaks. That is, if two peaks have a distance
91 < than $seedouble points , only the first is kept.
97 for index in range(len(above)):
101 if len(nonzero) != 0:
103 nonzero.append(nonzero[0]+1)
104 peaks_size.append(min(above[nonzero[0]:nonzero[-1]]))
105 peaks_location.append(above[nonzero[0]:nonzero[-1]].index(peaks_size[-1])+nonzero[0])
110 #recursively eliminate double peaks
111 #(maybe not the smartest of cycles, but i'm asleep...)
113 while temp_location != []:
115 if len(peaks_location)>1:
116 for index in range(len(peaks_location)-1):
117 if peaks_location[index+1]-peaks_location[index] < seedouble:
118 temp_location=peaks_location[:index]+peaks_location[index+1:]
119 if temp_location != []:
120 peaks_location=temp_location
122 return peaks_location,peaks_size