'Matlab wrapToPi and python np.unwrap

I am trying to port my code from Matlab to Python. Most of it seems to work except Matlab's function

wrapToPi

I am using numpy's unwrap function

np.unwrap

to mimic wrapToPi but it doesn't seem to work. On Matlab page, it says that

lambdaWrapped = wrapToPi(lambda) wraps angles in lambda, in radians, to the interval [−pi pi]. pi maps to pi and −pi maps to −pi. (In general, odd, positive multiples of pi map to pi and odd, negative multiples of pi map to −pi.)

How is wrapToPi different from np.unwrap?



Solution 1:[1]

Octave's mapping addon has this code:

function xwrap = wrapToPi(x)

  xwrap = rem (x, 2*pi);
  idx = find (abs (xwrap) > pi);
  xwrap(idx) -= 2*pi * sign (xwrap(idx));

endfunction

unwrap in numpy and Octave (and presumably MATLAB) is something entirely different.

>> x=linspace(-2*pi, 2*pi, 10)
x =
 Columns 1 through 8:
  -6.28319  -4.88692  -3.49066  -2.09440  -0.69813   0.69813   2.09440   3.49066
 Columns 9 and 10:
   4.88692   6.28319
>> wrapToPi(x)
ans =
 Columns 1 through 8:
   0.00000   1.39626   2.79253  -2.09440  -0.69813   0.69813   2.09440  -2.79253
 Columns 9 and 10:
  -1.39626   0.00000

In numpy I can replicate this with:

In [274]: x = np.linspace(-2*np.pi, 2*np.pi, 10)
In [275]: x
Out[275]: 
array([-6.28318531, -4.88692191, -3.4906585 , -2.0943951 , -0.6981317 ,
        0.6981317 ,  2.0943951 ,  3.4906585 ,  4.88692191,  6.28318531])
In [276]: xwrap=np.remainder(x, 2*np.pi)
In [277]: mask = np.abs(xwrap)>np.pi
In [278]: xwrap[mask] -= 2*np.pi * np.sign(xwrap[mask])
In [279]: xwrap
Out[279]: 
array([ 0.       ,  1.3962634,  2.7925268, -2.0943951, -0.6981317,
        0.6981317,  2.0943951, -2.7925268, -1.3962634,  0.       ])

Solution 2:[2]

Based on hpaulj's answer, here we have a function which has exactly the same performance as Matlab. Just make sure your input is a numpy array

def wrapToPi(x):
    xwrap = np.remainder(x, 2 * np.pi)
    mask = np.abs(xwrap) > np.pi
    xwrap[mask] -= 2 * np.pi * np.sign(xwrap[mask])
    mask1 = x < 0
    mask2 = np.remainder(x, np.pi) == 0
    mask3 = np.remainder(x, 2 * np.pi) != 0
    xwrap[mask1 & mask2 & mask3] -= 2 * np.pi
    return xwrap

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Eric Aya