1 # Copyright (C) 2007-2010 Fabrizio Benedetti
2 # Massimo Sandal <devicerandom@gmail.com>
3 # W. Trevor King <wking@drexel.edu>
5 # This file is part of Hooke.
7 # Hooke is free software: you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation, either
10 # version 3 of the License, or (at your option) any later version.
12 # Hooke is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with Hooke. If not, see
19 # <http://www.gnu.org/licenses/>.
21 """a library of helping functions for spotting force spectroscopy peaks.
26 def conv_dx(data,vect):
28 Returns the right-centered convolution of data with vector vect
37 for k in range(window):
38 temparr[j]+=data[j+k]*vect[k]
44 Calculates the absolute deviation of a vector
54 def noise_absdev(data,positive=False,maxcut=0.2,stable=0.005):
56 Returns the standard deviation of the noise.
57 The logic is: we cut the most negative (or positive) data points until the absolute deviation
58 becomes stable (it doesn't vary more than 0.005) or we have cut more than maxcut*len(data) points.
59 Then calculate the absolute deviation.
61 If positive=True we cut the most positive data points, False=we cut the negative ones.
63 out=[item for item in data] #we copy just to be sure...
68 temp_absdev=absdev(out)
70 for index in range(len(out)):
72 cut_absdev=absdev(out[cutindex:]) #we jump five points after five points...
73 if 1-(cut_absdev/temp_absdev) < stable and cutindex<(maxcut*len(out)):
74 temp_absdev=cut_absdev
80 def abovenoise(convoluted,noise_level,cut_index=0,abs_devs=4):
82 Generates a vector which is 0 where the vector is less than abs_devs*noise_level ; 1 if not (spike).
84 #calculate absolute noise deviation
85 #noise_level=noise_absdev(convoluted[cut_index:])
89 for index in range(len(convoluted)):
93 #FIXME: should calculate the *average* (here we assume that convolution mean is 0, which is FALSE!)
94 if convoluted[index] < -1*noise_level*abs_devs:
95 above.append(convoluted[index])
100 def find_peaks(above, seedouble=10):
102 Finds individual peak location.
103 abovenoise() finds all points above a given threshold in the convolution. This point is often not unique
104 but there is a "cluster" of points above a threshold.
105 Here we obtain only the coordinates of the largest *convolution* spike for each cluster.
107 above=vector obtained from abovenoise()
108 seedouble=value at which we want to "delete" double peaks. That is, if two peaks have a distance
109 < than $seedouble points , only the first is kept.
115 for index in range(len(above)):
116 if above[index] != 0:
117 nonzero.append(index)
119 if len(nonzero) != 0:
121 nonzero.append(nonzero[0]+1)
122 peaks_size.append(min(above[nonzero[0]:nonzero[-1]]))
123 peaks_location.append(above[nonzero[0]:nonzero[-1]].index(peaks_size[-1])+nonzero[0])
128 #recursively eliminate double peaks
129 #(maybe not the smartest of cycles, but i'm asleep...)
131 while temp_location != []:
133 if len(peaks_location)>1:
134 for index in range(len(peaks_location)-1):
135 if peaks_location[index+1]-peaks_location[index] < seedouble:
136 temp_location=peaks_location[:index]+peaks_location[index+1:]
137 if temp_location != []:
138 peaks_location=temp_location
140 return peaks_location,peaks_size