View Raw SPL
/*****************************************************************************
*                                                                            *
*   XTOIDX.SPL  Copyright (C) 2003-2010 DSP Development Corporation          *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Converts an x value to an index                             *
*                                                                            *
*   Revisions:   30 Jan 2003  RRR  Creation                                  *
*                19 Aug 2008  RRR  optional limit argument                   *
*                 2 Dec 2010  RRR  return scalar for scalar input            *
*                                                                            *
*****************************************************************************/

#include 


#if @HELP_XTOIDX

    XTOIDX

    Purpose: Converts X values of a series to index values.

    Syntax:  XTOIDX(series, x, limit)

             series    - input series

                  x    - A real or series of reals. The x values
                         to convert to indices

              limit    - Optional integer, limit result to existing
                         indices range.

                           0: do not limit output
                           1: limit output to existing indices (default)

    Returns: A real or series.

    Example:
             W1: 1..0.1..10
             W2: xtoidx(W1, 1..0.1..1.5)

             W2 contains the series {1, 2, 3, 4, 5}, the first 5
             index values of W1.

    Example:
             W1: 1..0.1..10
             W2: xtoidx(W1, 8..20)
             W3: xtoidx(W1, 8..20, 0)

             The values in W2 range from 71 to 91. Because some x values
             correspond to a indices larger than the length of W1, the
             result is limited to the length of W1. The resulting indices
             in W3 are not limited to the indices of W1 and range
             from 71 to 191.

    Remarks:
             For XY or XYZ series, the indices are looked up and the
             closest matches are returned.

             For interval series, the indices are computed as follows:

                 idx = 1 + int((x - xoffset(s)) / deltax(s) + 0.5);

             If LIMIT is set to 0, XTOIDX can return index value outside
             the range of the input series.

    See Also:
             Idx
             Idxtox
             Xvals

#endif


/* convert x value to index */
xtoidx(s, x, limit)
{
        local idx, ptype, isnum;

        if (argc < 3)
        {
                if (argc < 2)
                {
                        if (argc < 1) error("xtoindex - input series and X value required");

                        /* assume sole input is x value */
                        x = s;

                        /* reference current series */
                        s = refseries();
                }
                
                limit = 1;
        }

        /* check if scalar */
        isnum = isscalar(x);

        if (isxy(s) || isxyz(s))
        {
                idx = xtoidx_lookup(s, x, limit);
        }
        else if (numcols(s) > 1)
        {
                ptype = getplottype(s);

                if (itemtype(s) == 2 && ptype >= 1 && ptype <= 5)
                {
                        /* waterfall, contour, density, Z surface, image */
                        idx = xtoidx_interval(s, x, limit);
                }
                else
                {
                        /* multi-column series */
                        idx = xtoidx_interval_iterate(s, x, limit);
                }
        }
        else
        {
                /* interval series */
                idx = xtoidx_interval(s, x, limit);
        }

        /* convert back to scalar if necessary */
        if (isnum)
        {
                idx = castint(idx);
        }

        return(idx);
}


/* xy or xyz series */
ITERATE xtoidx_lookup(s, x, limit)
{
        local sz, leb, sx, gx, idx, start;

        /* try to lookup indices */
        sx  = xvals(s);
        len = length(s);

        if (len < length(sx))
        {
                sx = extract(sx, 1, len);
        }

        /* get indices of sorted x values */
        (sx, gx) = sort(sx, 1);

        /* lookup indices from sorted xvalues */
        idx = round(yvals({xylookup(sx, 1..len, x, "linear", 1)}));

        /* start index - usually 1 */
        start = castint(getconf("SPL_START_INDEX"));

        /* limit to gx size */
        idx = clip({idx}, start, length(gx));

        /* convert to original indices */
        idx = gx[idx];

        if (limit)
        {
                /* clip out of range values */
                idx = clip({idx}, start, length(s));
        }

        return(idx);
}


/* interval series */
xtoidx_interval(s, x, limit)
{
        local start, scale, idx;

        /* start index - usually 1 */
        start = castint(getconf("SPL_START_INDEX"));

        /* unit scale factor (mS, MHz, etc.) */
        scale = gethunitsscale(s);

        /* interval series - use direct computation */
        idx = int(((x - xoffset(s)) * scale) / deltax(s) + 0.5) + start;

        if (limit)
        {
                /* clip out of range values */
                idx = clip({idx}, start, length(s));
        }

        return(idx);
}


/* multi-column interval series */
ITERATE xtoidx_interval_iterate(s, x, limit)
{
        local idx;

        idx = xtoidx_interval(s, x, limit);
        
        return(idx);
}