def GetHFF(x,y,delta): """Compute and display the HF parameters of a signal on its single sided amplitude spectrum. Parameters: x - time vector y - signal delta - smoothing parameter Return: g - vector of the gap in frequency between the trend and the oscillations d - relative amplitude of the oscillations """ # Fourier Transform frequency sampling dt=x[int(len(x)/2)]-x[int(len(x)/2-1)] Fs=1/(dt) (P1,f)=get_fft(y,Fs) # Smoothing the Fourier transform (fb,En)=EnergyBand(f,P1,delta,'Roll') #(fb,En)=(f,P1) # HFF parameters detection (nu_star,unused,n_1_star,n_2_star,n_3_star)=HFF_Parameters(fb,np.power(En,2)) d=nu_star # relative amplitude of the HFF g=n_3_star-n_2_star # frequency interval between HFF and trend # plot of the smoothed Fourier transfor and the HFF parameters sig=En fig, ax = getFig(1, 'Amplitude spectrum and HFF parameters') ax.plot(fb,sig) ax.plot(fb[n_1_star],sig[n_1_star],'rD') ax.plot(fb[n_2_star],sig[n_2_star],'rD') ax.plot(fb[n_3_star],sig[n_3_star],'bD') ax.set_yscale('log') ax.set_xlabel('Freq (Hz)') ax.set_ylabel('|Y(freq)|') return(g,d)
def SigOsc(x,ampl,sigma): """Return an oscillating signal with decreasing trend. Parameters: x - time vector ampl - amplitude of the oscillations Return: y - Oscillating signal """ y1=1/np.sqrt((x+1)) t1=np.zeros((int(len(x)/4),)) t2=x[int(len(x)/4):int(3*len(x)/4)] t3=np.hstack((t1,t2)) t=np.hstack((t3,t1)) y2=ampl*np.sin(2*np.pi*t/6) y=y1+y2+5 sig=y+np.random.normal(0,sigma,len(t)) fig, ax = getFig(2, 'Test signal') ax[0].plot(x,y) ax[0].set_xlabel('time axis') ax[0].set_ylabel('real signal') ax[1].plot(x,sig) ax[1].set_xlabel('time axis') ax[1].set_ylabel('noisy signal') fig.tight_layout() return(sig)
def l1(signal, regularizer): """ Fits the l1 trend on top of the `signal` with a particular `regularizer` Parameters: signal(np.ndarray) - Original Signal that we want to fit l1 trend regularizer(float) - Regularizer which provides a balance between smoothing of a signal and truthfulness of signal Returns: values(np.array) - l1 Trend of a signal that is extracted from the signal """ if not isinstance(signal, np.ndarray): raise TypeError("Signal Needs to be a numpy array") m = float(signal.min()) M = float(signal.max()) difference = M - m if not difference: # If signal is constant difference = 1 t = (signal - m) / difference values = matrix(t) values = _l1(values, regularizer) values = values * difference + m values = np.asarray(values).squeeze() fig, ax = getFig(1,'Trend Estimation') x=np.linspace(0,1,len(signal)) ax.plot(x, signal, label='Signal') ax.plot(x, values, label='Trend') fig.legend() return values
def SanityCheckFunct(time,sigma,ca,cf): """ Build an oscillating signal with a trend like the Lennard John potential Parameters: time - discretisation x-axis sigma - standard deviation of the noise ca - amplitude of the oscillations cf - frenquency of the oscillations in 3600*Hz Returns: t - time sc - oscillating signal """ # Parameters for the trend of the signal c1=0.4 c2=2 c3=4 c4=5 n=len(time) # Trend construction t_temp1=time[int(n/8):] trend2 = c1*(np.power(c2*np.true_divide(1,t_temp1),8) \ - c3*np.power(c2*np.true_divide(1,t_temp1),4))+c4 t_temp2=time[:int(n/8)] a=time[int(n/8-10)] b=time[int(n/8)] f_a=c1*((c2/a)**8 - c3*(c2/a)**3)+c4 f_b=c1*((c2/b)**8 - c3*(c2/b)**3)+c4 trend1=((f_b-f_a)/b)*t_temp2+f_a; trend=np.concatenate((trend1,trend2)) # oscillations construction t2=np.concatenate((np.ones(int(n/8-1))*time[int(n/8)],time[int(n/8):int(2*n/8)+1],\ np.ones(len(time)-int(2*n/8))*time[int(n/8)])); osc=ca*np.multiply(np.multiply((t2-time[int(int(n/8))]),(time[int(2*n/8)]-t2)),np.sin(t2*2*np.pi*cf))\ *(4/(time[int(2*n/8)]-time[int(n/8)])**2) # Noise construction Gaussian distributed noise=np.random.normal(0,sigma,len(time)) sc=trend+osc+noise fig, ax = getFig(2, 'Test signal') ax[0].plot(time,trend+osc) ax[0].set_xlabel('time axis') ax[0].set_ylabel('real signal') ax[1].plot(time,sc) ax[1].set_xlabel('time axis') ax[1].set_ylabel('noisy signal') fig.tight_layout() return(sc)
def RejZoneAlpha(g,d,gmu,dmu,alpha): """Compute for each point of the cloud of the points {(g,d)} the proportion of points in the North-East quarter of the plane. Parameters: g - vector of the gap in frequency between the trend and the oscillations (null hypothesis) d - vector of the relative amplitudes of the oscillations (null hypothesis) gmu - gap in frequency between the trend and the oscillations (signal subject to the test) dmu - relative amplitude of the oscillations (signal subject to the test) alpha - level of the test (number of false negative acceptable in %) Returns: c_alpha - set of threshold for the gap in frequency of level alpha nu_alpha - set of threshold for the relative amplitude of level alpha g_mesh - x-axis for the grid of the mesh (frequency gap) d_mesh - y-axis for the grid of the mesh (relative amplitude) mesh - necessary grid to compute threshold of any level alpha """ n=len(g) K=int(alpha*n) g_mesh=np.unique(g) # ordered vector of gap in frequency d_mesh=np.unique(d) # ordered vector of amplitude x=np.vstack((g,d)) x=np.transpose(x) mesh=np.zeros(n) for i in range(n): xtest=np.concatenate((np.ones((n,1))*g[i],np.ones((n,1))*d[i]),axis=1) # vector for the 2D order relation xtilde=(x>=xtest).astype(int) # 2D order relation out=xtilde[np.all(xtilde!=0,axis=1)] # get rid of rows with 0 in it mesh[i]=len(out[:,1]) # number of couple in the north east corner of the plane index_alpha=np.where(abs(mesh-K)<(1/n)) c_alpha=g[index_alpha] nu_alpha=d[index_alpha] fig, ax = getFig(1,'Cloud of points and HFF parameters') ax.scatter(g,d, c='b', s=10) ax.set_xlabel('Frequency gap g') ax.set_ylabel('Relative Amplitude d') ax.scatter(gmu, dmu, c='r', s=40) ax.set_ylim([min(np.hstack((d,dmu))),max(np.hstack((d,dmu)))]) return(c_alpha,nu_alpha,g_mesh,d_mesh,mesh)