SlopeDetectorFilter.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Edward Daw, Jolien Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /********************************** <lalVerbatim file="SlopeDetectorFilterCV">
00021 Author: Daw, E. J.
00022 $Id: SlopeDetectorFilter.c,v 1.10 2007/06/08 14:41:52 bema Exp $  
00023 ************************************* </lalVerbatim> */
00024 
00025 /********************************************************** <lalLaTeX>
00026 \subsection{Module \texttt{SlopeDetectorFilter.c}}
00027 
00028 Functions in this code segment implement various time domain 
00029 search algorithms for transients and bursts in the LIGO data.
00030 
00031 \subsubsection*{Prototypes}
00032 \input{SlopeDetectorFilterCP}
00033 \idx{LALSlopeDetectorFilter()}
00034 \input{SlopeLineFitFilterCP}
00035 \idx{LALSlopeLineFitFilter()}
00036 \input{SlopeConvolutionFilterCP}
00037 \idx{LALSlopeConvolutionFilter()}
00038 
00039 \subsubsection*{Description}
00040 
00041 The three fine fuctions prototyped above implement time domain linear and nonlinear
00042 filters on input data. The resulting output data is intended to enhance
00043 sensitivity to burst sources. 
00044 
00045 The first function is \texttt{void LALSlopeDetectorFilter()}, which
00046 takes input data through its third argument
00047 \texttt{const REAL4Vector* input\_data}. For
00048 each element $i$ of the input data ntuple $x_i$, the best fit slope
00049 the data points $i$ to $i+N-1$ is found, where $N$ is the fourth
00050 argument \texttt{ntaps} passed to the function. This function 
00051 provides no provision for history buffers. The output data is written
00052 to the address \texttt{REAL4Vector* output\_data} passed as the second
00053 argument.
00054 
00055 The second function is \texttt{LALSlopeLineFitFilter()}, which also
00056 takes a \texttt{const REAL4Vector* input\_data} pointer to input data as
00057 its third argument. For each element $i$ of the
00058 input data ntuple $x_i$, the best fit slope, $a_i$ , or the best
00059 fit intercept to the data (vertical) axis, $b_i$, or a particular
00060 nonlinear combination of $a_i$ and $b_i$ is found. Any of these
00061 three quantities can be returned to the output address 
00062 \texttt{REAL4Vector* output\_data}, depending on the argument passed
00063 to \texttt{fparams.function\_select}. Acceptable values for this parameter
00064 are shown in table \ref{slopetable:fitsettings}.
00065 
00066 \begin{table}
00067 \begin{center}
00068 \begin{tabular}{|l|c|r|} \hline
00069 \texttt{fparams.function\_select} & 
00070 value & filter output \\ \hline\hline
00071 \texttt{FILTER\_OUTPUT\_SLOPE} & 1 & fit to slope $a_i$ over N bins \\ \hline
00072 \texttt{FILTER\_OUTPUT\_OFFSET} & 2 & fit to offset $b_i$ over N bins \\ \hline
00073 \texttt{FILTER\_OUTPUT\_ALF} & 3 & ALF filter (see algorithms) \\ \hline
00074 \end{tabular}
00075 \caption{settings for \texttt{fparams.function\_select} used in conjunction
00076 with function \texttt{LALSlopeLineFitFilter()}.}
00077 \label{slopetable:fitsettings}
00078 \end{center}
00079 \end{table}
00080 
00081 The third function is \texttt{LALSlopeConvolutionFilter()}.This
00082 function convolves input data with time domain
00083 finite impulse response (FIR) filters of four types. Before
00084 running the filter on data, the filter taps must be set. Allocate
00085 enough memory to hold the number of filter taps you want. Set
00086 \texttt{fparams.forder} to be equal to the number of taps.
00087 Set the \texttt{fparams.function\_select} to one of the values given
00088 in table \ref{slopetable:convsettings}.
00089 
00090 \begin{table}
00091 \begin{center}
00092 \begin{tabular}{|l|c|r|} \hline
00093 \texttt{fparams.function\_select} & 
00094 value & filter output \\ \hline\hline
00095 \texttt{FILTER\_OUTPUT\_BOXCAR} & 4 & 
00096 set taps to uniform window over N bins \\ \hline
00097 \texttt{FILTER\_OUTPUT\_GAUSSIAN} 
00098 & 5 & set taps to Gaussian over N bins \\ \hline
00099 \texttt{FILTER\_OUTPUT\_SINE} & 6 & 
00100 set taps to sine wave period over N bins \\ \hline
00101 \texttt{FILTER\_OUTPUT\_USER} & 7 & 
00102 set taps to user defined \\ \hline
00103 \texttt{FILTER\_OUTPUT\_CONVOLVE} & 8 & 
00104 convolve data with a filter already set up \\ \hline
00105 \end{tabular}
00106 \caption{settings for \texttt{fparams.function\_select} used in conjunction
00107 with function \texttt{LALSlopeConvolutionFilter()}.}
00108 \label{slopetable:convsettings}
00109 \end{center}
00110 \end{table}
00111 
00112 The \texttt{BOXCAR} option creates N taps that are all set to 1/N.
00113 The \texttt{GAUSSIAN} option creates taps that represent part of
00114 a gaussian curve between $\pm 3\sigma$. The \texttt{SINE} option
00115 sets the taps to be one period of a sine wave. 
00116 Both the sine and Gaussian tap waveforms are of unity height. If the 
00117 \texttt{USER} option is set, then the \texttt{input\_data} field
00118 is used to set the taps. In the latter case, the 
00119 \texttt{input\_data->length} field must be the same as
00120 \texttt{fparams.forder} field, and equal the number of elements
00121 in the input data array. In all cases, memory must be allocated 
00122 by the calling function to the \texttt{fparams.taps\_set} field,
00123 which must be initialized to zero. Once the function is called
00124 to set the taps, the \texttt{fparams.taps\_set} field is changed to
00125 one. 
00126 
00127 Once the filter has been initialized, it can be convolved with
00128 data. History buffering is supported, and works in the same way
00129 as for the \texttt{LALSlopeLineFitFilter} function described
00130 above. Note that the \texttt{fparams.function\_select} field
00131 must be set to \texttt{FILTER\_OUTPUT\_CONVOLVE}. 
00132 
00133 \subsubsection*{Algorithm}
00134 
00135 The algorithms used for applying filters with the three functions
00136 described above are given below. For all formulae, $x_i$ represents
00137 an array of input data. The filters embedded in the functions
00138 \texttt{LALSlopeDetectionFilter} and \texttt{LALSlopeLineFitFilter}
00139 work by fitting each overlapping set of N successive data points
00140 to a straight line $a_i x_{i+j} + b_i$. The fit parameters $a_i$
00141 and $b_i$ are used as the basis to form discriminants. The
00142 \texttt{LALSlopeConvolutionFilter} function convolves input
00143 data either with a standard set of waveforms, or with waveforms
00144 set by the user as described above. In all the equations below,
00145 N is the number of successive data samples used to compute the
00146 quantities, the filter `order'. 
00147 
00148 For \texttt{LALSlopeDetectionFilter} the output data array is $y_i$:
00149 
00150 \begin{equation}
00151 y_i = \frac{
00152 \frac{1}{N} \sum_{j=0}^{N-1} x_{i+j} t_{i+j} - 
00153 \left( \frac{1}{N} \sum_{k=0}^{N-1} x_{i+k} \right)
00154 \left( \frac{1}{N} \sum_{m=0}^{N-1} t_{i+m} \right)
00155 }{
00156 \frac{1}{N} \sum_{p=0}^{N-1} t_{i+p}^2 -
00157 \left( \frac{1}{N} \sum_{q=0}^{N-1} t_{i+q} \right)^2
00158 }
00159 \label{eqn:slopedetectone}
00160 \end{equation}
00161 
00162 For
00163 \texttt{LALSlopeLineFitFilter} with 
00164 \texttt{fparams.function\_select} set to \texttt{FILTER\_OUTPUT\_SLOPE},
00165 the output data $a_i$ is
00166 
00167 \begin{equation}
00168 a_i = \frac{12}{\tau N(N^2 - 1)}
00169 \left( \sum_{j=0}^{N-1} jx_j - \frac{N-1}{2} \sum_{k=0}^{N-1} x_k \right),
00170 \label{eqn:slopedgrad}
00171 \end{equation}
00172 
00173 where $\tau$ is the sampling period. Apart from a factor of $\tau$, equations
00174 \ref{eqn:slopedetectone} and \ref{eqn:slopedgrad} are equivalent,
00175 since we have the following identities:
00176 
00177 \begin{eqnarray}
00178 \sum_{j=0}^{N-1} j & = & \frac{N(N-1)}{2} \\ \nonumber
00179 \sum_{j=0}^{N-1} j^2 & = & \frac{N}{6} (2N-1)(N-1) \\ \nonumber
00180 \label{eqn:slopepartialsums}
00181 \end{eqnarray}
00182 
00183 Note that slope filters have a mimimum order of 2, since it takes at least 2 points
00184 to estimate the slope.
00185 
00186 For 
00187 \texttt{LALSlopeLineFitFilter} with
00188 \texttt{fparams.function\_select} set to \texttt{FILTER\_OUTPUT\_OFFSET},
00189 $a_i$ is calculated and used to estimate the output $b_i$ given by
00190 
00191 \begin{equation}
00192 b_i = \sum_{j=0}^{N-1} x_j - \frac{a_i \tau (N-1)}{2}.
00193 \label{eqn:slopedetecttwogradient}
00194 \end{equation}
00195 
00196 For
00197 \texttt{LALSlopeLineFitFilter} with
00198 \texttt{fparams.function\_select} set to \texttt{FILTER\_OUTPUT\_ALF},
00199 a nonlinear combination of $a_i$ and $b_i$ is constructed.
00200 Define $\sigma_a$ and $\sigma_b$:
00201 
00202 \begin{eqnarray}
00203 \sigma_a & = & \frac{12}{\tau N(N^2 - 1)} \\ \nonumber
00204 \sigma_b & = & \frac{4N+2}{N(N-1)}. \\ \nonumber
00205 \label{eqn:slopedetecttwoalfone}
00206 \end{eqnarray}
00207 
00208 Let $X_a = a_i / \sigma_a$ and $X_b = b_i / \sigma_b$. Then the
00209 output $c_i$ of the \texttt{ALF} filter is 
00210 
00211 \begin{equation}
00212 c_i = \frac{
00213 X_a^2 + X_b^2 - 2 \alpha X_a X_b}{
00214 1 - \alpha^2},
00215 \label{eqn:slopedetecttwoalftwo}
00216 \end{equation}
00217 
00218 where
00219 
00220 \begin{equation}
00221 \alpha = -\sqrt{
00222 \frac{3(N+1)}{2(2N+1)}.
00223 \label{eqn:slopedetecttwoalfthree}
00224 }
00225 \end{equation}
00226 
00227 This nonlinear combination was found by the Orsay group to 
00228 be particularly sensitive to bursts in the Zwerger Mueller catalog.
00229 See \texttt{gr/qc-0010037} for a full description.
00230 
00231 The remaining filters use a standard convolution algorithm to
00232 convolve input data with the waveforms described above (boxcar,
00233 gaussian, sinewave, user). The convolution of input data
00234 $x_i$ with filter taps $c_j$ is
00235 
00236 \begin{equation}
00237 y_i = \sum_{j=0}^{N-1} x_{i+j} c_j
00238 \label{eqn:slopedetectconv}
00239 \end{equation}
00240 
00241 \subsubsection*{Uses}
00242 
00243 % List any external functions called by this function.
00244 \begin{verbatim}
00245 These functions do not use any other LAL routines.
00246 \end{verbatim}
00247 
00248 \subsubsection*{Notes}
00249 
00250 All pointers passed to these functions must be preallocated by
00251 the calling routine to have enough memory to hold the objects
00252 written to them. In particular, the pointer to the output data
00253 must be of size \texttt{input\_data\_length - filter\_order + 1},
00254 where \texttt{filter\_order} is \texttt{ntaps} in the function
00255 \texttt{LALSlopeDetectorFilter} and \texttt{fparams.forder} in
00256 \texttt{LALSlopeLineFitFilter} and \texttt{LALSlopeConvolutionFilter}.
00257 Unused parameters that are pointers can be set to \texttt{NULL} (for
00258 example, the \texttt{fparams.tap} field can be null if calling
00259 the \texttt{LALSlopeLineFitFilter} function.
00260 
00261 The functions
00262 \texttt{LALSlopeLineFitFilter} and \texttt{LALSlopeConvolutionFilter}
00263 support the passing of a history buffer between successive applications
00264 of a filter. The history buffer pointer needs to be allocated by the
00265 calling routine when using these functions. Enough memory must be
00266 allocated to it to hold \texttt{fparams.forder - 1} \texttt{REAL4}
00267 elements. After running the filter, the history buffer will contain
00268 the last \texttt{fparams.forder - 1} elements of the input data sent
00269 to the filter. By adding these elements to the beginning of the next
00270 set of input data sent to the filter, a continuous filtered data stream
00271 with a seamless boundary may be maintained between successive 
00272 applications of the filter. Note that currently the passing of history
00273 buffers between successive MPI jobs is not supported under LDAS. 
00274 
00275 Both \texttt{LALSlopeLineFitFilter} and \texttt{LALSlopeConvolutionFilter}
00276 require the field \texttt{fparams.sampling\_period\_s} to contain
00277 the reciprocal of the sampling frequency for the channel. 
00278 
00279 The \texttt{waveform\_offset} field in \texttt{SLOPEFilterParam} is
00280 there in case you need to offset the filter waveform by a fraction
00281 of a frequency bin (eg, if you want the maximum of a gaussian filter
00282 to fall equally between two bins, you would set
00283 this field to $0.5$).
00284 
00285 \vfill{\footnotesize\input{SlopeDetectorFilterCV}}
00286 
00287 *** </lalLaTeX> */ 
00288 
00289 /******* INCLUDE STANDARD LIBRARY HEADERS; ************/
00290 /* note LALStdLib.h already includes stdio.h and stdarg.h */
00291 
00292 #include <math.h>
00293 
00294 /******* INCLUDE ANY LDAS LIBRARY HEADERS ************/
00295 
00296 /******* INCLUDE ANY LAL HEADERS ************/
00297 #include <lal/LALStdlib.h>
00298 #include <lal/SlopeDetectorFilter.h>
00299 
00300 /******* DEFINE RCS ID STRING ************/
00301 NRCSID( SLOPEDETECTORFILTERC, "$Id: SlopeDetectorFilter.c,v 1.10 2007/06/08 14:41:52 bema Exp $" );
00302 
00303 /******* DEFINE LOCAL CONSTANTS AND MACROS ************/
00304 
00305 /********************************************/
00306 /**** LALSlopeDetectorFilter ****************/
00307 /********************************************/
00308 
00309 static void
00310 CreateGaussianTaps( UINT4 ntaps,
00311                     REAL4 binoffset,
00312                     REAL4* tap );
00313 
00314 static void 
00315 CreatePeriodSineTaps( UINT4 ntaps,
00316                       REAL4 binoffset,
00317                       REAL4* tap );
00318 
00319 
00320 
00321 /* <lalVerbatim file="SlopeDetectorFilterCP"> */
00322 void
00323 LALSlopeDetectorFilter( LALStatus          *status,
00324                         REAL4Vector*       output_data,
00325                         const REAL4Vector* input_data,
00326                         const UINT4        ntaps )
00327 /* </lalVerbatim> */
00328 {
00329   /******* DECLARE VARIABLES; for example: ************/
00330 
00331   REAL4              meanxt,meant,meanx,meantsquared;
00332   UINT4              i,j,datalength;
00333   REAL4*             datain;
00334   REAL4*             dataout;
00335   REAL4              tindex, nreal;
00336 
00337   INITSTATUS( status, "LALSlopeDetectorFilter", SLOPEDETECTORFILTERC );
00338   /* only needed if you call other LAL functions within your code */
00339   /* ATTATCHSTATUSPTR (status); */
00340 
00341   if ( input_data == NULL ) {
00342     ABORT( status, SLOPEDETECTORFILTERH_EINPUTNULLP, 
00343            SLOPEDETECTORFILTERH_MSGEINPUTNULLP );
00344   }
00345   if ( output_data == NULL ) {
00346     ABORT( status, SLOPEDETECTORFILTERH_EOUTPUTNULLP, 
00347            SLOPEDETECTORFILTERH_MSGEOUTPUTNULLP );
00348   }
00349 
00350   datalength = input_data->length;
00351   datain = input_data->data;
00352   dataout = output_data->data;
00353 
00354   /******* CHECK VALIDITY OF ARGUMENTS; for example ************/
00355 
00356   if ( dataout == NULL ) {
00357     ABORT( status, SLOPEDETECTORFILTERH_EINPUTNULLP, 
00358            SLOPEDETECTORFILTERH_MSGEINPUTNULLP );
00359   }
00360   if ( datain == NULL ) {
00361     ABORT( status, SLOPEDETECTORFILTERH_EOUTPUTNULLP, 
00362            SLOPEDETECTORFILTERH_MSGEOUTPUTNULLP );
00363   }
00364   if ( datalength < ntaps ) {
00365     ABORT( status, SLOPEDETECTORFILTERH_EDATATOOSHORT, 
00366            SLOPEDETECTORFILTERH_MSGEDATATOOSHORT );
00367   }
00368 
00369   /* printf("CODE: At div by zero point, ntaps is %u\n",ntaps); */
00370   /* check that the number of taps is not zero */
00371   if ( ntaps == 0 ) {
00372     ABORT( status, SLOPEDETECTORFILTERH_EDIVBYZERO, 
00373            SLOPEDETECTORFILTERH_MSGEDIVBYZERO );
00374   }
00375 
00376   /******* DO ANALYSIS ************/
00377 
00378   nreal=(REAL4)ntaps;
00379   for(i=0;i<(datalength-ntaps+1);++i) {
00380     meanx=0;
00381     meant=0; 
00382     meanxt=0; 
00383     meantsquared=0;
00384     for(j=0;j<ntaps;++j) {
00385       tindex = (REAL4)j;
00386       meanx += datain[i+j]/nreal;
00387       meant += tindex/nreal;
00388       meanxt += tindex*datain[i+j]/nreal;
00389       meantsquared += tindex*tindex/nreal;
00390     }
00391 
00392     /* check that the denominator is not zero */
00393     if ( (meantsquared - meant*meant) == 0 ) {
00394       ABORT( status, SLOPEDETECTORFILTERH_EDIVBYZERO, 
00395              SLOPEDETECTORFILTERH_MSGEDIVBYZERO );
00396     }
00397     
00398     dataout[i] = (meanxt - meanx * meant) / ( meantsquared - meant * meant );
00399 
00400     /*these lines present for testing purposes only*/
00401     /*printf("%u\t%f\t%f\t%f\t%f\t%f\n",
00402       i,meanx,meant,meanxt,meantsquared,dataout[i]); */
00403     /*dataout[i] = datain[i];*/
00404   }
00405   
00406   /* DETATCHSTATUSPTR(status); */
00407   RETURN(status);
00408 }
00409 
00410 /**********************************************/
00411 /*** LALSlopeLineFitFilter ********************/
00412 /**********************************************/
00413 
00414 /* <lalVerbatim file="SlopeLineFitFilterCP"> */
00415 void
00416 LALSlopeLineFitFilter( LALStatus                *status,
00417                        REAL4Vector*             output_data,
00418                        const REAL4Vector*       input_data,
00419                        const SLOPEFilterParams  fparams )
00420 /* </lalVerbatim> */
00421 {
00422   /******* DECLARE VARIABLES ***************************/
00423 
00424   REAL4              sumxt,sumx,meant,normalization;
00425   UINT4              i,j,datalength;
00426   REAL4*             datain;
00427   REAL4*             dataout;
00428   REAL4              calculated_slope,calculated_offset,sigmaa,sigmab,alpha; 
00429   REAL4              xnorma, xnormb;
00430   REAL4              nreal;
00431 
00432   /******* FUNCTION BODY ********************************/
00433 
00434   INITSTATUS( status, "LALSlopeLineFitFilter", SLOPEDETECTORFILTERC );
00435   /* only needed if you call other LAL functions within your code */
00436   /* ATTATCHSTATUSPTR (status); */
00437 
00438   if ( input_data == NULL ) {
00439     ABORT( status, SLOPEDETECTORFILTERH_EINPUTNULLP, 
00440            SLOPEDETECTORFILTERH_MSGEINPUTNULLP );
00441   }
00442   if ( output_data == NULL ) {
00443     ABORT( status, SLOPEDETECTORFILTERH_EOUTPUTNULLP, 
00444            SLOPEDETECTORFILTERH_MSGEOUTPUTNULLP );
00445   }
00446   if ( fparams.history == NULL ) {
00447     ABORT( status, SLOPEDETECTORFILTERH_EHISTNULLP, 
00448            SLOPEDETECTORFILTERH_MSGEHISTNULLP );
00449   }
00450   /* filter order needs to be at least two for slope detector filters */
00451   /* since you can't fit the slope off one data point */
00452   if ( (fparams.forder < 2) || 
00453        (fparams.forder > MAX_SLOPE_DETECTOR_FILTER_ORDER ) ) {
00454     ABORT( status, SLOPEDETECTORFILTERH_EINVFILTLEN, 
00455            SLOPEDETECTORFILTERH_MSGEINVFILTLEN );
00456   }
00457   if ( ( *(fparams.history_allocated) != 0) &&
00458        ( *(fparams.history_allocated) != 1) ) {
00459     ABORT( status, SLOPEDETECTORFILTERH_EHISTNULLP, 
00460            SLOPEDETECTORFILTERH_MSGEHISTNULLP );
00461   }
00462 
00463   datalength = input_data->length;
00464   datain = input_data->data;
00465   dataout = output_data->data;
00466   nreal = (REAL4)fparams.forder;
00467 
00468   if ( dataout == NULL ) {
00469     ABORT( status, SLOPEDETECTORFILTERH_EINPUTNULLP, 
00470            SLOPEDETECTORFILTERH_MSGEINPUTNULLP );
00471   }
00472   if ( datain == NULL ) {
00473     ABORT( status, SLOPEDETECTORFILTERH_EOUTPUTNULLP, 
00474            SLOPEDETECTORFILTERH_MSGEOUTPUTNULLP );
00475   }
00476   if ( datalength <= fparams.forder ) {
00477     ABORT( status, SLOPEDETECTORFILTERH_EDATATOOSHORT, 
00478            SLOPEDETECTORFILTERH_MSGEDATATOOSHORT );
00479   }
00480 
00481   /* add checks that the input series is valid data, etc */
00482 
00483   /******* DO ANALYSIS ************/
00484 
00485   /* run filter */  
00486 
00487   /* calculate overall normalization to get output in counts per second */
00488   normalization = 12 / (nreal * 
00489                         fparams.sampling_period_s *
00490                         (nreal * nreal - 1));
00491 
00492   meant = fparams.sampling_period_s * ( nreal - 1 ) / 2;
00493   
00494   /* loop over input data */
00495   for(i=0;i<(datalength-fparams.forder+1);++i) {
00496 
00497     /* compute sums needed for calculating best fit slope */ 
00498     sumx=0; sumxt=0;
00499     for(j=0;j<fparams.forder;++j) {
00500       sumx += datain[i+j];
00501       sumxt += j*datain[i+j];
00502     }
00503 
00504     /* calculate slope, needed for all filter outputs */
00505     calculated_slope
00506       = normalization * (sumxt - meant * sumx / fparams.sampling_period_s );
00507 
00508     switch( fparams.function_select ) {
00509     case FILTER_OUTPUT_SLOPE:
00510       /* the output is the slope */
00511       dataout[i] = calculated_slope;
00512       break;
00513     case FILTER_OUTPUT_OFFSET:
00514       /* the output is the offset */
00515       dataout[i] = sumx / nreal - calculated_slope * meant;
00516       break;
00517     case FILTER_OUTPUT_ALF:
00518       /* output data is a nonlinear function of slope and offset */
00519       sigmaa = (1 / fparams.sampling_period_s) * (REAL4)sqrt 
00520         ( 12 / (    (REAL8)nreal * ( (REAL8)nreal*(REAL8)nreal - 1) )    ) ;
00521       sigmab = (REAL4)sqrt ( (4 * (REAL8)nreal + 2) / 
00522                       ( (REAL8)nreal * ( (REAL8)nreal - 1 ) ) );
00523       calculated_offset = sumx / nreal - calculated_slope * meant;
00524       alpha = ( 0 - sqrt( 1.5 * ( (REAL8)nreal + 1) / ( 2*(REAL8)nreal + 1 ) ) );
00525       xnorma = calculated_slope / sigmaa;
00526       xnormb = calculated_offset / sigmab;
00527       dataout[i] = ( ( xnorma*xnorma + xnormb*xnormb - 2*alpha*xnorma*xnormb ) /
00528                      ( 1 - alpha * alpha ) );
00529       break;
00530     default:
00531       ABORT( status, SLOPEDETECTORFILTERH_EINVALIDACTION, 
00532              SLOPEDETECTORFILTERH_MSGEINVALIDACTION );
00533 
00534     }
00535   }
00536   
00537   /* set history buffer */
00538   for(i=0;i<(fparams.forder-1);++i) {
00539     fparams.history[i] = datain[datalength-(fparams.forder-1)+i];
00540   }
00541   *(fparams.history_allocated) = 1;
00542 
00543   /* DETATCHSTATUSPTR(status); */
00544   RETURN(status);
00545 
00546 }
00547 
00548 /*************************************************/
00549 /*** LALSlopeConvolutionFilter *******************/
00550 /*************************************************/
00551 
00552 /* <lalVerbatim file="SlopeConvolutionFilterCP"> */
00553 void
00554 LALSlopeConvolutionFilter( LALStatus                *status,
00555                            REAL4Vector*             output_data,
00556                            const REAL4Vector*       input_data,
00557                            const SLOPEFilterParams  fparams )
00558 /* </lalVerbatim> */
00559 {
00560   /******* DECLARE VARIABLES; for example: ************/
00561 
00562   REAL4* datain;
00563   REAL4* dataout;
00564   REAL4 nreal;
00565   UINT4 datalength,i,j;
00566 
00567   INITSTATUS( status, "LALSlopeConvolutionFilter", SLOPEDETECTORFILTERC );
00568   /* only needed if you call other LAL functions within your code */
00569   /* ATTATCHSTATUSPTR (status);                                   */
00570 
00571   switch( fparams.function_select ) {
00572   case FILTER_OUTPUT_TAPS_SET_GAUSSIAN:
00573     if ( ( fparams.forder < 1) || 
00574          ( fparams.forder > MAX_SLOPE_DETECTOR_FILTER_ORDER ) ) {
00575       ABORT( status, SLOPEDETECTORFILTERH_EINVFILTLEN, 
00576              SLOPEDETECTORFILTERH_MSGEINVFILTLEN );
00577     }
00578     if ( *(fparams.taps_set) != 0 ) {
00579       ABORT( status, SLOPEDETECTORFILTERH_EINVALIDTAPSBIT, 
00580              SLOPEDETECTORFILTERH_MSGEINVALIDTAPSBIT );
00581     }
00582     if ( fparams.tap == NULL ) {
00583       ABORT( status, SLOPEDETECTORFILTERH_ETAPSNULLP, 
00584              SLOPEDETECTORFILTERH_MSGETAPSNULLP );
00585     }
00586     if ( (fparams.waveform_offset < 0) || 
00587          (fparams.waveform_offset > 1) ) {
00588       ABORT( status, SLOPEDETECTORFILTERH_EBINOFFINVALID, 
00589              SLOPEDETECTORFILTERH_MSGEBINOFFINVALID );
00590     }
00591     /* create the filter taps */
00592     CreateGaussianTaps(fparams.forder,fparams.waveform_offset,fparams.tap);
00593     /* set the taps bit */
00594     *(fparams.taps_set) = 1;
00595     break;
00596   case FILTER_OUTPUT_TAPS_SET_SINE:
00597     if ( ( fparams.forder < 1 ) || 
00598          ( fparams.forder > MAX_SLOPE_DETECTOR_FILTER_ORDER ) ) {
00599       ABORT( status, SLOPEDETECTORFILTERH_EINVFILTLEN, 
00600              SLOPEDETECTORFILTERH_MSGEINVFILTLEN );
00601     }
00602     if ( *(fparams.taps_set) != 0 ) {
00603       ABORT( status, SLOPEDETECTORFILTERH_EINVALIDTAPSBIT, 
00604              SLOPEDETECTORFILTERH_MSGEINVALIDTAPSBIT );
00605     }
00606     if ( fparams.tap == NULL ) {
00607       ABORT( status, SLOPEDETECTORFILTERH_ETAPSNULLP, 
00608              SLOPEDETECTORFILTERH_MSGETAPSNULLP );
00609     }
00610     if ( (fparams.waveform_offset < 0) || 
00611          (fparams.waveform_offset > 1) ) {
00612       ABORT( status, SLOPEDETECTORFILTERH_EBINOFFINVALID, 
00613              SLOPEDETECTORFILTERH_MSGEBINOFFINVALID );
00614     }
00615     /* create the filter taps */
00616     CreatePeriodSineTaps(fparams.forder,fparams.waveform_offset,fparams.tap);
00617     /* set the taps bit */
00618     *(fparams.taps_set) = 1;
00619     break;
00620   case FILTER_OUTPUT_TAPS_SET_BOXCAR:
00621     if ( ( fparams.forder < 1 ) || 
00622          ( fparams.forder > MAX_SLOPE_DETECTOR_FILTER_ORDER ) ) {
00623       ABORT( status, SLOPEDETECTORFILTERH_EINVFILTLEN, 
00624              SLOPEDETECTORFILTERH_MSGEINVFILTLEN );
00625     }
00626     if ( *(fparams.taps_set) != 0 ) {
00627       ABORT( status, SLOPEDETECTORFILTERH_EINVALIDTAPSBIT, 
00628              SLOPEDETECTORFILTERH_MSGEINVALIDTAPSBIT );
00629     }
00630     if ( fparams.tap == NULL ) {
00631       ABORT( status, SLOPEDETECTORFILTERH_ETAPSNULLP, 
00632              SLOPEDETECTORFILTERH_MSGETAPSNULLP );
00633     }
00634     if ( (fparams.waveform_offset < 0) || 
00635          (fparams.waveform_offset > 1) ) {
00636       ABORT( status, SLOPEDETECTORFILTERH_EBINOFFINVALID, 
00637              SLOPEDETECTORFILTERH_MSGEBINOFFINVALID );
00638     }
00639     nreal = (REAL4)fparams.forder;
00640     /*printf("CODE: nreal = %f\n",nreal);*/
00641     /* create the filter taps */
00642     for(i=0;i<fparams.forder;++i) {
00643       *(fparams.tap + i) = 1/nreal;
00644       /*printf("CODE: tap %d is %f.\n",i,*(fparams.tap + i));*/
00645     }
00646     /* set the taps bit */
00647     *(fparams.taps_set) = 1;
00648     break;
00649   case FILTER_OUTPUT_TAPS_SET_USER:
00650     if ( input_data == NULL ) {
00651       ABORT( status, SLOPEDETECTORFILTERH_EINPUTNULLP, 
00652              SLOPEDETECTORFILTERH_MSGEINPUTNULLP );
00653     }
00654     datalength = input_data->length;
00655     datain = input_data->data;
00656     /* check that the data array is of a usable length */
00657     if ( ((INT4)datalength < 0) ||
00658          (datalength > MAX_SLOPE_DETECTOR_FILTER_ORDER) ) {
00659       ABORT( status, SLOPEDETECTORFILTERH_EINVFILTLEN, 
00660              SLOPEDETECTORFILTERH_MSGEINVFILTLEN );
00661     }
00662     /* check that the taps bit is set to zero */
00663     if ( *(fparams.taps_set) != 0 ) {
00664       ABORT( status, SLOPEDETECTORFILTERH_EINVALIDTAPSBIT, 
00665              SLOPEDETECTORFILTERH_MSGEINVALIDTAPSBIT );
00666     }
00667     /* check that the taps pointer is not null */
00668     if ( fparams.tap == NULL ) {
00669       ABORT( status, SLOPEDETECTORFILTERH_ETAPSNULLP, 
00670              SLOPEDETECTORFILTERH_MSGETAPSNULLP );
00671     }
00672     /* copy the input data array to the filter taps */
00673     for(i=0;i<datalength;++i) {
00674       *(fparams.tap + i)=datain[i];
00675     }
00676     /* set taps bit */
00677     *(fparams.taps_set) = 1;
00678     break;
00679   case FILTER_OUTPUT_CONVOLVE:
00680     if ( input_data == NULL ) {
00681       ABORT( status, SLOPEDETECTORFILTERH_EINPUTNULLP, 
00682              SLOPEDETECTORFILTERH_MSGEINPUTNULLP );
00683     }
00684     if ( output_data == NULL ) {
00685       ABORT( status, SLOPEDETECTORFILTERH_EOUTPUTNULLP, 
00686              SLOPEDETECTORFILTERH_MSGEOUTPUTNULLP );
00687     }
00688     datalength = input_data->length;
00689     datain = input_data->data;
00690     dataout = output_data->data;
00691     /* check that the taps bit is set to one */
00692     if ( *(fparams.taps_set) != 1 ) {
00693       ABORT( status, SLOPEDETECTORFILTERH_EINVALIDTAPSBIT, 
00694              SLOPEDETECTORFILTERH_MSGEINVALIDTAPSBIT );
00695     }
00696     /* check that the taps pointer is not null */
00697     if ( fparams.tap == NULL ) {
00698       ABORT( status, SLOPEDETECTORFILTERH_ETAPSNULLP, 
00699              SLOPEDETECTORFILTERH_MSGETAPSNULLP );
00700     }
00701     /* check that the history buffer pointer is not null */
00702     if ( (fparams.history) == NULL ) {
00703       ABORT( status, SLOPEDETECTORFILTERH_EHISTNULLP, 
00704              SLOPEDETECTORFILTERH_MSGEHISTNULLP );
00705     }
00706     /* convolve the data with the filter */
00707     for(i=0;i<(datalength-fparams.forder+1);++i) {
00708 
00709       /* calculate convolution for each input data point */
00710       dataout[i]=0;
00711       for(j=0;j<fparams.forder;++j) {
00712         dataout[i]+=fparams.tap[j]*datain[i+j];
00713       }
00714 
00715     }
00716     /* set the history buffer */
00717     for(i=0;i<(fparams.forder-1);++i) {
00718       fparams.history[i] = datain[datalength-(fparams.forder-1)+i];
00719     }
00720     *(fparams.history_allocated) = 1;
00721     break;
00722   default:
00723       ABORT( status, SLOPEDETECTORFILTERH_EINVALIDACTION, 
00724              SLOPEDETECTORFILTERH_MSGEINVALIDACTION );
00725   }
00726   /* DETATCHSTATUSPTR(status); */
00727   RETURN(status);
00728 
00729 }
00730 
00731 /******** functions used interally by the slope detector library *******/
00732 
00733 static void CreateGaussianTaps(UINT4 ntaps, REAL4 binoffset, REAL4* tap) {
00734   UINT4 i;
00735   REAL8 midbin,sigbins,offs;
00736   midbin = ((REAL8)ntaps - 1)/2;
00737   sigbins = midbin / (REAL8)GAUSSIAN_TAPS_NSIGMA_AT_EDGE;
00738   for(i=0;i<ntaps;++i) {
00739     offs = (REAL8)i;
00740     tap[i] = (REAL4)exp( - (offs - (midbin+(REAL8)binoffset)) * 
00741                          (offs - (midbin+(REAL8)binoffset)) /
00742                          (2 * sigbins * sigbins) );
00743   }
00744   return;
00745 }
00746 
00747 static void CreatePeriodSineTaps(UINT4 ntaps, REAL4 binoffset, REAL4* tap) {
00748   UINT4 i;
00749   REAL8 midbin/*,sigbins*/;
00750   REAL8 offs;
00751   midbin = ((REAL8)ntaps - 1)/2;
00752   for(i=0;i<ntaps;++i) {
00753     offs = (REAL8)i;
00754     tap[i] = (REAL4)sin( (offs - (midbin+(REAL8)binoffset))*SLOPE_PI/midbin );
00755   }
00756   return;
00757 }

Generated on Fri Sep 5 03:07:28 2008 for LAL by  doxygen 1.5.2