\section{Appendix: Sisal Functions for the Optical Surveillance Example}

As presented in the text, the overall computation of this illustration
is structured as the composition of functions given in
Figure~\ref{process-sisal}. The overall computation processes
signals from a collection of sensors that are swept over the
region under surveillance. These signal are conditioned, averaged,
and filtered before a peak detection criterion is applied.


\begin{figure}[tb]\small
\begin{verbatim}
type Signal = stream [integer];
type ImageStream = array [ Signal ];
type DataStream = array [ array [Signal] ];
type MarkStream = array [ stream [boolean] ];

function Process (
   D: DataStream;
   w: integer;
   n: integer
   returns MarkStream )

   let
      R := for i in 1, w
      returns array of
         let S := for j in 1,n
            returns array of
               BaseRemove (D[i,j])
         Nyquist ( SpikeAdapt ( S[i], n ) )
      end for
   in
      PeakDetect ( TwoDimFilter ( R, w ) )
   end let

end function
\end{verbatim}
\caption{\label{process-sisal}The surveillance process as a composition
    of stream processing functions in Sisal.}
\end{figure}


\subsection{Baseline Removal}

The first step is a procedure designed to ignore a slowly-varying
base component of the signal from each sensor. This is defined by
the program {\tt BaseRemove} shown in Figure~\ref{base-sisal}.

\begin{figure}[tb]\small
\begin{verbatim}
function BaseRemove (
  D: stream [integer]
  returns stream [integer] )

  AdaptiveBase (
    D, stream_first(D), false, stream_first(D) )

end function

function AdaptiveBase (
  D: stream [integer];
  Th: integer;
  Sw: boolean;
  B: integer
  returns stream [integer] )

  let
    Th0 := 32;
    Df := stream_first(D);
    Dr := stream_rest(D);
    B_new :=
      if Sw then Df else B end if;
    Th_new := max ( Th0, Th +
      if Sw then ( Th / 4)
      else - ( Th / 16 )
      end if );
    Sw_new := ( Df - B_new > Th0 );
  in
    stream [ Df - B_new ] ||
      AdaptiveBase (Dr, Th_new, Sw_new, B_new)
  end let
end function
\end{verbatim}
\caption{\label{base-sisal}The {\tt BaseRemove} function.}
\end{figure}


\subsection{Spike Adaptive Averaging}

The second module (Figure~\ref{spike-sisal}) combines signals
from groups of $n$ sensors, rejecting data that exceeds a threshhold. 


\begin{figure}[tb]\small
\begin{verbatim}
function SpikeAdapt (
   D: stream [ array [integer] ];
   n: integer
   returns stream [integer] )

   let
      Th2 := 24;

      E := stream_first( D );

      L := for i in 1, n
         returns value of least ( E[i] ) 
         end for;

      Sm := for i in 1, n
         returns value of sum 
            if E[i] < ( L + Th2 ) then E[i]
            else 0
            end if
         end for;

      Nc := for i in 1, n
         returns value of sum
            if E[i] < ( L + Th2 ) then 1
            else 0
            end if
         end for;

   in
      stream [ Sm / Nc ] ||
           SpikeAdapt ( stream_rest(D), n )

   end let
end function
\end{verbatim}
\caption{\label{spike-sisal}The {\tt SpikeAdapt} function.}
\end{figure}


\subsection{Nyquist Filter}

This module (Figure~\ref{nyquist-sisal}) reduces the sampling
rate of the data stream by
combining groups of four samples using weights designed to
provide a good approximation to the input.

\begin{figure}[tb]\small
\begin{verbatim}
function
   NyquistFilter ( D: stream [integer]
   returns stream [integer])

   let
      Df, Dfr, Dfrr, Drrrr :=
         stream_first(D),
         stream_first( stream_rest(D) ),
         stream_first( stream_rest
             (stream_rest(D) ) ),
         stream_rest(stream_rest
             (stream_rest(stream_rest(D) ) ) );
      D_new :=
         ( 2 * Dfr + Df + Dfrr );
   in
      stream [ D_new ] ||
         NyquistFilter ( Drrrr )
   end let
