diff utils/acorr.py @ 0:26838b1f560f

initial commit of a segmenter project
author mi tian
date Thu, 02 Apr 2015 18:09:27 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/acorr.py	Thu Apr 02 18:09:27 2015 +0100
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+acorr.py
+
+This function provides similar fuctionality to Matlab's xcorr() but for computing autocorrelation only.
+
+It gives equivalent results given the following Matlab test script:
+
+%==== MATLAB ====
+a=[1,2,3,4,5,1,2,3,4,5,2,3,4,5,6,1,2,3,4,5];
+[xcr,lag] = xcorr(a,a,20,'unbiased');
+disp(xcr);
+plot(lag,xcr);
+%==== MATLAB ====
+
+Created by George Fazekas on 2014-02-26.
+Copyright (c) 2014 . All rights reserved.
+"""
+
+import sys,os
+import numpy as np
+from scipy.fftpack import fft, ifft
+
+class ACORR(object):
+
+	def nextpow2(self, n):
+		'''Return the next power of 2 such as 2^p >= n'''
+		if np.any(n < 0):
+			raise ValueError("n should be > 0")
+		if np.isscalar(n):
+			f, p = np.frexp(n)
+			if f == 0.5:
+				return p-1
+			elif np.isfinite(f):
+				return p
+			else:
+				return f
+		else:
+			f, p = np.frexp(n)
+			res = f
+			bet = np.isfinite(f)
+			exa = (f == 0.5)
+			res[bet] = p[bet]
+			res[exa] = p[exa] - 1
+			return res
+
+	def acorr_ifft_fft(self, x, nfft, lag, onesided=False, scale='none'):
+		'''Compute the actual autocorrelation via IFFT/FFT	'''
+		ra = np.real(ifft(np.abs(fft(x, n=nfft) ** 2)))
+		if onesided:
+			b = ra[..., :lag]
+		else:
+			b = np.concatenate([ra[..., nfft-lag+1:nfft], ra[..., :lag]], axis=-1)
+		#print b, ra[..., 0][..., np.newaxis], b / ra[..., 0][..., np.newaxis]
+		if scale == 'coeff':
+			return b / ra[..., 0][..., np.newaxis]
+		elif scale == 'unbiased':
+			'''scale = len(x)-abs(lags)'''
+			lags = np.array(range(-lag+1,lag))
+			# print lags,len(x)
+			scale = len(x) - abs(lags)
+			scale[scale<=0] = 1.0
+			# print scale
+			return b/scale
+		else:
+			return b
+
+	def acorr(self, x, axis=-1, onesided=False, lag=None, scale='none'):
+		'''Compute autocorrelation of x along given axis.
+			x : array-like
+				signal to correlate.
+			axis : int
+				axis along which autocorrelation is computed.
+			onesided: bool, optional
+				if True, only returns the right side of the autocorrelation.
+			scale: {'none', 'coeff'} scaling mode. 
+			If 'coeff', the correlation is normalised such as the 0-lag is equal to 1.
+			if 'unbiased' the correlation is normalised using len(x) -	abs(lags) '''
+
+		if not scale in ['none', 'coeff','unbiased']:
+			raise ValueError("scale mode %s not understood" % scale)
+		if not lag :
+			lag = x.shape[axis]
+		lag += 1
+		nfft = 2 ** self.nextpow2(2 * lag - 1)
+		lags = np.array(range(-lag+1, lag))
+		if axis != -1:
+			x = np.swapaxes(x, -1, axis)
+		a = self.acorr_ifft_fft(x, nfft, lag, onesided, scale)
+		if axis != -1:
+			a = np.swapaxes(a, -1, axis)
+		return a,lags
+