Example #1
0
    def compute_hist(self,
                     bins=None,
                     density=True,
                     folded=False,
                     weight="duration"):
        """
        Computes histogram from the pitch data in Pitch object (pitch), and creates
        a Data object (pypeaks).

        :param bins: Refers to number of bins in the histogram, determines the granularity.
        If it is not set, the number of bins which gives the highest granularity is chosen
        automatically.
        :param density: defaults to True, which means the histogram will be a normalized one.
        :param folded: defaults to False. When set to True, all the octaves are folded to one.
        :param weight: It can be one of the 'duration' or 'instance'. In the latter case, make
        sure that the pitch object has the pitch values discretized.
        """
        #Step 1: get the right pitch values
        assert isinstance(self.pitch_obj.pitch, np.ndarray)
        valid_pitch = self.pitch_obj.pitch
        valid_pitch = [i for i in valid_pitch if i > -10000]
        if folded:
            valid_pitch = map(lambda x: int(x % 1200), valid_pitch)

        #Step 2: based on the weighing scheme, compute the histogram
        if weight == "duration":
            #Step 2.1 set the number of bins (if not passed)
            if not bins:
                bins = max(valid_pitch) - min(valid_pitch)
            n, bin_edges = np.histogram(valid_pitch, bins, density=density)
            bin_centers = 0.5 * (bin_edges[1:] + bin_edges[:-1])
            self.histogram = Data(bin_centers, n)
        elif weight == "instance":
            n = {}
            i = 1
            while i < len(valid_pitch) - 1:
                if (valid_pitch[i] - valid_pitch[i - 1] != 0) and \
                        (valid_pitch[i + 1] - valid_pitch[i] == 0):
                    if valid_pitch[i] in n.keys():
                        n[valid_pitch[i]] += 1
                    else:
                        n[valid_pitch[i]] = 1
                i += 1
            n = n.items()
            n.sort(key=lambda x: x[0])
            n = np.array(n)
            self.histogram = Data(n[:, 0], n[:, 1])

            median_diff = np.median(np.diff(n[:, 0]))
            bin_edges = [n[0, 0] - median_diff / 2]
            bin_edges.extend(median_diff / 2 + n[:, 0])
            n[:, 1] = n[:, 1] / (n[:, 1].sum() * np.diff(bin_edges))
            self.histogram = Data(n[:, 0], n[:, 1], default_smooth=False)
Example #2
0
 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
Example #3
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
Example #4
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
Example #5
0
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
Example #6
0
# -*- coding: utf-8 -*-

#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