%%HP: T(3)A(R)F(.);
DIR

  DEMO                 @ Generate the data and call the filter demo.
    \<< RAD            @ RAD will set radians mode.  You may want to
                       @ remove it if you change Bpar's function.
Bpar BUILD             @ Get BUILD parameters.  Call BUILD.
PLOT 2 WAIT TEXT 40    @ Plot the good data.  Pause a bit.
NOISE PLOT 2 WAIT      @ Add noise of amplitude 40 Peak to Peak.
                       @ Plot the noisy data and pause again.
                       @ You may want to change this noise value
                       @ if you change the function in Bpar.
FDMO                   @ Call the filter demo.
    \>>

@ Filter Demo.
@ Assumes the summation array is valid and contains the data
@ you want filtered.  Loops 5 times, redisplaying the data
@ after each loop.

  FDMO
    \<< 1 5            @ Call the filter algorith 5 times.
      FOR i TEXT
CLLCD
"Filtering data...
Loop "
i + 1 DISP \GSDAT      @ Recall sum data to stack.
SMOOTH '\GSDAT' STO    @ Filter it. Store it.
PLOT 2 WAIT            @ Plot it.
      NEXT 7 FREEZE    @ Freeze display if last pass.
    \>>

@ Bpar
@ This list defines the function that will generate the initial
@ "clean" data.  The first element of the list is a function that
@ expects the X value on the stack.  After evaluating the function,
@ the Y value is on the stack.  The 2nd element is the starting X
@ value.  The 3rd is the ending X value.

  Bpar {
    \<< SIN 100 *      @ The function used by the demo is '100 * SIN(X)'
    \>> 0 12.5 }       @ The starting X value and ending X value.

@ BUILD
@ Builds summation data array based on Bpar values.
@ Expects a list (just like Bpar) on stack level 1.

  BUILD
    \<< OBJ\-> DROP DUP @ Get the individual elements from the list.
131 / RCLF \-> f        @ Take 131 samples.  Save flags.
start end step
flags
      \<< CLLCD
"Building \GSDAT.
Patience please...
 ...I aint a Cray!"
1 DISP 1 FIX CL\GS      @ Display the prompt.  Clear sum data.
start end
        FOR i end i     @ Display our progress.
%T "%" + 4 DISP i       @ Get the current X value.
DUP f EVAL \->V2 \GS+   @ Calculate Y form a vector.  Sum it away.
step                    @ Do next X.
        STEP flags
STOF
      \>>
    \>>

@ PLOT
@ Assumes the summation array exists.
@ Will draw a scatter plot based on the X values
@ in column 1 and the Y values in column 2.

  PLOT                  @ SCATTER PLOT of summed data
    \<< 1 XCOL 2 YCOL
SCATRPLOT
    \>>

@ SMOOTH is the main filtering (or smoothing) algorithm.
@ SMOOTH takes all y values (column 2) in the array and
@ averages them with the adjacent y values.
@ SMOOTH expects the summation data array on the stack.
@ It returns the filtered array to the stack when finished.
@ All you DSP experts out there can hack away at this or provide
@ your own algorithm.  As long as it's inputs and outputs are the
@ same, it should work well with the rest of these routines.

  SMOOTH                @ The main filtering algorithm.
    \<< OBJ\-> DUP 1    @ Break up array and determine size.
GET 2 * 3 PICK \->      @ Get the number of stack elements to roll.
dim ec y                @ Save initial y endpoint
      \<< 1 ec 2 / 1    @ Average all y values in the array.
-
        START 3         @ Get adjacent y values and average them.
PICK + 5 PICK + 3 /
y SWAP 'y' STO ec       @ Save current average and restore the last one.
ROLLD ec ROLLD          @ Roll twice to get the next xy pair.
        NEXT ec
ROLLD ec ROLLD dim      @ Reassemble the array.
\->ARRY
      \>>
    \>>

@ NOISE adds random data to all y values in the
@ array.  The peak to peak noise amplitude is on
@ level 1.  It assumes a valid array is stored in
@ the summation data array variable.

  NOISE                 @ Add noise to all y data values.
    \<< CLLCD
"Adding noise..." 1
DISP \GSDAT OBJ\-> DUP
1 GET 2 * DUP 3 +
ROLL \-> dim ec noise
      \<< 1 ec 2 /
        START RAND
.5 - noise * + ec
ROLLD ec ROLLD
        NEXT dim
\->ARRY '\GSDAT' STO
      \>>
    \>>

@ LOOP calls the SMOOTH routine n times.
@ The array is on level 2 and n is on level 1.
@ LOOP is not used by the demo.  It is usefull
@ for repeating the SMOOTH algorithm without
@ the delays caused by replotting the data as
@ the demo does.

  LOOP
    \<< 1 SWAP
      FOR i CLLCD
"Filtering data...
Loop "
i + 1 DISP SMOOTH
      NEXT
    \>>

END
