FOCUS AREAS

Statistics and Operations Research: Examples

Source Code for the Forecast Command Builder

/* Copyright(c) 2000 by SAS Institute Inc., Cary, NC USA */
/* FORCCOUT.SCL:  Source code for FORCCOUT.FRAME. */
/* Updated for version 8.2 25August2000.          */
/* Displays forecast output from the Forecast     */
/* Command Builder (forccmd.frame). Each data set */
/* obtained from the out= argument in the command */
/* list can be displayed as a graph--using either */
/* forcgraf.frame (new type) or forccgrf.frame    */
/* (classic type)--or as a table (using Viewtable)*/
/* by selecting the name and clicking the graph   */
/* button or the table button.                    */
/* Ordinarily, each data set will have the same   */
/* name as the input series, making it easy to    */
/* identify the series associated with the output.*/
/* If a data set does not exist due to errors in  */
/* in the forecasting process, an asterisk is     */
/* displayed next to its name and a footnote is   */
/* displayed below the list box.                  */
/* If the user requested graphs for all forecasts,*/
/* the name of a graphics catalog (graphcat) is   */
/* passed in, and proc gplot is run using the     */
/* %forgraph macro.  If the user also requested   */
/* output to a web page, an html directory name   */
/* is passed in and proc greplay is used with the */
/* webframe device driver to created a frame page */
/* with thumbnails linking to the individual      */
/* graphs.                                        */
/* Entries called by this program:                */
/* forcmtd.scl (scl methods),                     */
/* forcgraf.frame (new graphics),                 */
/* forccgrf.frame (classic graphics).             */

length dsn $ 41 text $ 8 outname $ 41 horizon $ 4
       timeid interval $ 32 cmd $ 200
       prefix $ 4 htmlfile $ 200 delim $ 1;

entry comndlst  8   /* List of forecast commands */
      graphcat $    /* Graphics output catalog   */
      htmldir  $    /* HTML output directory     */
      title2   $    /* Extra title text          */
      datefrmt $    /* Time/date format          */
      ;

init:

   outlist = makelist();   * List of output data set names;
   cmdlist = copylist(comndlst);  * Use a local copy;
   footnote = ' ';

   /* File delimiter depends on operating system. */
   if substr(symget("sysscp"),1,3) = "WIN"
   then delim = '\';
   else delim = '/';

   /*Loop over command list passed in from forccmd.frame.*/
   do i=1 to listlen( cmdlist );
      cmd = getitemc( cmdlist, i );

      /* Get the output data set name from the command. */
      call method( 'forcmtd.scl', 'getarg', cmd,
                   'OUT=', 41, outname );

      if outname ^= ' '
      then do;
           if ^exist( outname ) then do;
               outname = outname || '*';
               footnote =
                 '* Not available.  See log for errors.';
               end;
           outlist = insertc( outlist, outname, -1 );
           end;

      end;  /*  do i=1 to listlen( cmdlist ); */

   /* If no out= args were given, there will be no      */
   /* output data sets.                                 */
   if listlen( outlist ) < 1
   then outlist = insertc( outlist,
        'No data sets were specified', -1 );

   else if graphcat ^= ' ' then link gplot;

   call notify('graph',    '_gray');
   call notify('graftype', '_gray');
   call notify('table',    '_gray');

   /* Set graftype to 1 by default (new type of forecast*/
   /* graph using Time Series Graphics object.          */
   graftype = 1;
return;  /* init */

term:
   outlist = dellist( outlist );
   cmdlist = dellist( cmdlist );
   rc = delete( 'work.tempf' );
return;  /* term */

gplot:
  /* Use %forgraph macro to graph all the forecast */
  /* data sets using proc gplot.                   */

  do i=1 to listlen(outlist);
    dsn      = getitemc( outlist, i  );
    if ^index(dsn, '*') then do;

      /* Get the time id from the command. */
      cmd = getitemc( cmdlist, i );
      call method( 'forcmtd.scl', 'getarg', cmd,
                   'ID=', 32, timeid );
      if timeid = _blank_ then timeid = 'DATE';

      /* Get the interval name from the command. */
      call method( 'forcmtd.scl', 'getarg', cmd,
                   'INTERVAL=', 32, interval );

      /* Get the horizon, if any, from the command. */
      call method( 'forcmtd.scl', 'getarg', cmd,
                   'HORIZON=', 4, horizon  );
      if horizon = _blank_
      then horizon = '12';

      submit continue;
        %forgraph( &dsn, actual=ACTUAL, forecast=PREDICT,
                   lower=LOWER,
                   upper=UPPER, timeid=&timeid,
                   interval=&interval,
                   lead=&horizon, type=0, title1=&dsn,
                   title2=&title2,
                   plotname=&dsn, outcat=&graphcat,
                   idformat=&datefrmt );
      endsubmit;
      end;
    end;


  if htmldir ^= ' ' then do;
      gdev = optgetc('DEVICE');
      submit continue;
      filename webdoc '&htmldir';

      goptions device=webframe gsfname=webdoc
               transparency noborder;

      proc greplay igout=&graphcat nofs;
      replay _all_;

      goptions device=&gdev;
      run;
      quit;
      endsubmit;

      htmlfile = htmldir || delim || 'index.html' ;
      end;

  outlist = insertc(outlist,
          '----Individual series forecasts: ----', 1 );
  outlist = insertc(outlist, 'SAS/GRAPH output '
                    || graphcat, 1 );
  cmdlist = insertc(cmdlist,' ',1);
  cmdlist = insertc(cmdlist,' ',1);

  if htmldir ^= _blank_ then do;
     outlist = insertc(outlist, 'HTML output '
                       || htmlfile, 1 );
     cmdlist = insertc(cmdlist,' ',1);
     end;
