Is there a similar numpy.unwrap function in julia? Thanks.

941 views
Skip to first unread message

Weichi Ding

unread,
Dec 16, 2013, 3:33:25 PM12/16/13
to julia...@googlegroups.com

Stefan Karpinski

unread,
Dec 16, 2013, 3:40:17 PM12/16/13
to Julia Users
Even reading the documentation, I have no idea what that function does. We do have degrees2radians and radians2degrees along with sinpi, cospi, and mod2pi.


On Mon, Dec 16, 2013 at 3:33 PM, Weichi Ding <weich...@gmail.com> wrote:


Weichi Ding

unread,
Dec 16, 2013, 3:52:14 PM12/16/13
to julia...@googlegroups.com
Thanks. it's "Unwrap by changing deltas between values to 2*pi complement."

Steven G. Johnson

unread,
Dec 16, 2013, 3:59:50 PM12/16/13
to julia...@googlegroups.com
Not that I know of, but it would be easy enough to write.

Something like:

function unwrap!(p)
    length(p) < 2 && return p
    for i = 2:length(p)
        d = p[i] - p[i-1]
        if abs(d) > pi
            p[i] -= floor((d+pi) / (2pi)) * 2pi
        end
    end
    return p
end

will I think mimic what the numpy source (https://github.com/numpy/numpy/blob/v1.8.0/numpy/lib/function_base.py#L1122), although the numpy source is much more complicated because it has to bend over backwards to avoid using loops.

Stefan Karpinski

unread,
Dec 16, 2013, 3:59:53 PM12/16/13
to Julia Users
Yes, I already read that, but it doesn't clarify the behavior for me even a little bit.

Stefan Karpinski

unread,
Dec 16, 2013, 4:02:05 PM12/16/13
to Julia Users
That's a fairly classic example of vectorized code gone wrong.

Weichi Ding

unread,
Dec 16, 2013, 4:03:25 PM12/16/13
to julia...@googlegroups.com
Thanks a lot, Stefan!

Patrick O'Leary

unread,
Dec 16, 2013, 4:41:32 PM12/16/13
to julia...@googlegroups.com
Perhaps the Mathworks documentation is clearer:

http://www.mathworks.com/help/matlab/ref/unwrap.html

Spencer Russell

unread,
Dec 16, 2013, 4:53:54 PM12/16/13
to julia...@googlegroups.com
I didn't find one when I needed it a couple weeks ago, so I wrote one. It takes a vector, whereas it would probably be nice to allow the user to give a matrix and then specify which direction to unwrap in. Also note that it uses the first value in the vector as the anchor point to unwrap all subsequent values towards.


Note that I'm by no means an experienced Julia coder and I'm not sure what's considered good idiomatic Julia code, e.g. I have an "inplace=false" argument and then add an unwrap!() alias that sets inplace to true.

If this seems like a useful utility function I can do a pull request into DSP.jl.

-s

Stefan Karpinski

unread,
Dec 16, 2013, 4:54:13 PM12/16/13
to Julia Users
Slightly better, but I'm just chalking this up to me being dense :-). Since both NumPy and Matlab have this function, perhaps we should as well. Seems like the kind of thing that's easy to do wrong.


On Mon, Dec 16, 2013 at 4:41 PM, Patrick O'Leary <patrick...@gmail.com> wrote:

Tobias Knopp

unread,
Dec 16, 2013, 5:14:20 PM12/16/13
to julia...@googlegroups.com
Phase unwrapping is required when you want to reconstruct a quantity t that covers a range larger than [-pi,pi) but you have given only measurements y = exp(2pi*im* t)
You make use of the fact that usually t is a smooth function.

It actually a quite common operation in signal processing.

Stefan Karpinski

unread,
Dec 16, 2013, 5:24:58 PM12/16/13
to Julia Users
Ah, ok. I think I get it now. When you see a discontinuity, you know the function wrapped around so you can reconstruct the continuous version. Thanks.

Patrick O'Leary

unread,
Dec 16, 2013, 6:38:28 PM12/16/13
to julia...@googlegroups.com
On Monday, December 16, 2013 4:14:20 PM UTC-6, Tobias Knopp wrote:
It actually a quite common operation in signal processing.

And it can also be useful when trying to understand attitude states expressed as Euler angles.

Steven G. Johnson

unread,
Dec 17, 2013, 8:55:51 PM12/17/13
to julia...@googlegroups.com, s...@mit.edu


On Monday, December 16, 2013 4:53:54 PM UTC-5, Spencer Russell wrote:
I didn't find one when I needed it a couple weeks ago, so I wrote one. It takes a vector, whereas it would probably be nice to allow the user to give a matrix and then specify which direction to unwrap in. Also note that it uses the first value in the vector as the anchor point to unwrap all subsequent values towards.


Note that I'm by no means an experienced Julia coder and I'm not sure what's considered good idiomatic Julia code, e.g. I have an "inplace=false" argument and then add an unwrap!() alias that sets inplace to true.

If this seems like a useful utility function I can do a pull request into DSP.jl.


It's more idiomatic to define an in-place version, and then make the out-of-place version by

    unwrap(x) = unwrap!(copy(x))

Also, note that you should be able to use truncated division rather than loops to add/subtract the correct multiple of 2pi, as in my snippet.

Steven G. Johnson

unread,
Dec 17, 2013, 8:58:38 PM12/17/13
to julia...@googlegroups.com, s...@mit.edu


On Tuesday, December 17, 2013 8:55:51 PM UTC-5, Steven G. Johnson wrote:
Also, note that you should be able to use truncated division rather than loops to add/subtract the correct multiple of 2pi, as in my snippet.

(The problem with loops is that I can easily imagine data for which the nested-loops version is O(n^2) or worse rather than O(n), simply by having the phase grow linearly or faster with n.)

Spencer Russell

unread,
Dec 17, 2013, 10:50:49 PM12/17/13
to julia...@googlegroups.com
Ah, thanks for the tip on the in-place/out-of-place idiom, and good point on the faster unwrap.

-s

Spencer Russell

unread,
Dec 18, 2013, 12:58:25 AM12/18/13
to julia...@googlegroups.com
I'm trying to adapt this to use to unwrap along arbitrary dimensions in an array and having a bit of trouble wrapping my head around how to manage it.

I can compute the phase difference between adjacent slices using slicedim, and computing the new phase value isn't hard, but i need to assign the result back to the array, basically treating slicedim as a view (which doesn't work). How should I do this?

Here's what I have so far (with the failing assignment into the slicedim):

function unwrap!(m::Array, dim::Integer=ndims(m))
    if size(m, dim) < 2
        return m
    end
    for i = 2:size(m, dim)
        d = slicedim(m, dim, i) - slicedim(m, dim, i-1)
        slicedim(m, dim, i) -= floor((d+pi) / (2pi)) * 2pi
    end
    return m
end

Steven G. Johnson

unread,
Dec 18, 2013, 8:03:34 AM12/18/13
to julia...@googlegroups.com, s...@mit.edu
For Array types, you can exploit the column-major order to do loop over any single dimension using at most 3 nested loops.  See e.g.:

https://github.com/stevengj/Hadamard.jl/blob/master/src/Hadamard.jl#L148-L162
Reply all
Reply to author
Forward
0 new messages