def test_peaks_plot(self): data = self.data.copy() data[30] = 100 data[60] = 40 threshold = 10 peaks = findpeaks.find_peaks2_short(data, threshold, 3) fig = peaks_plot(data=data, starttime=UTCDateTime("2008001"), samp_rate=10, peaks=peaks, show=False, return_figure=True) return fig
def _median_window(window, window_start, multiplier, starttime, sampling_rate, debug=0): """ Internal function to aid parallel processing :type window: numpy.ndarry :param window: Data to look for peaks in. :type window_start: int :param window_start: Index of window start point in larger array, used \ for peak indexing. :type multiplier: float :param multiplier: Multiple of MAD to use as threshold :type starttime: obspy.core.utcdatetime.UTCDateTime :param starttime: Starttime of window, used in debug plotting. :type sampling_rate: float :param sampling_rate in Hz, used for debug plotting :type debug: int :param debug: debug level, if want plots, >= 4. :returns: peaks :rtype: list """ from eqcorrscan.utils.findpeaks import find_peaks2_short from eqcorrscan.utils.plotting import peaks_plot MAD = np.median(np.abs(window)) thresh = multiplier * MAD if debug >= 2: print('Threshold for window is: ' + str(thresh) + '\nMedian is: ' + str(MAD) + '\nMax is: ' + str(np.max(window))) peaks = find_peaks2_short(arr=window, thresh=thresh, trig_int=5, debug=0) if debug >= 4 and peaks: peaks_plot(window, starttime, sampling_rate, save=False, peaks=peaks) if peaks: peaks = [(peak[0], peak[1] + window_start) for peak in peaks] else: peaks = [] return peaks
def _median_window(window, window_start, multiplier, starttime, sampling_rate, debug=0): """Internal function to aid parallel processing :type window: np.ndarry :param window: Data to look for peaks in. :type window_start: int :param window_start: Index of window start point in larger array, used \ for peak indexing. :type multiplier: float :param multiplier: Multiple of MAD to use as threshold :type starttime: obspy.UTCDateTime :param starttime: Starttime of window, used in debug plotting. :type sampling_rate: float :param sampling_rate in Hz, used for debug plotting :type debug: int :param debug: debug level, if want plots, >= 4. :returns: peaks """ from eqcorrscan.utils.findpeaks import find_peaks2_short from eqcorrscan.utils.plotting import peaks_plot MAD = np.median(np.abs(window)) thresh = multiplier * MAD if debug >= 2: print('Threshold for window is: ' + str(thresh) + '\nMedian is: ' + str(MAD) + '\nMax is: ' + str(np.max(window))) peaks = find_peaks2_short(arr=window, thresh=thresh, trig_int=5, debug=0) if debug >= 4 and peaks: peaks_plot(window, starttime, sampling_rate, save=False, peaks=peaks) if peaks: peaks = [(peak[0], peak[1] + window_start) for peak in peaks] else: peaks = [] return peaks
def find_peaks2_short(arr, thresh, trig_int, debug=0, starttime=False, samp_rate=1.0): """ Determine peaks in an array of data above a certain threshold. Uses a mask to remove data below threshold and finds peaks in what is left. :type arr: numpy.ndarray :param arr: 1-D numpy array is required :type thresh: float :param thresh: The threshold below which will be considered noise and \ peaks will not be found in. :type trig_int: int :param trig_int: The minimum difference in samples between triggers,\ if multiple peaks within this window this code will find the highest. :type debug: int :param debug: Optional, debug level 0-5 :type starttime: obspy.core.utcdatetime.UTCDateTime :param starttime: Starttime for plotting, only used if debug > 2. :type samp_rate: float :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2. :return: peaks: Lists of tuples of peak values and locations. :rtype: list >>> import numpy as np >>> arr = np.random.randn(100) >>> threshold = 10 >>> arr[40] = 20 >>> arr[60] = 100 >>> find_peaks2_short(arr, threshold, 3) [(20.0, 40), (100.0, 60)] """ if not starttime: starttime = UTCDateTime(0) # Set everything below the threshold to zero image = np.copy(arr) image = np.abs(image) image[image < thresh] = 0 if len(image[image > thresh]) == 0: if debug > 0: print('No values over threshold found') return [] if debug > 0: print(' '.join(['Found', str(len(image[image > thresh])), 'samples above the threshold'])) initial_peaks = [] peaks = [] # Find the peaks labeled_image, number_of_objects = ndimage.label(image) peak_slices = ndimage.find_objects(labeled_image) for peak_slice in peak_slices: # print('Width of peak='+str(peak_slice[0].stop-peak_slice[0].start) window = arr[peak_slice[0].start: peak_slice[0].stop] initial_peaks.append((max(window), int(peak_slice[0].start + np.argmax(window)))) if initial_peaks: peaks = decluster(peaks=initial_peaks, trig_int=trig_int, debug=debug) if debug >= 3: from eqcorrscan.utils import plotting _fname = ''.join(['peaks_', starttime.datetime.strftime('%Y-%m-%d'), '.pdf']) plotting.peaks_plot(data=image, starttime=starttime, samp_rate=samp_rate, save=True, peaks=peaks, savefile=_fname) peaks = sorted(peaks, key=lambda time: time[1], reverse=False) return peaks else: print('No peaks for you!') return peaks
def find_peaks2_short(arr, thresh, trig_int, debug=0, starttime=False, samp_rate=1.0, full_peaks=False): """ Determine peaks in an array of data above a certain threshold. Uses a mask to remove data below threshold and finds peaks in what is left. :type arr: numpy.ndarray :param arr: 1-D numpy array is required :type thresh: float :param thresh: The threshold below which will be considered noise and peaks will not be found in. :type trig_int: int :param trig_int: The minimum difference in samples between triggers, if multiple peaks within this window this code will find the highest. :type debug: int :param debug: Optional, debug level 0-5 :type starttime: obspy.core.utcdatetime.UTCDateTime :param starttime: Starttime for plotting, only used if debug > 2. :type samp_rate: float :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2. :type full_peaks: bool :param full_peaks: If True, will remove the issue eluded to below, by declustering within data-sections above the threshold, rather than just taking the peak within that section. This will take more time. This defaults to True for match_filter. :return: peaks: Lists of tuples of peak values and locations. :rtype: list >>> import numpy as np >>> arr = np.random.randn(100) >>> threshold = 10 >>> arr[40] = 20 >>> arr[60] = 100 >>> find_peaks2_short(arr, threshold, 3) [(20.0, 40), (100.0, 60)] .. note:: peak-finding is optimised for zero-mean cross-correlation data where fluctuations are frequent. Because of this, in certain cases some peaks may be missed if the trig_int is short and the threshold is low. Consider the following case: >>> arr = np.array([1, .2, .2, .2, .2, 1, .2, .2, .2, .2, 1]) >>> find_peaks2_short(arr, thresh=.2, trig_int=3) [(1.0, 0)] Whereas you would expect the following: >>> arr = np.array([1, .2, .2, .2, .2, 1, .2, .2, .2, .2, 1]) >>> find_peaks2_short(arr, thresh=.2, trig_int=3, full_peaks=True) [(1.0, 0), (1.0, 5), (1.0, 10)] This is rare and unlikely to happen for correlation cases, where trigger intervals are usually large and thresholds high. """ if not starttime: starttime = UTCDateTime(0) # Set everything below the threshold to zero image = np.copy(arr) image = np.abs(image) debug_print("Threshold: {0}\tMax: {1}".format(thresh, max(image)), 2, debug) image[image < thresh] = 0 if len(image[image > thresh]) == 0: debug_print("No values over threshold {0}".format(thresh), 0, debug) return [] debug_print( 'Found {0} samples above the threshold'.format( len(image[image > thresh])), 0, debug) initial_peaks = [] # Find the peaks labeled_image, number_of_objects = ndimage.label(image) peak_slices = ndimage.find_objects(labeled_image) for peak_slice in peak_slices: window = arr[peak_slice[0].start:peak_slice[0].stop] if peak_slice[0].stop - peak_slice[0].start > trig_int and full_peaks: peaks = decluster(peaks=window, trig_int=trig_int, index=np.arange(peak_slice[0].start, peak_slice[0].stop)) else: peaks = [(window[np.argmax(abs(window))], int(peak_slice[0].start + np.argmax(abs(window))))] initial_peaks.extend(peaks) peaks = decluster(peaks=np.array(list(zip(*initial_peaks))[0]), index=np.array(list(zip(*initial_peaks))[1]), trig_int=trig_int) if initial_peaks: if debug >= 3: from eqcorrscan.utils import plotting _fname = ''.join( ['peaks_', starttime.datetime.strftime('%Y-%m-%d'), '.pdf']) plotting.peaks_plot(data=image, starttime=starttime, samp_rate=samp_rate, save=True, peaks=peaks, savefile=_fname) peaks = sorted(peaks, key=lambda time: time[1], reverse=False) return peaks else: print('No peaks for you!') return []
def find_peaks2(arr, thresh, trig_int, debug=0, maxwidth=10, starttime=False, samp_rate=1.0): r"""Function to determine peaks in an array of data using scipy \ find_peaks_cwt, works fast in certain cases, but for match_filter cccsum \ peak finding, find_peaks2_short works better. Test it out and see which \ works best for your application. :type arr: ndarray :param arr: 1-D numpy array is required :type thresh: float :param thresh: The threshold below which will be considered noise and \ peaks will not be found in. :type trig_int: int :param trig_int: The minimum difference in samples between triggers, \ if multiple peaks within this window this code will find the highest. :type debug: int :param debug: Optional, debug level 0-5 :type maxwidth: int :param maxwidth: Maximum peak width to look for in samples :type starttime: osbpy.UTCDateTime :param starttime: Starttime for plotting, only used if debug > 2. :type samp_rate: float :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2. :return: peaks: Lists of tuples of peak values and locations. """ from scipy.signal import find_peaks_cwt import numpy as np from obspy import UTCDateTime if not starttime: starttime = UTCDateTime(0) # Set everything below the threshold to zero image = np.copy(arr) image = np.abs(image) image[image < thresh] = thresh # We need to check if the number of samples in the image is prime, if it # is this method will be really slow, so we add a pad to the end to make # it not of prime length! if is_prime(len(image)): image = np.append(image, 0.0) print('Input array has a prime number of samples, appending a zero') print(len(image)) if len(image[image > thresh]) == 0: print('No values over threshold found') return [] if debug > 0: msg = ' '.join(['Found', str(len(image[image > thresh])), 'samples above the threshold']) print(msg) initial_peaks = [] peaks = [] # Find the peaks print('Finding peaks') peakinds = find_peaks_cwt(image, np.arange(1, maxwidth)) initial_peaks = [(image[peakind], peakind) for peakind in peakinds] # Sort initial peaks according to amplitude print('sorting peaks') peaks_sort = sorted(initial_peaks, key=lambda amplitude: amplitude[0], reverse=True) if debug >= 4: for peak in initial_peaks: print(peak) if initial_peaks: peaks.append(peaks_sort[0]) # Definitely take the biggest peak if debug > 3: msg = ' '.join(['Added the biggest peak of', str(peaks[0][0]), 'at sample', str(peaks[0][1])]) print(msg) if len(initial_peaks) > 1: if debug > 3: msg = ' '.join(['Multiple peaks found, checking them', 'now to see if they overlap']) print(msg) for next_peak in peaks_sort: # i in xrange(1,len(peaks_sort)): # Loop through the amplitude sorted peaks # if the next highest amplitude peak is within trig_int of any # peak already in peaks then we don't want it, else, add it # next_peak = peaks_sort[i] if debug > 3: print(next_peak) for peak in peaks: add = False # Use add as a switch for whether or not to append # next peak to peaks, if once gone through all the peaks # it is True, then we will add it, otherwise we won't! if abs(next_peak[1] - peak[1]) < trig_int: if debug > 3: msg = ' '.join(['Difference in time is', str(next_peak[1] - peak[1]), '\n' 'Which is less than', str(trig_int)]) print(msg) add = False # Need to exit the loop here if false break else: add = True if add: if debug > 3: msg = ' '.join(['Adding peak of', str(next_peak[0]), 'at sample', str(next_peak[1])]) print(msg) peaks.append(next_peak) elif debug > 3: msg = ' '.join(['I did not add peak of', str(next_peak[0]), 'at sample', str(next_peak[1])]) print(msg) if debug >= 3: from eqcorrscan.utils import plotting _fname = ''.join(['peaks_', starttime.datetime.strftime('%Y-%m-%d'), '.pdf']) print(' '.join(['Saving plot to', _fname])) plotting.peaks_plot(image, starttime, samp_rate, True, peaks, _fname) peaks = sorted(peaks, key=lambda time: time[1], reverse=False) return peaks else: print('No peaks for you!') return peaks
def find_peaks_dep(arr, thresh, trig_int, debug=0, starttime=False, samp_rate=1.0): r"""Function to determine peaks in an array of data above a certain \ threshold. Depreciated peak-finding routine, very slow, but accurate. If all else \ fails this one should work. :type arr: ndarray :param arr: 1-D numpy array is required :type thresh: float :param thresh: The threshold below which will be considered noise and \ peaks will not be found in. :type trig_int: int :param trig_int: The minimum difference in samples between triggers,\ if multiple peaks within this window this code will find the highest. :type starttime: osbpy.UTCDateTime :param starttime: Starttime for plotting, only used if debug > 2. :type samp_rate: float :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2. :return: peaks: Lists of tuples of peak values and locations. """ import numpy as np from obspy import UTCDateTime if not starttime: starttime = UTCDateTime(0) # Perform some checks if trig_int < 3: msg = 'Trigger interval must be greater than 2 samples to find maxima' raise IOError(msg) # from joblib import Parallel, delayed # Will find peaks in the absolute then transfer these to the true values sig = np.abs(arr) - thresh true_peaks = [] for i in xrange(int(trig_int), int(len(sig) - trig_int), int(trig_int)): window = sig[i - trig_int: i + trig_int] # Define a moving window containing data from +/- the trigger iterval peaks = [] locs = [] for j in xrange(1, len(window) - 1): # Find all turning points within the window if window[j] > 0.0 and window[j] > window[j+1] and\ window[j] > window[j - 1]: peaks.append(window[j]) locs.append(i - trig_int + j) # Find maximum peak in window if peaks: true_peaks.append((np.max(np.array(peaks)), locs[np.argmax(np.array(peaks))])) # Get unique values peaks = sorted(list(set(true_peaks)), key=lambda loc: loc[1]) # Find highest peak in peaks within trig_int of each other for i in xrange(1, len(peaks) - 1): if peaks[i + 1][1]-peaks[i][1] < trig_int: if peaks[i][0] < peaks[i + 1][0]: peaks[i] = peaks[i + 1] else: peaks[i + 1] = peaks[i] elif peaks[i][1] - peaks[i - 1][1] < trig_int: if peaks[i][0] < peaks[i - 1][0]: peaks[i] = peaks[i - 1] else: peaks[i - 1] = peaks[i] peaks = sorted(list(set(peaks)), key=lambda loc: loc[1]) if debug >= 3: from eqcorrscan.utils import plotting _fname = ''.join(['peaks_', starttime.datetime.strftime('%Y-%m-%d'), '.pdf']) plotting.peaks_plot(arr, starttime, samp_rate, True, peaks, _fname) return peaks
def find_peaks2_short(arr, thresh, trig_int, debug=0, starttime=False, samp_rate=1.0): r"""Function to determine peaks in an array of data above a certain \ threshold. Uses a mask to remove data below threshold and finds peaks in \ what is left. :type arr: ndarray :param arr: 1-D numpy array is required :type thresh: float :param thresh: The threshold below which will be considered noise and \ peaks will not be found in. :type trig_int: int :param trig_int: The minimum difference in samples between triggers,\ if multiple peaks within this window this code will find the highest. :type debug: int :param debug: Optional, debug level 0-5 :type starttime: osbpy.UTCDateTime :param starttime: Starttime for plotting, only used if debug > 2. :type samp_rate: float :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2. :return: peaks: Lists of tuples of peak values and locations. """ from scipy import ndimage import numpy as np from obspy import UTCDateTime if not starttime: starttime = UTCDateTime(0) # Set everything below the threshold to zero image = np.copy(arr) image = np.abs(image) image[image < thresh] = 0 if len(image[image > thresh]) == 0: print('No values over threshold found') return [] if debug > 0: print(' '.join(['Found', str(len(image[image > thresh])), 'samples above the threshold'])) initial_peaks = [] peaks = [] # Find the peaks labeled_image, number_of_objects = ndimage.label(image) peak_slices = ndimage.find_objects(labeled_image) for peak_slice in peak_slices: # print('Width of peak='+str(peak_slice[0].stop-peak_slice[0].start) window = arr[peak_slice[0].start: peak_slice[0].stop] initial_peaks.append((max(window), peak_slice[0].start + np.argmax(window))) # Sort initial peaks according to amplitude peaks_sort = sorted(initial_peaks, key=lambda amplitude: amplitude[0], reverse=True) # Debugging if debug >= 4: for peak in initial_peaks: print(peak) if initial_peaks: peaks.append(peaks_sort[0]) # Definitely take the biggest peak if debug > 3: print(' '.join(['Added the biggest peak of', str(peaks[0][0]), 'at sample', str(peaks[0][1])])) if len(initial_peaks) > 1: if debug > 3: msg = ' '.join(['Multiple peaks found, checking', 'them now to see if they overlap']) print(msg) for next_peak in peaks_sort: # i in xrange(1,len(peaks_sort)): # Loop through the amplitude sorted peaks # if the next highest amplitude peak is within trig_int of any # peak already in peaks then we don't want it, else, add it # next_peak=peaks_sort[i] if debug > 3: print(next_peak) for peak in peaks: add = False # Use add as a switch for whether or not to append # next peak to peaks, if once gone through all the peaks # it is True, then we will add it, otherwise we won't! if abs(next_peak[1]-peak[1]) < trig_int: if debug > 3: msg = ' '.join(['Difference in time is', str(next_peak[1]-peak[1]), '\n', 'Which is less than', str(trig_int)]) print(msg) add = False # Need to exit the loop here if false break else: add = True if add: if debug > 3: msg = ' '.join(['Adding peak of', str(next_peak[0]), 'at sample', str(next_peak[1])]) print(msg) peaks.append(next_peak) elif debug > 3: msg = ' '.join(['I did not add peak of', str(next_peak[0]), 'at sample', str(next_peak[1])]) print(msg) if debug >= 3: from eqcorrscan.utils import plotting _fname = ''.join(['peaks_', starttime.datetime.strftime('%Y-%m-%d'), '.pdf']) plotting.peaks_plot(image, starttime, samp_rate, True, peaks, _fname) peaks = sorted(peaks, key=lambda time: time[1], reverse=False) return peaks else: print('No peaks for you!') return peaks
def find_peaks2_short(arr, thresh, trig_int, debug=0, starttime=False, samp_rate=1.0): """ Determine peaks in an array of data above a certain threshold. Uses a mask to remove data below threshold and finds peaks in what is left. :type arr: numpy.ndarray :param arr: 1-D numpy array is required :type thresh: float :param thresh: The threshold below which will be considered noise and \ peaks will not be found in. :type trig_int: int :param trig_int: The minimum difference in samples between triggers,\ if multiple peaks within this window this code will find the highest. :type debug: int :param debug: Optional, debug level 0-5 :type starttime: obspy.core.utcdatetime.UTCDateTime :param starttime: Starttime for plotting, only used if debug > 2. :type samp_rate: float :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2. :return: peaks: Lists of tuples of peak values and locations. :rtype: list >>> import numpy as np >>> arr = np.random.randn(100) >>> threshold = 10 >>> arr[40] = 20 >>> arr[60] = 100 >>> find_peaks2_short(arr, threshold, 3) [(20.0, 40), (100.0, 60)] """ if not starttime: starttime = UTCDateTime(0) # Set everything below the threshold to zero image = np.copy(arr) image = np.abs(image) image[image < thresh] = 0 if len(image[image > thresh]) == 0: if debug > 0: print('No values over threshold found') return [] if debug > 0: print(' '.join(['Found', str(len(image[image > thresh])), 'samples above the threshold'])) initial_peaks = [] peaks = [] # Find the peaks labeled_image, number_of_objects = ndimage.label(image) peak_slices = ndimage.find_objects(labeled_image) for peak_slice in peak_slices: # print('Width of peak='+str(peak_slice[0].stop-peak_slice[0].start) window = arr[peak_slice[0].start: peak_slice[0].stop] initial_peaks.append((max(window), int(peak_slice[0].start + np.argmax(window)))) # Sort initial peaks according to amplitude peaks_sort = sorted(initial_peaks, key=lambda amplitude: amplitude[0], reverse=True) # Debugging if debug >= 4: for peak in initial_peaks: print(peak) if initial_peaks: peaks.append(peaks_sort[0]) # Definitely take the biggest peak if debug > 3: print(' '.join(['Added the biggest peak of', str(peaks[0][0]), 'at sample', str(peaks[0][1])])) if len(initial_peaks) > 1: if debug > 3: msg = ' '.join(['Multiple peaks found, checking', 'them now to see if they overlap']) print(msg) for next_peak in peaks_sort: # i in range(1,len(peaks_sort)): # Loop through the amplitude sorted peaks # if the next highest amplitude peak is within trig_int of any # peak already in peaks then we don't want it, else, add it # next_peak=peaks_sort[i] if debug > 3: print(next_peak) for peak in peaks: # Use add as a switch for whether or not to append # next peak to peaks, if once gone through all the peaks # it is True, then we will add it, otherwise we won't! if abs(next_peak[1] - peak[1]) < trig_int: if debug > 3: msg = ' '.join(['Difference in time is', str(next_peak[1] - peak[1]), '\n', 'Which is less than', str(trig_int)]) print(msg) add = False # Need to exit the loop here if false break else: add = True if add: if debug > 3: msg = ' '.join(['Adding peak of', str(next_peak[0]), 'at sample', str(next_peak[1])]) print(msg) peaks.append(next_peak) elif debug > 3: msg = ' '.join(['I did not add peak of', str(next_peak[0]), 'at sample', str(next_peak[1])]) print(msg) if debug >= 3: from eqcorrscan.utils import plotting _fname = ''.join(['peaks_', starttime.datetime.strftime('%Y-%m-%d'), '.pdf']) plotting.peaks_plot(data=image, starttime=starttime, samp_rate=samp_rate, save=True, peaks=peaks, savefile=_fname) peaks = sorted(peaks, key=lambda time: time[1], reverse=False) return peaks else: print('No peaks for you!') return peaks
def find_peaks_dep(arr, thresh, trig_int, debug=0, starttime=False, samp_rate=1.0): """ Determine peaks in an array of data above a certain threshold: depreciated. Depreciated peak-finding routine, very slow, but accurate. If all else \ fails this one should work. :type arr: numpy.ndarray :param arr: 1-D numpy array is required :type thresh: float :param thresh: The threshold below which will be considered noise and \ peaks will not be found in. :type trig_int: int :param trig_int: The minimum difference in samples between triggers,\ if multiple peaks within this window this code will find the highest. :type starttime: obspy.core.utcdatetime.UTCDateTime :param starttime: Starttime for plotting, only used if debug > 2. :type samp_rate: float :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2. :return: peaks: Lists of tuples of peak values and locations. :rtype: list >>> import numpy as np >>> arr = np.random.randn(100) >>> threshold = 10 >>> arr[40] = 20 >>> arr[60] = 100 >>> find_peaks_dep(arr, threshold, 3) [(20.0, 40), (100.0, 60)] """ if not starttime: starttime = UTCDateTime(0) # Perform some checks if trig_int < 3: msg = 'Trigger interval must be greater than 2 samples to find maxima' raise IOError(msg) # from joblib import Parallel, delayed # Will find peaks in the absolute then transfer these to the true values sig = np.abs(arr) - thresh true_peaks = [] for i in range(int(trig_int), int(len(sig) - trig_int), int(trig_int)): window = sig[i - trig_int: i + trig_int] # Define a moving window containing data from +/- the trigger iterval peaks = [] locs = [] for j in range(1, len(window) - 1): # Find all turning points within the window if window[j] > 0.0 and window[j] > window[j + 1] and\ window[j] > window[j - 1]: peaks.append(window[j]) locs.append(i - trig_int + j) # Find maximum peak in window if peaks: true_peaks.append((np.max(np.array(peaks)), locs[np.argmax(np.array(peaks))])) # Get unique values peaks = sorted(list(set(true_peaks)), key=lambda loc: loc[1]) # Find highest peak in peaks within trig_int of each other for i in range(1, len(peaks) - 1): if peaks[i + 1][1] - peaks[i][1] < trig_int: if peaks[i][0] < peaks[i + 1][0]: peaks[i] = peaks[i + 1] else: peaks[i + 1] = peaks[i] elif peaks[i][1] - peaks[i - 1][1] < trig_int: if peaks[i][0] < peaks[i - 1][0]: peaks[i] = peaks[i - 1] else: peaks[i - 1] = peaks[i] peaks = sorted(list(set(peaks)), key=lambda loc: loc[1]) if debug >= 3: from eqcorrscan.utils import plotting _fname = ''.join(['peaks_', starttime.datetime.strftime('%Y-%m-%d'), '.pdf']) plotting.peaks_plot(arr, starttime, samp_rate, True, peaks, _fname) peaks = [(peak[0] + thresh, peak[1]) for peak in peaks] return peaks
def find_peaks2(arr, thresh, trig_int, debug=0, maxwidth=10, starttime=False, samp_rate=1.0): r"""Function to determine peaks in an array of data using scipy \ find_peaks_cwt, works fast in certain cases, but for match_filter cccsum \ peak finding, find_peaks2_short works better. Test it out and see which \ works best for your application. :type arr: ndarray :param arr: 1-D numpy array is required :type thresh: float :param thresh: The threshold below which will be considered noise and \ peaks will not be found in. :type trig_int: int :param trig_int: The minimum difference in samples between triggers, \ if multiple peaks within this window this code will find the highest. :type debug: int :param debug: Optional, debug level 0-5 :type maxwidth: int :param maxwidth: Maximum peak width to look for in samples :type starttime: osbpy.UTCDateTime :param starttime: Starttime for plotting, only used if debug > 2. :type samp_rate: float :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2. :return: peaks: Lists of tuples of peak values and locations. """ from scipy.signal import find_peaks_cwt import numpy as np from obspy import UTCDateTime if not starttime: starttime = UTCDateTime(0) # Set everything below the threshold to zero image = np.copy(arr) image = np.abs(image) image[image < thresh] = thresh # We need to check if the number of samples in the image is prime, if it # is this method will be really slow, so we add a pad to the end to make # it not of prime length! if is_prime(len(image)): image = np.append(image, 0.0) print('Input array has a prime number of samples, appending a zero') print(len(image)) if len(image[image > thresh]) == 0: print('No values over threshold found') return [] if debug > 0: msg = ' '.join([ 'Found', str(len(image[image > thresh])), 'samples above the threshold' ]) print(msg) initial_peaks = [] peaks = [] # Find the peaks print('Finding peaks') peakinds = find_peaks_cwt(image, np.arange(1, maxwidth)) initial_peaks = [(image[peakind], peakind) for peakind in peakinds] # Sort initial peaks according to amplitude print('sorting peaks') peaks_sort = sorted(initial_peaks, key=lambda amplitude: amplitude[0], reverse=True) if debug >= 4: for peak in initial_peaks: print(peak) if initial_peaks: peaks.append(peaks_sort[0]) # Definitely take the biggest peak if debug > 3: msg = ' '.join([ 'Added the biggest peak of', str(peaks[0][0]), 'at sample', str(peaks[0][1]) ]) print(msg) if len(initial_peaks) > 1: if debug > 3: msg = ' '.join([ 'Multiple peaks found, checking them', 'now to see if they overlap' ]) print(msg) for next_peak in peaks_sort: # i in xrange(1,len(peaks_sort)): # Loop through the amplitude sorted peaks # if the next highest amplitude peak is within trig_int of any # peak already in peaks then we don't want it, else, add it # next_peak = peaks_sort[i] if debug > 3: print(next_peak) for peak in peaks: add = False # Use add as a switch for whether or not to append # next peak to peaks, if once gone through all the peaks # it is True, then we will add it, otherwise we won't! if abs(next_peak[1] - peak[1]) < trig_int: if debug > 3: msg = ' '.join([ 'Difference in time is', str(next_peak[1] - peak[1]), '\n' 'Which is less than', str(trig_int) ]) print(msg) add = False # Need to exit the loop here if false break else: add = True if add: if debug > 3: msg = ' '.join([ 'Adding peak of', str(next_peak[0]), 'at sample', str(next_peak[1]) ]) print(msg) peaks.append(next_peak) elif debug > 3: msg = ' '.join([ 'I did not add peak of', str(next_peak[0]), 'at sample', str(next_peak[1]) ]) print(msg) if debug >= 3: from eqcorrscan.utils import plotting _fname = ''.join( ['peaks_', starttime.datetime.strftime('%Y-%m-%d'), '.pdf']) print(' '.join(['Saving plot to', _fname])) plotting.peaks_plot(image, starttime, samp_rate, True, peaks, _fname) peaks = sorted(peaks, key=lambda time: time[1], reverse=False) return peaks else: print('No peaks for you!') return peaks