def peakfinding(): # first step of getting peaks peaks_obj = Data(frq, abs(Y), smoothness=11) # second part of getting peaks peaks_obj.get_peaks(method='slope') # pull data out of peaks data object for filtering peaks_obj.peaks["peaks"] peaks = peaks_obj.peaks["peaks"] peaks_obj.plot() show() peaksnp = np.zeros((2, len(peaks[0]))) peaksnp[0] = peaks[0] peaksnp[1] = peaks[1] maxpeaks = max(peaks[1]) # filtering function: removes peaks that are shorter than 10% of the max peak filteredpeaksnp = [] cutoff = .05 filtered_peaks = ma.masked_less(peaksnp[1], (cutoff * maxpeaks)) indeces = ma.nonzero(filtered_peaks) indeces = indeces[0] final_peaks = np.zeros((3,len(indeces))) i = 0 while i < len(indeces): final_peaks [0,i] = frq[i] final_peaks[1,i] = peaksnp[1, indeces[i]] final_peaks[2,i] = peaksnp[0, indeces[i]] i = i + 1
def find_peaks(self): print '# Finding peaks.' for i in self.data: for e in self.data[i]: hist = Data(list(self.data[i][e].index), list(self.data[i][e]['hits']), smoothness=1, default_smooth=False) hist.normalize() try: hist.get_peaks(method="slope", peak_amp_thresh=0.00005, valley_thresh=0.00003, intervals=None, lookahead=self.lookahead, avg_interval=100) self.data[i][e]['peaks'] = sorted(np.array(hist.peaks['peaks'][0]).tolist()) self.data[i][e]['valleys'] = sorted(np.array(hist.peaks['valleys'][0]).tolist()) except ValueError: self.data[i][e]['peaks'] = [] self.data[i][e]['valleys'] = [] return True
def find_peaks(func,interpolation_points=1000,peak_finding_smoothness=30, plot=False, plot_new_fig=True): x = np.arange(0,len(func)) y = func f = interp1d(x,y,kind='linear') x_2 = np.linspace(0,len(func)-1,interpolation_points) y_2 = f(x_2) data_obj = Data(x_2,y_2,smoothness=peak_finding_smoothness) data_obj.normalize() try: data_obj.get_peaks(method='slope') if plot==True: data_obj.plot(new_fig=plot_new_fig) return data_obj except ValueError: return 0
def find_peaks(func, interpolation_points=1000, peak_finding_smoothness=30, plot=False, plot_new_fig=True): x = np.arange(0, len(func)) y = func f = interp1d(x, y, kind='linear') x_2 = np.linspace(0, len(func) - 1, interpolation_points) y_2 = f(x_2) data_obj = Data(x_2, y_2, smoothness=peak_finding_smoothness) data_obj.normalize() try: data_obj.get_peaks(method='slope') if plot == True: data_obj.plot(new_fig=plot_new_fig) return data_obj except ValueError: return 0
def find_peaks_big_array(func,interpolation_points=1000,peak_finding_smoothness=30, plot=False, plot_new_fig=True): """Find peaks on 'big' arrays doesn't work when array is normalized... So this function doesn't normalize the array before running the peaks method.""" x = np.arange(0,len(func)) y = func f = interp1d(x,y,kind='linear') x_2 = np.linspace(0,len(func)-1,interpolation_points) y_2 = f(x_2) data_obj = Data(x_2,y_2,smoothness=peak_finding_smoothness) #data_obj.normalize() try: data_obj.get_peaks(method='slope') if plot==True: data_obj.plot(new_fig=plot_new_fig) return data_obj except ValueError: return 0
def find_peaks_big_array(func, interpolation_points=1000, peak_finding_smoothness=30, plot=False, plot_new_fig=True): """Find peaks on 'big' arrays doesn't work when array is normalized... So this function doesn't normalize the array before running the peaks method.""" x = np.arange(0, len(func)) y = func f = interp1d(x, y, kind='linear') x_2 = np.linspace(0, len(func) - 1, interpolation_points) y_2 = f(x_2) data_obj = Data(x_2, y_2, smoothness=peak_finding_smoothness) #data_obj.normalize() try: data_obj.get_peaks(method='slope') if plot == True: data_obj.plot(new_fig=plot_new_fig) return data_obj except ValueError: return 0
#Import necessary modules import pickle from pypeaks import Data, Intervals #Load data #We already have provided some data samples and a script in examples/ directory. #If you don't have it, you can either load your own data, or download them from #https://github.com/gopalkoduri/pypeaks data = pickle.load(file("../examples/sample-histogram.pickle")) hist = Data(data[0], data[1]) #Get peaks by slope method and plot them hist.get_peaks(method='slope') hist.plot() #Get peaks by interval method and plot them #In the example/ folder, there is a pickle file with some example intervals, #in this case, just-intonation intervals for music. They can refer to any intervals! ji_intervals = pickle.load(file('../examples/ji-intervals.pickle')) ji_intervals = Intervals(ji_intervals) hist.get_peaks(method='interval', intervals=ji_intervals) hist.plot(intervals=ji_intervals.intervals) #Accessing the peaks data #The Data object has x, y_raw, y, smoothness and peaks variables available. #The help functions shows the methods available for it:
def getpeaks(frq, Y, cutoff, showplot, plot_title, smooth = 5, plotraw = False): """ Description: This is used to find peaks in an fft. Parameters: frq: frequency data from an fft, Y: amplitude data from an fft, cutoff: percent of highest peak at which we'll consider other peaks. (eg: .10 means we'll save all peaks that are 10% or more of the highest peak in amplitude. plot_title: title for the plot, if the user wants a plot, showplot: boolean to either show or not show a completed peaks plot, plotraw: boolean to either show or not show the canned plot the pypeaks package makes. Calculations: (1) uses pypeaks to get peaks. This is a rough measure, because it smooths the fft so much. (2) first filtering step: removes peaks that are smaller than the cutoff * highest peak. (3) second filtering step: compares the x,y data for the found peaks to the actual values on the fft. In particular, pypeaks smooths the data, so the real peaks are a bit off. This filtering step finds the real local maximum on the fft. Returns: cfg.final_peaks: 2-d array that contains x and y values of the peaks. """ # first step of getting peaks - smooths the fft # smoothness value can be changed to make the peak-detection more or less sensitive depending on your needs. peaks_obj = Data(frq, Y, smoothness=smooth) #second part of getting peaks peaks_obj.get_peaks(method='slope') # gives a raw, built-in plot of the peak data. Axes aren't particularly meaningful, but can be a useful sanity check. if plotraw: peaks_obj.plot() #pull data out of peaks data object for filtering peaks = peaks_obj.peaks["peaks"] peaksnp = np.zeros((2, len(peaks[0]))) peaksnp[0] = peaks[0] peaksnp[1] = peaks[1] maxpeaks = max(peaks_obj.peaks["peaks"][1]) # first filtering function: removes peaks that are shorter than the cutoff specified in function filteredypeaks = [] filteredxpeaks = [] filter_thresh = cutoff * maxpeaks readvar = 0 while readvar < len(peaks_obj.peaks["peaks"][1]): if peaks_obj.peaks["peaks"][1][readvar] > filter_thresh: filteredxpeaks.append(peaks_obj.peaks["peaks"][0][readvar]) filteredypeaks.append(peaks_obj.peaks["peaks"][1][readvar]) readvar = readvar +1 filteredpeaks = [filteredxpeaks, filteredypeaks] #puts filteredpeaks into a numpy array for the second filtering step filter1_peaks = np.array(filteredpeaks) filter1_peaksy = [] # gets the absolute value of the Y array so we don't get weird errors. absY = abs(Y) # superimposes the found peaks onto our array from the wav file readvar = 0 while readvar < len(filter1_peaks[1]): ypeak = np.searchsorted(frq,[filter1_peaks[0][readvar,]],side='left')[0] filter1_peaksy.append(absY[ypeak]) readvar = readvar + 1 # now we have to get the peaks in order, so that each peak is relative to his nearest neighbor. Important for optimizing peaks in the next step. this is very important if you don't want innapropriate peaks! indexarray = np.argsort(filter1_peaks[0]) indexed_array=filter1_peaks[:,indexarray] # second filtering step. Judders peaks back and forth along the x-axis of the frequency plot until they reach the true local max (y) rangeleft_arr = [] rangeright_arr = [] finalpeaksx = [] finalpeaksy = [] cfg.final_peaks = np.zeros((2, len(filter1_peaks[1]))) # if we only have one peak, we just write that one to the final_peaks array if len(filter1_peaks[0]) == 1: finalpeaky = max(abs(Y)) # filtering step to remove freqencies outside of a reasonable range. This probably isn't the best option, but since we have # A good idea of what the frequencies should be, this is a reasonable cutoff and we will just remove the feature outright rather # than trying to fix it. indexy = np.where(abs(Y) == finalpeaky) finalpeakx = frq[indexy] cfg.final_peaks[0] = finalpeakx finalpeaksy.append(finalpeaky) cfg.final_peaks[1] = finalpeaky maxpeak = round(finalpeakx,2) else: readvar = 0 while readvar < len(indexed_array[0]): # figure out the x-distance to the next closest peak, then if readvar == 0: xdist = abs(indexed_array[0][readvar +1] - indexed_array[0][readvar]) elif readvar == len(indexed_array[0]) - 1: xdist = abs(indexed_array[0][readvar - 1] - indexed_array[0][readvar]) else: distright = abs(indexed_array[0][readvar +1] - indexed_array[0][readvar]) distleft = abs(indexed_array[0][readvar - 1] - indexed_array[0][readvar]) xdist = min(distright, distleft) # we want to search the half the distance to the next closest peak. Calculates this distance and finds it on the wav file. xdist2 = xdist/2 rangeleft = max(0, indexed_array[0][readvar] - xdist2) rangeright = min(indexed_array[0][readvar] + xdist2, max(frq)) rangeright_arr.append(rangeright) rangeleft_arr.append(rangeleft) readvar = readvar + 1 readvar = 0 while readvar < len(rangeright_arr): # actually gets the local maximum and matches it to an x value xmin = np.searchsorted(frq,[rangeleft_arr[readvar]],side='left')[0] xmax = np.searchsorted(frq,[rangeright_arr[readvar]],side ='right')[0] finalpeaky = max(abs(Y)[xmin:xmax]) indexy = np.where(abs(Y)==finalpeaky) finalpeakx = frq[indexy] cfg.final_peaks[0][readvar] = finalpeakx cfg.final_peaks[1][readvar] = finalpeaky maxarray = max([frq[xmin:xmax]]) readvar = readvar + 1 #figures out where the max. peak is. We do this by finding the highest peak in the y peak values, then finding the index of it in the other part of the array maxy = max(cfg.final_peaks[1]) maxyindex = np.where(cfg.final_peaks[1]==maxy) cfg.maxpeak = round(cfg.final_peaks[0][maxyindex],2) #get rid of peaks above 1 kHz for when we're calculating that interval peaksforinterval = [x for x in cfg.final_peaks[0] if x < 1000] intervals = [] i = 1 while i < len(peaksforinterval): intervals.append(peaksforinterval[i]-peaksforinterval[i-1]) i += 1 fundcalc = np.mean(intervals) fundcalc = round(fundcalc,2) # a little error checking for fundamental frequency, in case there are weird peaks further down the line. If the fundamental frequency is greater than 10 Hz different from peak frequency, change fundamental to peak. This will catch most (but not all) of the issues we were having before if abs(fundcalc - cfg.maxpeak) > 10: fundcalc = cfg.maxpeak maxpeakstr = str(cfg.maxpeak) + " Hz" fundcalcstr = str(fundcalc) + " Hz" #this allows the user to double-check peaks and hand-calculate a fundamental (and peak) if desired. We assume that the peak frequency will be ok regardless, but this algorithm doesn't do a great job with the fundmentals. if showplot: # shows plot if user requests it # plotting the spectrum fig = plt.gcf() fig.canvas.set_window_title(cfg.plotinfo) p1 = plt.plot(frq,abs(Y),'r') # plotting the original (non-filtered) peaks. Uncomment this if you want to see how the peak-optimizing algorithm is working #p2 = plt.plot(c, filter1_peaksy, linestyle = "none", marker = "o", color = "black") # plotting the filtered peaks p3 = plt.plot(cfg.final_peaks[0], cfg.final_peaks[1], linestyle = "none", marker = "o", color = "black") # Gives max. peak and fundamental in the title plt.title(" Max peak: " + maxpeakstr + "\nFundamental: " + fundcalcstr) pylab.xlim([0,500]) xlabel('Freq (Hz)') ylabel('|Y(freq)|') plt.show() peakspresent = np.round_(cfg.final_peaks[0], decimals=2, out=None) peakspresent = re.sub('[ ]+', ' ', re.sub(' *[\\[\\]] *', '', np.array_str(peakspresent))) fundok = tkMessageBox.askyesno(cfg.plotinfo, "Fundamental is calculated as " + fundcalcstr + ". Does this look ok?") if fundok: cfg.fund = fundcalc else: cfg.fund = tkSimpleDialog.askfloat(cfg.plotinfo, "The peaks are:\n" + peakspresent) cfg.fund = round(cfg.fund,2) # a bit more error-checking, in case the peak-finding algorithm completely fails. Note that this assumes that the peak is the same as the fundamental if cfg.maxpeak > 500: cfg.maxpeak = cfg.fund return cfg.final_peaks
def getpeaks(frq, Y, cutoff, showplot, smooth=10, plot_title="Your plot, fine sir/madam: ", plotraw=False): """ Description: This is used to find peaks in an fft. Parameters: frq: frequency data from an fft, Y: amplitude data from an fft, cutoff: percent of highest peak at which we'll consider other peaks. (eg: .10 means we'll save all peaks that are 10% or more of the highest peak in amplitude. plot_title: title for the plot, if the user wants a plot, showplot: boolean to either show or not show a completed peaks plot, plotraw: boolean to either show or not show the canned plot the pypeaks package makes. Calculations: (1) uses pypeaks to get peaks. This is a rough measure, because it smooths the fft so much. (2) first filtering step: removes peaks that are smaller than the cutoff * highest peak. (3) second filtering step: compares the x,y data for the found peaks to the actual values on the fft. In particular, pypeaks smooths the data, so the real peaks are a bit off. This filtering step finds the real local maximum on the fft. Returns: cfg.final_peaks: 2-d array that contains x and y values of the peaks. """ # first step of getting peaks - smooths the fft # smoothness value can be changed to make the peak-detection more or less sensitive depending on your needs. peaks_obj = Data(frq, Y, smoothness=smooth) #second part of getting peaks peaks_obj.get_peaks(method='slope') # gives a raw, built-in plot of the peak data. Axes aren't particularly meaningful, but can be a useful sanity check. if plotraw: peaks_obj.plot() #pull data out of peaks data object for filtering peaks = peaks_obj.peaks["peaks"] peaksnp = np.zeros((2, len(peaks[0]))) peaksnp[0] = peaks[0] peaksnp[1] = peaks[1] maxpeaks = max(peaks_obj.peaks["peaks"][1]) # first filtering function: removes peaks that are shorter than the cutoff specified in function filteredypeaks = [] filteredxpeaks = [] filter_thresh = cutoff * maxpeaks readvar = 0 while readvar < len(peaks_obj.peaks["peaks"][1]): if peaks_obj.peaks["peaks"][1][readvar] > filter_thresh: filteredxpeaks.append(peaks_obj.peaks["peaks"][0][readvar]) filteredypeaks.append(peaks_obj.peaks["peaks"][1][readvar]) readvar = readvar + 1 filteredpeaks = [filteredxpeaks, filteredypeaks] #puts filteredpeaks into a numpy array for the second filtering step filter1_peaks = np.array(filteredpeaks) filter1_peaksy = [] # gets the absolute value of the Y array so we don't get weird errors. absY = abs(Y) # superimposes the found peaks onto our array from the wav file readvar = 0 while readvar < len(filter1_peaks[1]): ypeak = np.searchsorted(frq, [filter1_peaks[0][readvar, ]], side='left')[0] filter1_peaksy.append(absY[ypeak]) readvar = readvar + 1 # now we have to get the peaks in order, so that each peak is relative to his nearest neighbor. Important for optimizing peaks in the next step. this is very important if you don't want innapropriate peaks! indexarray = np.argsort(filter1_peaks[0]) indexed_array = filter1_peaks[:, indexarray] # second filtering step. Judders peaks back and forth along the x-axis of the frequency plot until they reach the true local max (y) rangeleft_arr = [] rangeright_arr = [] finalpeaksx = [] finalpeaksy = [] cfg.final_peaks = np.zeros((2, len(filter1_peaks[1]))) # if we only have one peak, we just write that one to the final_peaks array if len(filter1_peaks[0]) == 1: finalpeaky = max(abs(Y)) # filtering step to remove freqencies outside of a reasonable range. This probably isn't the best option, but since we have # A good idea of what the frequencies should be, this is a reasonable cutoff and we will just remove the feature outright rather # than trying to fix it. indexy = np.where(abs(Y) == finalpeaky) finalpeakx = frq[indexy] cfg.final_peaks[0] = finalpeakx finalpeaksy.append(finalpeaky) cfg.final_peaks[1] = finalpeaky maxpeak = round(finalpeakx, 0) else: readvar = 0 while readvar < len(indexed_array[0]): # figure out the x-distance to the next closest peak, then if readvar == 0: xdist = abs(indexed_array[0][readvar + 1] - indexed_array[0][readvar]) elif readvar == len(indexed_array[0]) - 1: xdist = abs(indexed_array[0][readvar - 1] - indexed_array[0][readvar]) else: distright = abs(indexed_array[0][readvar + 1] - indexed_array[0][readvar]) distleft = abs(indexed_array[0][readvar - 1] - indexed_array[0][readvar]) xdist = min(distright, distleft) # we want to search the half the distance to the next closest peak. Calculates this distance and finds it on the wav file. xdist2 = xdist / 2 rangeleft = max(0, indexed_array[0][readvar] - xdist2) rangeright = min(indexed_array[0][readvar] + xdist2, max(frq)) rangeright_arr.append(rangeright) rangeleft_arr.append(rangeleft) readvar = readvar + 1 readvar = 0 while readvar < len(rangeright_arr): # actually gets the local maximum and matches it to an x value xmin = np.searchsorted(frq, [rangeleft_arr[readvar]], side='left')[0] xmax = np.searchsorted(frq, [rangeright_arr[readvar]], side='right')[0] finalpeaky = max(abs(Y)[xmin:xmax]) indexy = np.where(abs(Y) == finalpeaky) finalpeakx = frq[indexy] cfg.final_peaks[0][readvar] = finalpeakx cfg.final_peaks[1][readvar] = finalpeaky maxarray = max([frq[xmin:xmax]]) readvar = readvar + 1 maxpeak = round(max(cfg.final_peaks[1]), 0) maxpeakstr = str(maxpeak) + " Hz" if showplot: # shows plot if user requests it # plotting the spectrum p1 = plt.plot(frq, abs(Y), 'r') # plotting the original (non-filtered) peaks p2 = plt.plot(filter1_peaks[0], filter1_peaksy, linestyle="none", marker="o", color="black") # plotting the filtered peaks p3 = plt.plot(cfg.final_peaks[0], cfg.final_peaks[1], linestyle="none", marker="o", color="green") # defines the title based on the string that the user put in plt.title(plot_title + " - max peak at: " + maxpeakstr) pylab.xlim([0, 500]) xlabel('Freq (Hz)') ylabel('|Y(freq)|') plt.show() return cfg.final_peaks