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 }
1.5.2