[SciPy-user] phase wrapping algorithm

Bryan Cole bryan at cole.uklinux.net
Tue Oct 10 15:55:49 CDT 2006

I do this quite a lot in the context of FFTs.

def unwrap(thetaArray):
    """takes an array of theta values in degrees
    returns the data in unwrapped form"""
    diff = zeros_like(thetaArray)
    diff[1:] = thetaArray[1:] - thetaArray[:-1]
    upSteps = diff > 180
    downSteps = diff < -180
    shift = cumsum(upSteps) - cumsum(downSteps)
    return thetaArray - 360*shift

Obviously, a Weave version will be a lot faster, but this is at least 
fully vectorised, so it's not bad.


On Tue, 2006-10-10 at 12:32 -0500, Ryan Krauss wrote:
> I am rethinking an algorithm for unwrapping phase data from arctan2
> for a vector of complex numbers (coming from lti models of feedback
> control systems).  I had written something a while ago using weave,
> but my old code causes seg faults with a recent scipy update.  So, I
> am rethinking the algorithm.
> The problem occurs when either because of noise or just the definition
> of the inverse tangent, their are discontinuities in the phase (which
> is coming from arctan2(imag(vector), real(vector)).  For example, in
> the attached plot and data file, there is a point where the phase
> passes through -180 degrees.  arctan2 jumps to returning +180, +175
> etc, when it makes a pretty plot and makes more sense to me to convert
> +175 to -185.  What I had done previously is write a for loop that
> compares the current value of the phase to the value at the previous
> index (i.e. if phase[i]-phase[-1]>300 or if phase[i]-phase[i-1]<-300)
> to find the discontinuities.  Is there a cleaner/faster way to do
> this?  (I had done it in weave and will probably now do it in f2py for
> comparison on speeds).  I have attached/included a first attempt at an
> algorithm that is more vectorized.  But is there a fast, easy way to
> compare a vector to the same vector shift one element up or down?
> Right now I am doing this
> phase2=r_[phase[0:1],phase[0:-1]]
> to shift the vector (and reuse the first element so there isn't a jump
> from phase[-1] to phase[0] which may legitimately be far apart).
> Has anyone else already done this?  Are there obvious bottlenecks with
> the algorithm?
> Thanks for your thoughts,
> Ryan
> =====================================
> from scipy import arange, io, r_
> from pylab import show, figure, subplot, clf, cla, semilogx, xlabel,
> ylabel, legend, xlim
> import copy
> data=io.read_array('phase_data.txt')
> f=data[:,0]
> phase=data[:,1]
> figure(1)
> clf()
> startphase=copy.copy(phase)
> semilogx(f,startphase)
> keepgoing=1
> inds=arange(0,len(phase))
> while keepgoing:
>     phase2=r_[phase[0:1],phase[0:-1]]#artificially repeat the first element
>     diff=phase-phase2
>     jumps=inds[abs(diff)>250]
>     keepgoing=jumps.any()
>     if not keepgoing:
>         break
>     ind=jumps.min()
>     if diff[ind]>0:
>         phase[ind:]-=360
>     else:
>         phase[ind:]+=360
> semilogx(f,phase,'r--')
> legend(['Before unwrapping','after unwrapping'],2)
> xlim([1,30])
> show()
> _______________________________________________
> SciPy-user mailing list
> SciPy-user at scipy.org
> http://projects.scipy.org/mailman/listinfo/scipy-user

More information about the SciPy-user mailing list