@@ -426,81 +426,105 @@ def zero_crossings(y, x=None, direction=None, bouncingZero=False):
426426# --------------------------------------------------------------------------------}
427427# --- Correlation
428428# --------------------------------------------------------------------------------{
429- def autoCorrCoeff (x , nMax = None ):
430- if nMax is None :
431- nMax = len (x )
432- return np .array ([1 ]+ [np .corrcoef (x [:- i ], x [i :])[0 ,1 ] for i in range (1 , nMax )])
433-
434- def correlation (x , nMax = 80 , dt = 1 , method = 'numpy' ):
429+ def autoCorrCoeff (x , nMax = None , dt = 1 , method = 'corrcoef' ):
435430 """
436431 Compute auto correlation of a signal
432+ - nMax: number of values to return
437433 """
438- nvec = np .arange (0 ,nMax )
434+ x = x .copy () - np .mean (x )
435+ var = np .var (x )
436+ n = len (x )
437+ if nMax is None :
438+ nMax = n
439+ rvec = np .arange (0 ,nMax )
439440 if method == 'manual' :
440- sigma2 = np .var (x )
441- R = np .zeros (nMax )
442- R [0 ] = 1
443- for i ,nDelay in enumerate (nvec [1 :]):
444- R [i + 1 ] = np .mean ( x [0 :- nDelay ] * x [nDelay :] ) / sigma2
445- #R[i+1] = np.corrcoef(x[:-nDelay], x[nDelay:])[0,1]
446-
447- elif method == 'numpy' :
448- R = autoCorrCoeff (x , nMax = nMax )
441+ rho = np .zeros (nMax )
442+ rho [0 ] = 1
443+ for i ,nDelay in enumerate (rvec [1 :]):
444+ rho [i + 1 ] = np .mean ( x [0 :- nDelay ] * x [nDelay :] ) / var
445+
446+ elif method == 'manual-roll' :
447+ rho = np .zeros (len (rvec ))
448+ for i ,r in enumerate (rvec ):
449+ shifted_x = np .roll (x , int (r )) #Shift x by tau
450+ rho [i ] = np .mean (x * shifted_x ) / var
451+
452+ elif method == 'corrcoef' :
453+ rho = np .array ([1 ]+ [np .corrcoef (x [:- i ], x [i :])[0 ,1 ] for i in range (1 , nMax )])
454+
455+ elif method == 'correlate' :
456+ rho = np .correlate (x , x , mode = 'full' )[- n :] / (var * n )
457+ rho = rho [:nMax ]
449458 else :
450- raise NotImplementedError ()
459+ raise NotImplementedError (method )
460+
461+ tau = rvec * dt
462+ return rho , tau
451463
452- tau = nvec * dt
453- return R , tau
464+ def correlation (* args , ** kwargs ):
465+ print ('[WARN] welib.tools.signal_analysis.correlation will be deprecated use autoCorrCoeff' )
466+ return autoCorrCoeff (* args , ** kwargs )
454467# Auto-correlation comes in two versions: statistical and convolution. They both do the same, except for a little detail: The statistical version is normalized to be on the interval [-1,1]. Here is an example of how you do the statistical one:
455468#
456469#
457470# def autocorr(x):
458471# result = numpy.correlate(x, x, mode='full')
459472# return result[result.size/2:]
460473
461-
462- def xCorrCoeff (x , y , dt = None , mode = 'same' , return_lags = False , method = 'numpy' ):
463- """
464- Compute and plot the cross-correlation coefficient between two signals.
465-
466- Parameters:
467- - x: array-like, first signal values
468- - y: array-like, second signal values
474+
475+ def xCorrCoeff (x1 , x2 , t = None , nMax = None , method = 'manual' ):
476+ """
477+ Compute cross-correlation coefficient between two signals.
469478 """
470- from scipy .signal import correlate
471- # Compute cross-correlation
472-
473- sigma1 = np .std (x )
474- sigma2 = np .std (y )
475- N = len (x )// 2
476- N3 = len (x )// 3
477- if method == 'manual' :
478- nMax = len (x )
479- R = np .zeros (nMax )
480- R [0 ] = 1
481- nvec = np .arange (0 ,nMax )
482- for i ,nDelay in enumerate (nvec [1 :]):
483- R [i + 1 ] = np .mean ( x [0 :- nDelay ] * y [nDelay :] ) / (sigma1 * sigma2 )
484- #R[i+1] = np.corrcoef(x[:-nDelay], x[nDelay:])[0,1]
485- cross_corr = R
479+ x1 = x1 .copy ()- np .mean (x1 )
480+ x2 = x2 .copy ()- np .mean (x2 )
481+ sigma1 = np .std (x1 )
482+ sigma2 = np .std (x2 )
483+ # Only if x1 and x2 have the same length for now
484+ N1 = min (len (x1 ), len (x2 ))
485+ if nMax is None :
486+ nMax = len (x1 )
487+ if t is None :
488+ t = np .array (range (N1 ))
489+ if method == 'subset-tauPos' :
490+ # Only if x1 and x2 have the same length
491+ rho = np .zeros (nMax )
492+ rvec = np .arange (0 ,nMax )
493+ for i ,r in enumerate (rvec ):
494+ rho [i ] = np .mean ( x1 [:N1 - r ] * x2 [r :] ) / (sigma1 * sigma2 )
495+ elif method == 'manual' :
496+ rvec = np .array (range (- nMax + 1 ,nMax ))
497+ rho = np .zeros (len (rvec ))
498+ # TODO two for loops for pos and neg..
499+ for i ,r in enumerate (rvec ):
500+ if r >= 0 :
501+ t11 , x11 = t [0 :N1 - r ], x1 [0 :N1 - r ]
502+ t22 , x22 = t [r :] , x2 [r :]
503+ else :
504+ r = abs (r )
505+ t22 , x22 = t [0 :N1 - r ], x2 [0 :N1 - r ]
506+ t11 , x11 = t [r :] , x1 [r :]
507+ rho [i ] = np .mean (x11 * x22 ) / (sigma1 * sigma2 )
486508 else :
509+ raise NotImplementedError (method )
487510 cross_corr = correlate (x , y , mode = mode )/ min (len (x ), len (y )) / (sigma1 * sigma2 )
488511 if mode == 'same' :
489512 cross_corr = np .concatenate ( [ cross_corr [N :], cross_corr [:N ] ] )
490513 cross_corr [N3 :2 * N3 ]= 0
491-
492- if return_lags :
493- # --- Compute lags
494514 if mode == 'full' :
495515 lags = np .arange (- len (x ) + 1 , len (x )) * dt
496516 elif mode == 'same' :
497517 lags = (np .arange (len (x )) - N ) * dt
498518 lags = np .concatenate ( [ lags [N :], lags [:N ] ] )
499519 else :
500520 raise NotImplementedError (mode )
501- return cross_corr , lags
502- else :
503- return cross_corr
521+
522+
523+ tau = rvec * (t [1 ]- t [0 ])
524+ return rho , tau
525+
526+
527+
504528
505529
506530def correlated_signal (coeff , n = 1000 , seed = None ):
@@ -522,63 +546,6 @@ def correlated_signal(coeff, n=1000, seed=None):
522546 return x
523547
524548
525- # --------------------------------------------------------------------------------}
526- # ---
527- # --------------------------------------------------------------------------------{
528- # def crosscorr_2(ts, iy0=None, iz0=None):
529- # """ Cross correlation along y
530- # If no index is provided, computed at mid box
531- # """
532- # y = ts['y']
533- # if iy0 is None:
534- # iy0,iz0 = ts.iMid
535- # u, v, w = ts._longiline(iy0=iy0, iz0=iz0, removeMean=True)
536- # rho_uu_y=np.zeros(len(y))
537- # for iy,_ in enumerate(y):
538- # ud, vd, wd = ts._longiline(iy0=iy, iz0=iz0, removeMean=True)
539- # rho_uu_y[iy] = np.mean(u*ud)/(np.std(u)*np.std(ud))
540- # return y, rho_uu_y
541- #
542- # def csd_longi(ts, iy0=None, iz0=None):
543- # """ Compute cross spectral density
544- # If no index is provided, computed at mid box
545- # """
546- # import scipy.signal as sig
547- # u, v, w = ts._longiline(iy0=iy0, iz0=iz0, removeMean=True)
548- # t = ts['t']
549- # dt = t[1]-t[0]
550- # fs = 1/dt
551- # fc, chi_uu = sig.csd(u, u, fs=fs, scaling='density') #nperseg=4096, noverlap=2048, detrend='constant')
552- # fc, chi_vv = sig.csd(v, v, fs=fs, scaling='density') #nperseg=4096, noverlap=2048, detrend='constant')
553- # fc, chi_ww = sig.csd(w, w, fs=fs, scaling='density') #nperseg=4096, noverlap=2048, detrend='constant')
554- # return fc, chi_uu, chi_vv, chi_ww
555- #
556- # def coherence_longi(ts, iy0=None, iz0=None):
557- # """ Coherence on a longitudinal line for different delta y and delta z
558- # compared to a given point with index iy0,iz0
559- # """
560- # try:
561- # import scipy.signal as sig
562- # except:
563- # import pydatview.tools.spectral as sig
564- # if iy0 is None:
565- # iy0,iz0 = ts.iMid
566- # u, v, w = ts._longiline(iy0=iy0, iz0=iz0, removeMean=True)
567- # y = ts['y']
568- # z = ts['z']
569- # diy=1
570- # dy=y[iy]-y[iy0]
571- # # TODO
572- # iy = iy0+diy
573- # ud, vd, wd = ts._longiline(iy0=iy, iz0=iz0, removeMean=True)
574- # fc, coh_uu_y1 = sig.coherence(u,ud, fs=fs)
575-
576-
577-
578-
579- # --------------------------------------------------------------------------------}
580- # ---
581- # --------------------------------------------------------------------------------{
582549def find_time_offset (t , f , g , outputAll = False ):
583550 """
584551 Find time offset between two signals (may be negative)
0 commit comments