def __init__(self, signal, time, frequency=100e3, wavelet='Mexican'): """ Parameters ---------- signal : ndarray Signal to be analyzed time : ndarray Time basis frequency : Float Fourier frequency for the analysis wavelet : :obj: `str` String indicating the type of wavelet used for the analysis. Default is 'Mexican' """ if wavelet == 'Mexican': self.mother = wav.MexicanHat() elif wavelet == 'DOG1': self.mother = wav.DOG(m=1) elif wavelet == 'Morlet': self.mother = wav.Morlet() else: print 'Not a valid wavelet using Mexican' self.mother = wav.MexicanHat() # inizializza l'opportuna scala self.fr = frequency self.scale = 1. / self.mother.flambda() / self.fr self.sig = copy.deepcopy(signal) self.nsamp = signal.size self.time = copy.deepcopy(time) self.dt = (time.max() - time.min()) / (self.nsamp - 1) self.Fs = 1. / self.dt self.cwt()
def graph_wavelet(data_xs, title, lims, font = 11, params = default_params): a_lims, b_lims, d_lims = lims plt.rcParams.update({'font.size': font}) return_data = {} N = len(data_xs) dt = (2*params['per_pixel'])/N #This is how much cm each pixel equals t = np.arange(0, N) * dt t = t - np.mean(t) t0 = 0 per_min = params['min_per'] per_max = params['max_per'] units = params['units'] sx = params['sx'] octaves = params['octaves'] dj = 1/params['suboctaves'] #suboctaves order = params['order'] var, std, dat_norm = detrend(data_xs) mother = cwt.DOG(order) #This is the Mother Wavelet s0 = sx * dt #This is the starting scale, which in out case is two pixels or 0.04cm/40um\ J = octaves/dj #This is powers of two with dj suboctaves return_data['var'] = var return_data['std'] = std try: alpha, _, _ = cwt.ar1(dat_norm) #This calculates the Lag-1 autocorrelation for red noise except: alpha = 0.95 wave, scales, freqs, coi, fft, fftfreqs = cwt.cwt(dat_norm, dt, dj, s0, J, mother) return_data['scales'] = scales return_data['freqs'] = freqs return_data['fft'] = fft iwave = cwt.icwt(wave, scales, dt, dj, mother) * std power = (np.abs(wave)) ** 2 fft_power = np.abs(fft) ** 2 period = 1 / freqs power /= scales[:, None] #This is an option suggested by Liu et. al. #Next we calculate the significance of the power spectra. Significane where power / sig95 > 1 signif, fft_theor = cwt.significance(1.0, dt, scales, 0, alpha, significance_level=0.95, wavelet=mother) sig95 = np.ones([1, N]) * signif[:, None] sig95 = power / sig95 glbl_power = power.mean(axis=1) dof = N - scales # Correction for padding at edges glbl_signif, tmp = cwt.significance(var, dt, scales, 1, alpha, significance_level=0.95, dof=dof, wavelet=mother) sel = find((period >= per_min) & (period < per_max)) Cdelta = mother.cdelta scale_avg = (scales * np.ones((N, 1))).transpose() scale_avg = power / scale_avg # As in Torrence and Compo (1998) equation 24 scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0) scale_avg_signif, tmp = cwt.significance(var, dt, scales, 2, alpha, significance_level=0.95, dof=[scales[sel[0]], scales[sel[-1]]], wavelet=mother) # Prepare the figure plt.close('all') plt.ioff() figprops = dict(figsize=(11, 11), dpi=72) fig = plt.figure(**figprops) wx = plt.axes([0.77, 0.75, 0.2, 0.2]) imz = 0 for idxy in range(0,len(period), 10): wx.plot(t, mother.psi(t / period[idxy]) + imz, linewidth = 1.5) imz+=1 wx.xaxis.set_ticklabels([]) ax = plt.axes([0.1, 0.75, 0.65, 0.2]) ax.plot(t, data_xs, 'k', linewidth=1.5) ax.plot(t, iwave, '-', linewidth=1, color=[0.5, 0.5, 0.5]) ax.plot(t, dat_norm, '--', linewidth=1.5, color=[0.5, 0.5, 0.5]) if a_lims != None: ax.set_ylim([-a_lims, a_lims]) ax.set_title('a) {}'.format(title)) ax.set_ylabel(r'Displacement [{}]'.format(units)) #ax.set_ylim([-20,20]) bx = plt.axes([0.1, 0.37, 0.65, 0.28], sharex=ax) levels = [0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16] bx.contourf(t, np.log2(period), np.log2(power), np.log2(levels), extend='both', cmap=plt.cm.viridis) extent = [t.min(), t.max(), 0, max(period)] bx.contour(t, np.log2(period), sig95, [-99, 1], colors='k', linewidths=2, extent=extent) bx.fill(np.concatenate([t, t[-1:] + dt, t[-1:] + dt, t[:1] - dt, t[:1] - dt]), np.concatenate([np.log2(coi), [1e-9], np.log2(period[-1:]), np.log2(period[-1:]), [1e-9]]), 'k', alpha=0.3, hatch='x') bx.set_title('b) {} Octaves Wavelet Power Spectrum [{}({})]'.format(octaves, mother.name, order)) bx.set_ylabel('Period (cm)') # Yticks = 2 ** np.arange(np.ceil(np.log2(period.min())), np.ceil(np.log2(period.max()))) bx.set_yticks(np.log2(Yticks)) bx.set_yticklabels(Yticks) # Third sub-plot, the global wavelet and Fourier power spectra and theoretical # noise spectra. Note that period scale is logarithmic. cx = plt.axes([0.77, 0.37, 0.2, 0.28], sharey=bx) cx.plot(glbl_signif, np.log2(period), 'k--') cx.plot(var * fft_theor, np.log2(period), '--', color='#cccccc') cx.plot(var * fft_power, np.log2(1./fftfreqs), '-', color='#cccccc', linewidth=1.) return_data['global_power'] = var * glbl_power return_data['fourier_spectra'] = var * fft_power return_data['per'] = np.log2(period) return_data['amp'] = np.log2(1./fftfreqs) cx.plot(var * glbl_power, np.log2(period), 'k-', linewidth=1.5) cx.set_title('c) Power Spectrum') cx.set_xlabel(r'Power [({})^2]'.format(units)) if b_lims != None: cx.set_xlim([0,b_lims]) #cx.set_xlim([0,max(glbl_power.max(), var*fft_power.max())]) #print(max(glbl_power.max(), var*fft_power.max())) cx.set_ylim(np.log2([period.min(), period.max()])) cx.set_yticks(np.log2(Yticks)) cx.set_yticklabels(Yticks) return_data['yticks'] = Yticks plt.setp(cx.get_yticklabels(), visible=False) # Fourth sub-plot, the scale averaged wavelet spectrum. dx = plt.axes([0.1, 0.07, 0.65, 0.2], sharex=ax) dx.axhline(scale_avg_signif, color='k', linestyle='--', linewidth=1.) dx.plot(t, scale_avg, 'k-', linewidth=1.5) dx.set_title('d) {}--{} cm scale-averaged power'.format(per_min, per_max)) dx.set_xlabel('Displacement (cm)') dx.set_ylabel(r'Average variance [{}]'.format(units)) ax.set_xlim([t.min(), t.max()]) if d_lims != None: dx.set_ylim([0,d_lims]) plt.savefig("C:\pyscripts\wavelet_analysis\Calibrated Images\{}".format(title)) return fig, return_data
import numpy as np from scipy import signal from scipy import interpolate import pycwt as wavelet from statsmodels.tsa.ar_model import AutoReg mother_wave_dict = { 'gaussian': wavelet.DOG(), 'paul': wavelet.Paul(), 'mexican_hat': wavelet.MexicanHat() } def calculate_power(freq, pow, fmin, fmax): """ Compute the power within the band range Parameters ---------- freq: array-like list of all frequencies need to be computed pow: array-like the power of relevant frequencies fmin: float lower bound of the selected band fmax: float upper bound of the selected band Returns ------- :float
def parse_frames(image_file, sig=0.95): """ """ cap = cv2.VideoCapture(image_file) if verbose: print("Video successfully loaded") FRAME_COUNT = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) FPS = cap.get(cv2.CAP_PROP_FPS) if verbose > 1: FRAME_HEIGHT = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) FRAME_WIDTH = cap.get(cv2.CAP_PROP_FRAME_WIDTH) print( "INFO: \n Frame count: ", FRAME_COUNT, "\n", "FPS: ", FPS, " \n", "FRAME_HEIGHT: ", FRAME_HEIGHT, " \n", "FRAME_WIDTH: ", FRAME_WIDTH, " \n", ) directory = os.getcwd( ) + '\\analysis\\{}_{}_{}_{}({})_{}_{}_scaled\\'.format( date, trial_type, name, wavelet, order, per_min, per_max) if not os.path.exists(directory): os.makedirs(directory) made = False frame_idx = 0 idx = 0 dropped = 0 skip = True thresh = None df_wav = pd.DataFrame() df_auc = pd.DataFrame() df_for = pd.DataFrame() df_pow = pd.DataFrame() for i in range(FRAME_COUNT): a, img = cap.read() if a: frame_idx += 1 if made == False: #first we need to manually determine the boundaries and angle res = bg.manual_format(img) #print(res) x, y, w, h, angle = res horizon_begin = x horizon_end = x + w vert_begin = y vert_end = y + h #scale_array = np.zeros((FRAME_COUNT, abs(horizon_begin - horizon_end))) #area_time = np.zeros((FRAME_COUNT)) #df['] print("Now Select the Red dot") red_res = bg.manual_format(img, stop_sign=True) red_x, red_y, red_w, red_h = red_res box_h_begin = red_x box_h_end = red_x + red_w box_v_begin = red_y box_v_end = red_y + red_h made = True #dims = (vert_begin, vert_end, horizon_begin, horizon_end) real_time = i / FPS rows, cols, chs = img.shape M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1) rot_img = cv2.warpAffine(img, M, (cols, rows)) roi = rot_img[vert_begin:vert_end, horizon_begin:horizon_end, :] red_box = img[box_v_begin:box_v_end, box_h_begin:box_h_end, 2] if thresh == None: thresh = np.mean(red_box) #print(np.mean(red_box)) percent_drop = 1 - (np.mean(red_box) / thresh) print(percent_drop) if percent_drop >= 0.18: #cv2.imshow("Red Image", red_box) #cv2.waitKey(0) skip = False if skip: if verbose >= 1: print('Frame is skipped {} / {}'.format( frame_idx, FRAME_COUNT)) continue if verbose >= 1: print('Processing frame {} / {}'.format( frame_idx, FRAME_COUNT)) idx += 1 begin_code, data_line = extract_frame(roi) #We need to detrend the data before sending it away N = len(data_line) dt = su / N t = np.arange(0, N) * dt t = t - np.mean(t) var, std, dat_norm = detrend(data_line) ################################################################### if wavelet == 'DOG': mother = cwt.DOG(order) elif wavelet == 'Paul': mother = cwt.Paul(order) elif wavelet == 'Morlet': mother = cwt.Morlet(order) elif wavelet == 'MexicanHat': mother = cwt.MexicanHat(order) s0 = 4 * dt try: alpha, _, _ = cwt.ar1(dat_norm) except: alpha = 0.95 wave, scales, freqs, coi, fft, fftfreqs = cwt.cwt( dat_norm, dt, dj, s0, J, mother) iwave = cwt.icwt( wave, scales, dt, dj, mother) * std #This is a reconstruction of the wave power = (np.abs(wave))**2 #This is the power spectra fft_power = np.abs(fft)**2 #This is the fourier power period = 1 / freqs #This is the periods of the wavelet analysis in cm power /= scales[:, None] #This is an option suggested by Liu et. al. #Next we calculate the significance of the power spectra. Significane where power / sig95 > 1 signif, fft_theor = cwt.significance(1.0, dt, scales, 0, alpha, significance_level=0.95, wavelet=mother) sig95 = np.ones([1, N]) * signif[:, None] sig95 = power / sig95 #This is the significance of the global wave glbl_power = power.mean(axis=1) dof = N - scales # Correction for padding at edges glbl_signif, tmp = cwt.significance(var, dt, scales, 1, alpha, significance_level=0.95, dof=dof, wavelet=mother) sel = find((period >= per_min) & (period < per_max)) Cdelta = mother.cdelta scale_avg = (scales * np.ones((N, 1))).transpose() scale_avg = power / scale_avg # As in Torrence and Compo (1998) equation 24 #scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0) #scale_array[i,:] = scale_array[i,:]/np.max(scale_array[i,:]) #data_array[i,:] = data_array[i,:]/np.max(data_array[i,:]) scale_avg = var * dj * dt / Cdelta * scale_avg[sel, :].sum(axis=0) scale_avg_signif, tmp = cwt.significance( var, dt, scales, 2, alpha, significance_level=0.95, dof=[scales[sel[0]], scales[sel[-1]]], wavelet=mother) Yticks = 2**np.arange(np.ceil(np.log2(period.min())), np.ceil(np.log2(period.max()))) plt.close('all') plt.ioff() figprops = dict(figsize=(11, 8), dpi=72) fig = plt.figure(**figprops) wx = plt.axes([0.77, 0.75, 0.2, 0.2]) imz = 0 for idxy in range(0, len(period), 10): wx.plot(t, mother.psi(t / period[idxy]) + imz, linewidth=1.5) imz += 1 wx.xaxis.set_ticklabels([]) #wx.set_ylim([-10,10]) # First sub-plot, the original time series anomaly and inverse wavelet # transform. ax = plt.axes([0.1, 0.75, 0.65, 0.2]) ax.plot(t, data_line - np.mean(data_line), 'k', label="Original Data") ax.plot(t, iwave, '-', linewidth=1, color=[0.5, 0.5, 0.5], label="Reconstructed wave") ax.plot(t, dat_norm, '--k', linewidth=1.5, color=[0.5, 0.5, 0.5], label="Denoised Wave") ax.set_title( 'a) {:10.2f} from beginning of trial.'.format(real_time)) ax.set_ylabel(r'{} [{}]'.format("Amplitude", unit)) ax.legend(loc=1) ax.set_ylim([-200, 200]) #If the non-serrated section, bounds are 200 - # Second sub-plot, the normalized wavelet power spectrum and significance # level contour lines and cone of influece hatched area. Note that period # scale is logarithmic. bx = plt.axes([0.1, 0.37, 0.65, 0.28], sharex=ax) levels = [0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16] cont = bx.contourf(t, np.log2(period), np.log2(power), np.log2(levels), extend='both', cmap=plt.cm.viridis) extent = [t.min(), t.max(), 0, max(period)] bx.contour(t, np.log2(period), sig95, [-99, 1], colors='k', linewidths=2, extent=extent) bx.fill(np.concatenate( [t, t[-1:] + dt, t[-1:] + dt, t[:1] - dt, t[:1] - dt]), np.concatenate([ np.log2(coi), [1e-9], np.log2(period[-1:]), np.log2(period[-1:]), [1e-9] ]), 'k', alpha=0.3, hatch='x') bx.set_title( 'b) {} Octaves Wavelet Power Spectrum [{}({})]'.format( octaves, mother.name, order)) bx.set_ylabel('Period (cm)') # Yticks = 2**np.arange(np.ceil(np.log2(period.min())), np.ceil(np.log2(period.max()))) bx.set_yticks(np.log2(Yticks)) bx.set_yticklabels(Yticks) cbar = fig.colorbar(cont, ax=bx) # Third sub-plot, the global wavelet and Fourier power spectra and theoretical # noise spectra. Note that period scale is logarithmic. cx = plt.axes([0.77, 0.37, 0.2, 0.28], sharey=bx) cx.plot(glbl_signif, np.log2(period), 'k--') cx.plot(var * fft_theor, np.log2(period), '--', color='#cccccc') cx.plot(var * fft_power, np.log2(1. / fftfreqs), '-', color='#cccccc', linewidth=1.) cx.plot(var * glbl_power, np.log2(period), 'k-', linewidth=1.5) cx.set_title('c) Global Wavelet Spectrum') cx.set_xlabel(r'Power [({})^2]'.format(unit)) #cx.set_xlim([0, (var*fft_theor).max()]) plt.xscale('log') cx.set_ylim(np.log2([period.min(), period.max()])) cx.set_yticks(np.log2(Yticks)) cx.set_yticklabels(Yticks) #if sig_array == []: yvals = np.linspace(Yticks.min(), Yticks.max(), len(period)) plt.xscale('linear') plt.setp(cx.get_yticklabels(), visible=False) # Fourth sub-plot, the scale averaged wavelet spectrum. dx = plt.axes([0.1, 0.07, 0.65, 0.2], sharex=ax) dx.axhline(scale_avg_signif, color='k', linestyle='--', linewidth=1.) dx.plot(t, scale_avg, 'k-', linewidth=1.5) dx.set_title('d) {}-{}cm scale-averaged power'.format( per_min, per_max)) dx.set_xlabel('Distance from center(cm)') dx.set_ylabel(r'Average variance [{}]'.format(unit)) #dx.set_ylim([0,500]) ax.set_xlim([t.min(), t.max()]) #plt.savefig(directory+'{}_analysis_frame-{}.png'.format(name, idx), bbox = 'tight') if verbose >= 2: print('*' * int((i / FRAME_COUNT) * 100)) df_wav[real_time] = (pd.Series(dat_norm, index=t)) df_pow[real_time] = (pd.Series(var * glbl_power, index=np.log2(period))) df_for[real_time] = (pd.Series(var * fft_power, index=np.log2(1. / fftfreqs))) df_auc[real_time] = [np.trapz(data_line)] else: print("Frame #{} has dropped".format(i)) dropped += 1 if verbose >= 1: print('All images saved') if verbose >= 1: print("{:10.2f} % of the frames have dropped".format( (dropped / FRAME_COUNT) * 100)) #Plotting and saving tyhe row, cols = df_pow.shape time = np.arange(0, cols) / FPS plt.close('all') plt.ioff() plt.contourf(time, df_pow.index.tolist(), df_pow) plt.contour(time, df_pow.index.tolist(), df_pow) plt.title("Global Power over Time") plt.ylabel("Period[cm]") plt.xlabel("Time") cax = plt.gca() #plt.xscale('log') cax.set_ylim(np.log2([period.min(), period.max()])) cax.set_yticks(np.log2(Yticks)) cax.set_yticklabels(Yticks) plt.savefig(directory + '{}_global_power-{}.png'.format(name, idx), bbox='tight') row, cols = df_for.shape time = np.arange(0, cols) / FPS plt.close('all') plt.ioff() plt.contourf(time, df_for.index.tolist(), df_for) plt.contour(time, df_for.index.tolist(), df_for) plt.title("Fourier Power over Time") plt.ylabel("Period[cm]") plt.xlabel("Time") cax = plt.gca() #plt.xscale('log') cax.set_ylim(np.log2([period.min(), period.max()])) cax.set_yticks(np.log2(Yticks)) cax.set_yticklabels(Yticks) plt.savefig(directory + '{}_fourier_power-{}.png'.format(name, idx), bbox='tight') plt.close('all') plt.ioff() rows, cols = df_auc.shape time = np.arange(0, cols) / FPS plt.plot(time, df_auc.T) plt.xlabel("Time") plt.ylabel("Area under the curve in cm") plt.title("Area under the curve over time") plt.savefig(directory + '{}_area_under_curve-{}.png'.format(name, idx), bbox='tight') df_wav['Mean'] = df_wav.mean(axis=1) df_pow['Mean'] = df_pow.mean(axis=1) df_for['Mean'] = df_for.mean(axis=1) df_auc['Mean'] = df_auc.mean(axis=1) df_wav['Standard Deviation'] = df_wav.std(axis=1) df_pow['Standard Deviation'] = df_pow.std(axis=1) df_for['Standard Deviation'] = df_for.std(axis=1) df_auc['Standard Deviation'] = df_auc.std(axis=1) ##[Writing analysis to excel]############################################## print("Writing files") writer = pd.ExcelWriter(directory + "analysis{}.xlsx".format(trial_name)) df_wav.to_excel(writer, "Raw Waveforms") df_auc.to_excel(writer, "Area Under the Curve") df_for.to_excel(writer, "Fourier Spectra") df_pow.to_excel(writer, "Global Power Spectra") writer.save() ##[Writing means to a single file]######################################### #filename = 'C:\\pyscripts\\wavelet_analysis\\Overall_Analysis.xlsx' #append_data(filename, df_pow['Mean'].values, str(trial_name), Yticks) ##[Plotting mean power and foruier]######################################## plt.close('all') plt.ioff() plt.plot(df_pow['Mean'], df_pow.index.tolist(), label="Global Power") plt.plot(df_for['Mean'], df_for.index.tolist(), label="Fourier Power") plt.title("Global Power averaged over Time") plt.ylabel("Period[cm]") plt.xlabel("Power[cm^2]") cax = plt.gca() #plt.xscale('log') cax.set_ylim(np.log2([period.min(), period.max()])) cax.set_yticks(np.log2(Yticks)) cax.set_yticklabels(Yticks) plt.legend() plt.savefig(directory + '{}_both_{}.png'.format(name, idx), bbox='tight') plt.close('all') plt.ioff() plt.plot(df_pow['Mean'], df_pow.index.tolist(), label="Global Power") plt.title("Global Power averaged over Time") plt.ylabel("Period[cm]") plt.xlabel("Power[cm^2]") cax = plt.gca() #plt.xscale('log') cax.set_ylim(np.log2([period.min(), period.max()])) cax.set_yticks(np.log2(Yticks)) cax.set_yticklabels(Yticks) plt.legend() plt.savefig(directory + '{}_global_power_{}.png'.format(name, idx), bbox='tight') plt.close('all') plt.ioff() plt.plot(df_for['Mean'], df_for.index.tolist(), label="Fourier Power") plt.title("Fourier averaged over Time") plt.ylabel("Period[cm]") plt.xlabel("Power[cm^2]") cax = plt.gca() #plt.xscale('log') cax.set_ylim(np.log2([period.min(), period.max()])) cax.set_yticks(np.log2(Yticks)) cax.set_yticklabels(Yticks) plt.legend() plt.savefig(directory + '{}_fourier_{}.png'.format(name, idx), bbox='tight') cap.release() return directory
def limStructure(self, frequency=100e3, wavelet='Mexican', peaks=False, valleys=False): """ Determination of the time location of the intermittent structure accordingly to the method defined in *M. Onorato et al Phys. Rev. E 61, 1447 (2000)* Parameters ---------- frequency : :obj: `float` Fourier frequency considered for the analysis wavelet : :obj: `string` Mother wavelet for the continuous wavelet analysis possibilityes are *Mexican [default]*, *DOG1* or *Morlet* peaks : :obj: `Boolean` if set it computes the structure only for the peaks Default is False valleys : :obj: `Boolean` if set it computes the structure only for the valleys Default is False Returns ------- maxima : :obj: `ndarray` A binary array equal to 1 at the identification of the structure (local maxima) allmax : :obj: `ndarray` A binary array equal to 1 in all the region where the signal is above the threshold Attributes ---------- scale : :obj: `float` Corresponding scale for the chosen wavelet """ if wavelet == 'Mexican': self.mother = wav.MexicanHat() elif wavelet == 'DOG1': self.mother = wav.DOG(m=1) elif wavelet == 'Morlet': self.mother = wav.Morlet() else: print('Not a valid wavelet using Mexican') self.mother = wav.Mexican_hat() self.freq = frequency self.scale = 1. / self.mother.flambda() / self.freq # compute the continuous wavelet transform wt, sc, freqs, coi, fft, fftfreqs = wav.cwt(self.sig, self.dt, 0.25, self.scale, 0, self.mother) wt = np.real(np.squeeze(wt)) wtOr = wt.copy() # normalization wt = (wt - wt.mean()) / wt.std() self.lim = np.squeeze(np.abs(wt**2) / np.mean(wt**2)) flatness = self.flatness newflat = flatness threshold = 20. while newflat >= 3.05 and threshold > 0: threshold -= 0.2 d_ev = (self.lim > threshold) count = np.count_nonzero(d_ev) if 0 < count < self.lim.size: newflat = np.mean(wt[~d_ev] ** 4) / \ np.mean(wt[~d_ev] ** 2) ** 2 # now we have identified the threshold # we need to find the maximum above the treshold maxima = np.zeros(self.sig.size) allmax = np.zeros(self.sig.size) allmax[(self.lim > threshold)] = 1 imin = 0 for i in range(maxima.size - 1): i += 1 if self.lim[i] >= threshold > self.lim[i - 1]: imin = i if self.lim[i] < threshold <= self.lim[i - 1]: imax = i - 1 if imax == imin: d = 0 else: d = self.lim[imin:imax].argmax() maxima[imin + d] = 1 if peaks: ddPeak = ((maxima == 1) & (wtOr > 0)) maxima[~ddPeak] = 0 if valleys: ddPeak = ((maxima == 1) & (wtOr < 0)) maxima[~ddPeak] = 0 return maxima, allmax