View Raw SPL
/*****************************************************************************
*                                                                            *
*   XYDTTAB.SPL  Copyright (C) 2015 DSP Development Corporation              *
*                               All Rights Reserved                          *
*                                                                            *
*   Author:      Randy Race                                                  *
*                                                                            *
*   Synopsis:    Creates a table of XY series from date, time and y data     *
*                                                                            *
*   Revisions:   20 Apr 2015  RRR  Creation                                  *
*                                                                            *
*****************************************************************************/

#if @HELP_XYDTTAB

    XYDTTAB

    Purpose: Creates a table of multiple XY series from date, time and Y series.

    Syntax:  XYDTTAB(data, date, time, collist, interval)

                  data - A table or series of y values.

                  date - Optional. A series or integer. A series of date
                         values or the column number in DATA containing
                         the date values. Defaults to the first column
                         in DATA.

                  time - Optional. A series or integer. A series of time
                         values or the column number in DATA containing the
                         time values. Defaults to the second column in
                         DATA.

               collist - Optional. A series or column number from DATA
                         to use as the Y values. Defaults to all the columns
                         of DATA except the date and time columns.

              interval - Optional. A real specifying the interpolation
                         interval. Defaults to 0, no interpolation, return
                         XY series.

    Returns: A table of one or more XY series.

    Example:
             W1: julstr(getdate)..julstr(getdate)+9;setvunits("Daily")
             W2: todstr(gettime)..todstr(gettime)+9;setvunits("Time")
             W3: randn(10, 3);setvunits("V", -1)
             W4: ravel(W1, W2, W3)
             W5: xydttab(w4)
             W6: getitem(W5, 2)

             W1 contains a series of 10 Julian dates starting from the
             current date.

             W2 contains a series of 10 time values starting from the
             current time.

             W3 contains 3 columns of random values where each column contains
             10 samples. The units for each column is set to "Volts".

             W4 combines W1, W2 and W3 to yield a 5 column table.

             W5 converts the table in W4 to a table of XY series where the
             first column is the date values, the second column is the time
             values and the remaining columns are the Y values. The resulting
             table contains 3 XY plots (a total of 6 columns).

             W6 returns the second XY plot from W5.

    Example:
             W1: julstr(getdate)..julstr(getdate)+9;setvunits("Daily")
             W2: todstr(gettime)..todstr(gettime)+9;setvunits("Time")
             W3: randn(10, 3);setvunits("V", -1)
             W4: ravel(W1, W2, W3)
             W5: stripchart(xydttab(w4))

             Same as above except W5 displays the three XY plots as a single
             stripchart.

    Remarks:
             XYDTTAB creates a table of XY plots from a table where
             typically one column is the date data, another column is
             the time data and the remaining columns are the Y data. 
             By default, the first column of the input table is
             considered the date values, the second column is
             considered the time values and the remaining columns are
             the Y values.

             Use GETITEM to extract a specific XY plot from the result.

             See XYTAB to create a table of XY plots from X and Y data.

             To configure the X Axis to display both date and time values,
             use SETCONF("dt_scales_format", "1")

    See Also:
             GETITEM
             JULSTR
             TODSTR
             JULYMD
             XY
             XYDT
             XYTAB
#endif


static ip = -1;

/* convert all columns of a table to xydt given the date and time columns */
xydttab(tab, datecol, timecol, collist, intv)
{
        local nc, cols, ncols, timeser, s, k, vu;

        if (argc < 4)
        {
                if (argc < 3)
                {
                        if (argc < 2)
                        {
                                if (argc < 1) error("xydttab - input table required");

                                datecol = 1;
                        }

                        timecol = 2;
                }

                collist = {};
                intv    = -2;
        }
        else
        {
                (collist, intv) = xydttab_parse_args(collist, intv);
        }

        if (isempty(collist))
        {
                collist = 1..numcols(tab);
        }

        if (isarray(datecol))
        {
                /* use input date data */
                dateser = refseries(datecol);
                datecol = 0;
        }
        else
        {
                dateser = col(tab, datecol);
                cols    = collist;
                collist = delete(cols, cols == datecol);

                if (length(collist) == 0)
                {
                        collist = cols;
                }
        }

        if (isarray(timecol))
        {
                /* use input time data */
                timeser = refseries(timecol);
                timecol = 0;
        }
        else
        {
                timeser = col(tab, timecol);
                cols    = collist;
                collist = delete(cols, cols == timecol);

                if (length(collist) == 0)
                {
                        collist = cols;
                }
        }

        /* remove out of range columns */
        collist = delete(collist, collist > numcols(tab));

        if (isempty(tab) || isempty(dateser) || isempty(timeser) || isempty(collist))
        {
                return({});
        }

        ncols = length(collist);

        /* check default comment for time */
        defcom = getwksattribute("defaultcomment");

        if (strcmp(getcomment(dateser), defcom) == 0)
        {
                setcomment(dateser, "Daily");
        }
        
        if (strcmp(getcomment(timeser), defcom) == 0)
        {
                setcomment(timeser, "Time");
        }

        (curim, previm) = iterate("xydt");

        /* replicate timeser for number of columns and convert to XY */
        s = xydt(repcol(dateser, ncols), repcol(timeser, ncols), tab[.., collist]);

        iterate("xydt", previm);
        
        if (intv >= -1)
        {
                /* let functions operate on each XY column */
                itemprocess(s, 1);

                /* override "process_items" mode to interpolate entire table */
                ip = setconfig("process_items", 1);

                /* interpolate each XY to interval series */
                s = xyinterp(s, intv);

                setconfig("process_items", ip);
                ip = -1;
        }

        /* set comments for Y */
        loop (k = 1..numitems(s))
        {
                vu = getvunits(tab, 1, collist[k]);
                setvunits(s, caststring(vu), k, 1);

                com = getcomment(s, k, 1);

                if (strcmp(defcom, com) == 0)
                {
                        com = sprintf("Chan %d", collist[k]);
                        setcomment(s, com, k, 1);
                }

        }

        /* let functions operate on each XY column */
        itemprocess(s, 1);

        /* display as table */
        setplotstyle(s, 4);
        setplottype(s, 0);

        return(s);
}


/* error handler, reset "process_items" */
xydttab_error(errnum, errmes)
{
        if (ip != -1)
        {
                setconfig("process_items", ip);
                ip = -1;
        }

        error(errmes);
}


xydttab_parse_args(collist, intv)
{
        local cl, iv;

        cl = {};
        iv = {};

        if (argc == 2)
        {
                if (isscalar(collist) && isarray(intv))
                {
                        cl = refseries(intv);
                        iv = collist;
                }
                else
                {
                        cl = refseries(collist);
                        iv = intv;
                }
        }

        if (argc == 1)
        {
                if (isscalar(collist))
                {
                        iv = collist;
                }
                else
                {
                        cl = collist;
                }
        }

        if (isempty(iv))
        {
                iv = -2;
        }

        return(cl, iv);
}