return;  /* gplot */

grafdata:
/* Prepare a temporary dataset for overlay graphing */
/* using a graphics object.  This is only used when */
/* using the 'classic' style graph.                 */

   /* Find forcstrt, the time ID value at which  */
   /* the forecast time range begins.            */
   dsid = open( dsn, 'IN' );
   tidvnum = varnum( dsid, timeid );

   /* Timeid might not be in dataset if a different time */
   /* id was saved in the project.  If not, use the      */
   /* first variable in the data set.                    */
   if tidvnum = 0 then do;
      tidvnum = 1;
      timeid = varname( dsid, 1 );
      end;

   rc = where( dsid, 'ACTUAL ^= .' );
   rc = varstat( dsid, timeid, 'max', maxtid );
   rc = where( dsid );
   rc = locaten( dsid, tidvnum, maxtid, 'a' );
   obs = curobs( dsid )    ;
   rc = fetchobs( dsid, obs );
   forcstrt = getvarn( dsid, tidvnum );
   rc = close( dsid );

   submit;
     data tempf;
     set &dsn;
   endsubmit;

   if datefrmt ^= _blank_ then do;
     submit;
     format &timeid &datefrmt;
     endsubmit;
     end;

   submit continue;
     keep &dsn Legend &timeid;
     if &timeid < &forcstrt then do;
        &dsn = actual;
        Legend = 'Actual Values    ';
        output;

        &dsn = predict;
        Legend = 'Model Predictions';
        output;
        end;
     else do;
        if &timeid = &forcstrt then do;
           &dsn = actual;
           Legend = 'Actual Values    ';
           output;

           &dsn = predict;
           Legend = 'Model Predictions';
           output;
           end;

        &dsn = predict;
        Legend = 'Forecast';
        output;

        &dsn = upper;
        Legend = 'Upper C.L.';
        output;

        &dsn = lower;
        Legend = 'Lower C.L.';
        output;
        end;
        run;
   endsubmit;

return;  /* grafdata */

graph:
   /* Graph button */

   if prefix = 'HTML'
   then do;
          /* The HTML output item is selected, so    */
          /* bring up web browser to display it.     */
          call execcmd('wbrowse "' || htmlfile || '"' );
          return;
          end;

   if prefix = 'SAS/' then do;
      /* The SAS/GRAPH output item is selected, so  */
      /* bring up graph window to display it.       */
      call execcmd('graph ' || graphcat );
      return;
      end;

   /* An individual forecast data set is selected so  */
   /* graph it using forccgrf.frame.                  */
   cmd = getitemc( cmdlist, row );
   call method( 'forcmtd.scl', 'getarg', cmd,
                'ID=', 32, timeid );

   /* Check graftype radio button.  If 1 (new) use the */
   /* new forecast graph (forcgraf.frame) for plotting */
   /* individual forecast data sets.  Otherwise use the*/
   /* classic type (forccgrf.frame).                   */

   if graftype = 1
   then call display( 'forcgraf.frame', dsn, timeid );

   else do;   /* 'classic' graph */
      link grafdata;
      call display( 'forccgrf.frame', dsn, timeid, forcstrt );
      end;

return;   /* graph */

outplist:
   /* The output objects list box */
   call notify( 'outplist', '_get_last_sel_',
                row, issel, text );

   if issel then do;
     dsn = getitemc( outlist,  row );
     prefix = substr(dsn,1,4);

     if index(dsn, '*' ) | (prefix = '----')
     then do;
          call notify('graph',    '_gray');
          call notify('graftype', '_gray');
          call notify('table',    '_gray');
          end;

     else do;
          call notify('graph',    '_ungray');
          call notify('graftype', '_ungray');
          if substr(dsn,1,4) in ('HTML','SAS/')
          then do;
                  call notify('table',    '_gray');
                  call notify('graftype', '_gray');
                  end;
          else do;
                  call notify('table',    '_ungray');
                  call notify('graftype', '_ungray');
                  end;
          end;
     end;

     else do;
          dsn = ' ';
          prefix = ' ';
          end;

return;  /* outplist */

quit:
   call execcmd( 'end' );
return;    /* quit */

table:
   /* The table button.  Can display individual */
   /* forecast data sets as a table.            */
   call execcmdi( 'viewtable ' || dsn );
return;   /* table */

rc = rc;    /* prevents compiler warning */