View Raw SPL
/*****************************************************************************
*                                                                            *
*   IFFTSHIFT.SPL Copyright (C) 2013 DSP Development Corporation             *
*                           All Rights Reserved                              *
*                                                                            *
*   Author:       Randy Race                                                 *
*                                                                            *
*   Synopsis:     Unshifts FFT so zero frequency is the first point          *
*                                                                            *
*   Revisions:    27 Nov 2013  RRR  Creation - from fftshift.spl             *
*                                                                            *
*****************************************************************************/


#if @HELP_IFFTSHIFT

    IFFTSHIFT

    Purpose: Unshifts a 1D or 2D FFT so the 0 frequency is the first point

    Syntax:  IFFTSHIFT(ser, dim)

               ser - A series or array.

               dim - Optional. An integer, the shift dimension.

                      -1: Shift rows and columns for arrays (default).
                       0: Do not shift quadrants for arrays (same as 1).
                       1: Shift rows only.
                       2: Shift columns only.

    Returns: A series or array.

    Example:
             W1: {1, 2, 3, 2, 1}
             W2: fft(W1)
             W3: fftshift(W2)
             W3: ifftshift(W3)

             The zero frequency (i.e. DC) value of W2 is the first point.
             The zero frequency of W3 is the 3rd point and appears in the
             middle of the resulting graph. W4 undoes the shift of W3
             to returns the same data as in W2.

    Example:
             W1: ravel(1..25, 5)
             W2: fftshift(W1)
             W3: fftshift(W1, 1)
             W4: fftshift(W1, 2)
             W5: ifftshift(W2)
             W6: ifftshift(W3, 1)
             W7: ifftshift(W4, 2)

             W1 == {{1,  6, 11, 16, 21},
                    {2,  7, 12, 17, 22},
                    {3,  8, 13, 18, 23},
                    {4,  9, 14, 19, 24},
                    {5, 10, 15, 20, 25}}

             W2 == {{19, 24,  4,  9, 14},
                    {20, 25,  5, 10, 15},
                    {16, 21,  1,  6, 11},
                    {17, 22,  2,  7, 12},
                    {18, 23,  3,  8, 13}}

             W3 == {{4,   9, 14, 19, 24},
                    {5,  10, 15, 20, 25},
                    {1,   6, 11, 16, 21},
                    {2,   7, 12, 17, 22},
                    {3,   8, 13, 18, 23}}

             W4 == {{16, 21,  1,  6, 11},
                    {17, 22,  2,  7, 12},
                    {18, 23,  3,  8, 13},
                    {19, 24,  4,  9, 14},
                    {20, 25,  5, 10, 15}}

            W5 == W6 == W7 == {{1,  6, 11, 16, 21},
                               {2,  7, 12, 17, 22},
                               {3,  8, 13, 18, 23},
                               {4,  9, 14, 19, 24},
                               {5, 10, 15, 20, 25}}


             W1 contains a 5x5 array.
             
             W2 shifts the rows and columns of the array. The result is
             the upper left and lower right quadrants are swapped and
             the upper right and lower left quadrands are swapped.

             W3 shifts the rows of the array only.

             W4 shifts the columns of the array only.

             W5, W6, and W7 undo the shifts and return the original array.

    Remarks:
             IFFTSHIFT undoes the shift produced by FFTSHIFT. For a series
             or array with an odd number of elements, IFFTSHIFT(FFTSHIFT(s))
             returns the original but FFTSHIFT(FFTSHIFT(s)) does not.

             By default, IFFTSHIFT flips the quadrants of an array. Set
             dim to 0 or 1 to shift rows only and not shift the quadrants.

    See Also:
             Fft
             Fft2
             Fftshift

#endif


/* undo the shift produced by fftshift */
ifftshift(s, dim)
{
        local rmid, rodd, cmid, codd, t;
        local nr, nc, r1, r2, c1, c2, bufsize;

        if (argc < 2)
        {
                if (argc < 1) error(sprintf("%s - input series required", __FUNC__));

                dim = -1;
        }

        /* numrows and numcols */
        (nr, nc) = size(s);

        /* get row midpoints */
        rmid = floor(nr / 2);
        rodd = nr % 2;

        if (nc > 1 && (dim == 2 || dim < 0))
        {
                /* array - get col midpoints */
                cmid = floor(nc / 2 + 1);
                codd = (nc % 2);

                /* array indices */
                if (dim == 2)
                {
                        r1 = 1..rmid;
                        r2 = (rmid + 1)..nr;
                }
                else
                {
                        r1 = (rmid + 1)..nr;
                        r2 = 1..rmid;
                }

                c1 = cmid..nc;
                c2 = 1..(cmid - 1);

                /* flip rows and columns in one operation */
                t = {ravel(s[r1, c1], s[r1, c2]), ravel(s[r2, c1], s[r2, c2])};

                /* fixup offset for even or odd columns */
                setdeltay(t, deltay(s));
                setyoffset(t, yoffset(s) + ((nc + codd) / 2) * deltay(t));
        }
        else if (dim == 1 || dim <= 0)
        {
                /* series - flip each half of all the rows */
                t = concat(extract(s, rmid + 1, -1), extract(s, 1, rmid));
        }
        else
        {
                t = s;
        }

        /* fixup offset for even or odd rows */
        if (dim <= 2)
        {
                setdeltax(t, deltax(s));
                setxoffset(t, xoffset(s) + ((nr + rodd) / 2) * deltax(t));
        }

        return(t);
}