end function
\end{verbatim}
\caption{\label{nyquist-sisal}The {\tt Nyquist} function.}
\end{figure}


\subsection{Two-Dimension Filter}

The function {\tt TwoDimFilter} shown in Figure~\ref{filter-sisal}
represents a two-dimension filter by a single Sisal function.
The filter is defined by the three coefficients, {\tt a}, {\tt b}, and {\tt c},
which are the center, side and corner elements of a three-by-three array.
The filter is applied at each position in the image data for
which an output value is desired. The input is an array
of streams indexed from $1$ to $w$. The output is an array
of streams indexed from $2$ to $w-1$.
(The boundary elements are omitted from the result data to
avoid applying the filter function to non-existing array
positions.)

\begin{figure}[tb]\small
\begin{verbatim}
function TwoDimFilter (
      D: ImageStream; w: integer
      returns ImageStream )

   let
      a := 4; b := 2; c := 1;

      Bf := for i in 1, w
         returns array of array [-1: 
            stream_first(D[i]),
            stream_first(stream_rest(D[i])),
            stream_first(stream_rest
               (stream_rest(D[i])))]     
         end for;

      Dt := for i in 1, w
         returns array of
            stream_rest( D[i] )
         end for;

      Dn := for i in 2, w-1
         returns array of
            a * Bf[i, 0] +
            b * ( Bf[i, -1] + Bf[i-1, 0] +
                Bf[i+1, 0] + Bf[i, +1] ) +
            c * ( Bf[i-1, -1] + Bf[i-1, +1] +
                Bf[i+1, -1] + Bf[i+1, +1] )
         end for;

      Dr := TwoDimFilter ( Dt, w )

   in
      for i in 2, w-1
      returns array of
         stream [ Dn[i] ] || Dr[i]
      end for
   end let

end function
\end{verbatim}
\caption{\label{filter-sisal}The {\tt TwoDimFilter} function.}
\end{figure}


\subsection{A Peak Detector Algorithm}

Figure~\ref{peak-sisal} shows a {\tt PeakDetect} function that identifies
all elements of the (image) data that have a value
that is at least equal to the values of all immediate neighbors
and exceeds their average by a given threshhold {\tt Th}.
The two conditions
are tested separately and combined to determine the result.
The input is an array of integer streams indexed from $2$ to $w-1$.
The output stream is an array of boolean
streams indexed from $3$ to $w-2$.
The peak detection function is similar in structure
to the filter function; each element of the result
is true if and
only if the data surrounding the corresponding input
pixel satisfies the specified conditions.


\begin{figure}[tb]\small
\begin{verbatim}
function PeakDetect (
    D: ImageStream; w: integer
    returns MarkStream )

  let
    Th := 0;

    B := for i in 2, w-1
      returns array of array [-1: 
         stream_first(D[i]),
         stream_first(stream_rest(D[i])),
         stream_first(stream_rest
                 (stream_rest(D[i])))]
      end for;

    Dt := for i in 2, w-1
      returns array of
        stream_rest( D[i] )
      end for;

    Pk := for i in 3, w-2

      P := B[i, 0];

      C := B[i-1, -1] <= P &
          B[i-1, 0] <= P &
          B[i-1, +1] <= P &
          B[i, -1] <= P &
          B[i, +1] <= P &
          B[i+1, -1] <= P &
          B[i+1, 0] <= P &
          B[i+1, +1] <= P;

      S := B[i-1, -1] + B[i-1, 0] + B[i-1, +1] +
          B[i, -1] + B[i, +1] +
          B[i+1, -1] + B[i+1, 0] + B[i+1, +1];
     
      returns array of C & ( 8 * P > S + 8 * Th )
      end for;

    Dr := PeakDetect ( Dt, w );

  in

    for i in 3, w-2
    returns array of
      stream [ Pk[i] ] || Dr[i]
    end for

  end let

end function
\end{verbatim}
\caption{\label{peak-sisal}The {\tt PeakDetect} algorithm.}
\end{figure}
