LALSimulation  5.4.0.1-fe68b98
LALSimInspiralWaveformTaper.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2007 David McKechan, Thomas Cokelaer, Drew Keppel
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19 
20 
21 #include <LALSimInspiral.h>
22 #include <lal/LALError.h>
23 #include <stdio.h>
24 #include <math.h>
25 
26 /* hard-coded resampling filter length, see LALSimulation.c
27  * the filter is 19 samples long, resampling can produce ringing
28  * up to 9 samples away from an abrupt jump
29  */
31 
32 /**
33  * \addtogroup LALSimInspiralWaveformTaper_c
34  * \author McKechan D J A
35  *
36  * \brief The code \c XLALInspiralREAL4WaveformTaper() and
37  * \c XLALInspiralREAL8WaveTaper() impose a smooth time tapering at the
38  * beginning and/or the end of REAL4 or REAL8 waveforms in the time domain.
39  *
40  * They take either a \c REAL4Vector or a \c REAL8Vector and search for the
41  * beginning and end points of the signal, in case there are null data points
42  * at either end. They then taper the waveform from the ends to the second
43  * maxima from each end in the waveform, according to formula 3.35 of
44  * <tt>gr-qc/0001023</tt>.
45  *
46  * If the waveform does has less than 4 maxima, such that it cannot be tapered
47  * from the each end to the second peak then the waveform is tapered from the
48  * ends to the centre of the instead.
49  *
50  * The bookends option is an \c LALSimInspiralApplyTaper enumerator and allows the
51  * user to specify whether just the start, just the end or both the start and
52  * end of the signal are tapered. These options are #LAL_SIM_INSPIRAL_TAPER_START,
53  * #LAL_SIM_INSPIRAL_TAPER_END and #LAL_SIM_INSPIRAL_TAPER_STARTEND.
54  *
55  * ### Prototypes ###
56  *
57  * <tt>XLALInspiralREAL4WaveformTaper()</tt>
58  * <tt>XLALInspiralREAL8WaveformTaper()</tt>
59  *
60  * ### Description ###
61  *
62  *
63  * ### Uses ###
64  *
65  *
66  * ### Notes ###
67  *
68  * \{
69  */
70 
72  REAL4Vector *signalvec, /**< pointer to waveform vector */
73  LALSimInspiralApplyTaper bookends /**< taper type enumerator */
74  )
75 {
76  UINT4 i, start=0, end=0, mid, n=0; /* indices */
77  UINT4 flag, safe = 1;
78  UINT4 length;
79  REAL4 z, sigma;
80  REAL4 realN, realI; /* REAL4 values of n & i used for the calculations */
81 
82  if ( !signalvec )
84 
85  if ( !signalvec->data )
87 
88  /* Check we have chosen a valid tapering method */
89  if ( (UINT4) bookends >= (UINT4) LAL_SIM_INSPIRAL_TAPER_NUM_OPTS )
91 
92  length = signalvec->length;
93 
94  if( bookends == LAL_SIM_INSPIRAL_TAPER_NONE )
95  {
96  XLALPrintWarning( "No taper specified; not tapering.\n" );
97  return XLAL_SUCCESS;
98  }
99 
100  /* Search for start and end of signal */
101  flag = 0;
102  i = 0;
103  while( flag == 0 && i < length )
104  {
105  if( signalvec->data[i] != 0. )
106  {
107  start = i;
108  flag = 1;
109  }
110  i++;
111  }
112  if ( flag == 0 )
113  {
114  XLALPrintWarning( "No signal found in the vector. Cannot taper.\n" );
115  return XLAL_SUCCESS;
116  }
117 
118  flag = 0;
119  i = length - 1;
120  while( flag == 0 )
121  {
122  if( signalvec->data[i] != 0. )
123  {
124  end = i;
125  flag = 1;
126  }
127  i--;
128  }
129 
130  /* Check we have more than 2 data points */
131  if( (end - start) <= 1 )
132  {
133  XLALPrintWarning( "Data less than 3 points, cannot taper!\n" );
134  safe = 0;
135  }
136 
137  if( safe == 1 )
138  {
139  /* Calculate middle point in case of short waveform */
140  mid = (start+end)/2;
141 
142  /* If requested search for second peak from start and taper */
143  if( bookends != LAL_SIM_INSPIRAL_TAPER_END )
144  {
145  flag = 0;
146  i = start+1;
147  while( flag < 2 && i != mid )
148  {
149  if( fabs(signalvec->data[i]) >= fabs(signalvec->data[i-1]) &&
150  fabs(signalvec->data[i]) >= fabs(signalvec->data[i+1]) )
151  {
152  if( fabs(signalvec->data[i]) == fabs(signalvec->data[i+1]) )
153  i++;
154  /* only count local extrema more than 19 samples in */
155  if ( i-start > LALSIMULATION_RINGING_EXTENT )
156  flag++;
157  n = i - start;
158  }
159  i++;
160  }
161 
162  /* Have we reached the middle without finding 2 peaks? */
163  if( flag < 2 )
164  n = mid - start;
165 
166  /* Taper to that point */
167  realN = (REAL4)(n);
168  signalvec->data[start] = 0.0;
169  for(i=start+1; i < start + n - 1; i++)
170  {
171  realI = (REAL4)(i - start);
172  z = (realN - 1.0)/realI + (realN - 1.0)/(realI - (realN - 1.0));
173  sigma = 1.0/(exp(z) + 1.0);
174  signalvec->data[i] = signalvec->data[i]*sigma;
175  }
176  }
177 
178  /* If requested search for second peak from end */
179  if( bookends == LAL_SIM_INSPIRAL_TAPER_END || bookends == LAL_SIM_INSPIRAL_TAPER_STARTEND )
180  {
181  i = end - 1;
182  flag = 0;
183  while( flag < 2 && i != mid )
184  {
185  if( fabs(signalvec->data[i]) >= fabs(signalvec->data[i+1]) &&
186  fabs(signalvec->data[i]) >= fabs(signalvec->data[i-1]) )
187  {
188  if( fabs(signalvec->data[i]) == fabs(signalvec->data[i-1]) )
189  i--;
190  /* only count local extrema more than 19 samples in */
192  flag++;
193  n = end - i;
194  }
195  i--;
196  }
197 
198  /* Have we reached the middle without finding 2 peaks? */
199  if( flag < 2 )
200  {
201  n = end - mid;
202  }
203 
204  /* Taper to that point */
205  realN = (REAL4)(n);
206  signalvec->data[end] = 0.0;
207  for(i=end-1; i > end-n+1; i--)
208  {
209  realI = (REAL4)(end - i);
210  z = (realN - 1.0)/realI + (realN - 1.0)/(realI - (realN-1.0));
211  sigma = 1.0/(exp(z) + 1.0);
212  signalvec->data[i] = signalvec->data[i]*sigma;
213  }
214  }
215  }
216 
217  return XLAL_SUCCESS;
218 }
219 
221  REAL8Vector *signalvec, /**< pointer to waveform vector */
222  LALSimInspiralApplyTaper bookends /**< taper type enumerator */
223  )
224 {
225  UINT4 i, start=0, end=0, mid, n=0; /* indices */
226  UINT4 flag, safe = 1;
227  UINT4 length;
228  REAL8 z, sigma;
229  REAL8 realN, realI; /* REAL4 values of n & i used for the calculations */
230 
231  if ( !signalvec )
233 
234  if ( !signalvec->data )
236 
237  /* Check we have chosen a valid tapering method */
238  if ( (UINT4) bookends >= (UINT4) LAL_SIM_INSPIRAL_TAPER_NUM_OPTS )
240 
241  length = signalvec->length;
242 
243  if( bookends == LAL_SIM_INSPIRAL_TAPER_NONE )
244  {
245  XLALPrintWarning( "No taper specified; not tapering.\n" );
246  return XLAL_SUCCESS;
247  }
248 
249  /* Search for start and end of signal */
250  flag = 0;
251  i = 0;
252  while( flag == 0 && i < length )
253  {
254  if( signalvec->data[i] != 0. )
255  {
256  start = i;
257  flag = 1;
258  }
259  i++;
260  }
261  if ( flag == 0 )
262  {
263  XLALPrintWarning( "No signal found in the vector. Cannot taper.\n" );
264  return XLAL_SUCCESS;
265  }
266 
267  flag = 0;
268  i = length - 1;
269  while( flag == 0 )
270  {
271  if( signalvec->data[i] != 0. )
272  {
273  end = i;
274  flag = 1;
275  }
276  i--;
277  }
278 
279  /* Check we have more than 2 data points */
280  if( (end - start) <= 1 )
281  {
282  XLALPrintWarning( "Data less than 3 points, cannot taper!\n" );
283  safe = 0;
284  }
285 
286  if( safe == 1 )
287  {
288  /* Calculate middle point in case of short waveform */
289  mid = (start+end)/2;
290 
291  /* If requested search for second peak from start and taper */
292  if( bookends != LAL_SIM_INSPIRAL_TAPER_END )
293  {
294  flag = 0;
295  i = start+1;
296  while( flag < 2 && i != mid )
297  {
298  if( fabs(signalvec->data[i]) >= fabs(signalvec->data[i-1]) &&
299  fabs(signalvec->data[i]) >= fabs(signalvec->data[i+1]) )
300  {
301  if( fabs(signalvec->data[i]) == fabs(signalvec->data[i+1]) )
302  i++;
303  /* only count local extrema more than 19 samples in */
304  if ( i-start > LALSIMULATION_RINGING_EXTENT )
305  flag++;
306  n = i - start;
307  }
308  i++;
309  }
310 
311  /* Have we reached the middle without finding 2 peaks? */
312  if( flag < 2 )
313  n = mid - start;
314 
315  /* Taper to that point */
316  realN = (REAL8)(n);
317  signalvec->data[start] = 0.0;
318  for(i=start+1; i < start + n - 1; i++)
319  {
320  realI = (REAL8)(i - start);
321  z = (realN - 1.0)/realI + (realN - 1.0)/(realI - (realN - 1.0));
322  sigma = 1.0/(exp(z) + 1.0);
323  signalvec->data[i] = signalvec->data[i]*sigma;
324  }
325  }
326 
327  /* If requested search for second peak from end */
328  if( bookends == LAL_SIM_INSPIRAL_TAPER_END || bookends == LAL_SIM_INSPIRAL_TAPER_STARTEND )
329  {
330  i = end - 1;
331  flag = 0;
332  while( flag < 2 && i != mid )
333  {
334  if( fabs(signalvec->data[i]) >= fabs(signalvec->data[i+1]) &&
335  fabs(signalvec->data[i]) >= fabs(signalvec->data[i-1]) )
336  {
337  if( fabs(signalvec->data[i]) == fabs(signalvec->data[i-1]) )
338  i--;
339  /* only count local extrema more than 19 samples in */
341  flag++;
342  n = end - i;
343  }
344  i--;
345  }
346 
347  /* Have we reached the middle without finding 2 peaks? */
348  if( flag < 2 )
349  {
350  n = end - mid;
351  }
352 
353  /* Taper to that point */
354  realN = (REAL8)(n);
355  signalvec->data[end] = 0.0;
356  for(i=end-1; i > end-n+1; i--)
357  {
358  realI = (REAL8)(end - i);
359  z = (realN - 1.0)/realI + (realN - 1.0)/(realI - (realN-1.0));
360  sigma = 1.0/(exp(z) + 1.0);
361  signalvec->data[i] = signalvec->data[i]*sigma;
362  }
363  }
364  }
365 
366  return XLAL_SUCCESS;
367 }
368 
369 /** \} */
static double sigma(const double a, const double b, const sysq *system)
Internal function that computes the spin-spin couplings.
const UINT4 LALSIMULATION_RINGING_EXTENT
double i
Definition: bh_ringdown.c:118
double REAL8
uint32_t UINT4
float REAL4
LALSimInspiralApplyTaper
Enumeration to specify the tapering method to apply to the waveform.
@ LAL_SIM_INSPIRAL_TAPER_STARTEND
Taper the start and the end of the waveform.
@ LAL_SIM_INSPIRAL_TAPER_NUM_OPTS
Number of elements in enum, useful for checking bounds.
@ LAL_SIM_INSPIRAL_TAPER_END
Taper the end of the waveform.
@ LAL_SIM_INSPIRAL_TAPER_NONE
No tapering.
int XLALSimInspiralREAL8WaveTaper(REAL8Vector *signalvec, LALSimInspiralApplyTaper bookends)
int XLALSimInspiralREAL4WaveTaper(REAL4Vector *signalvec, LALSimInspiralApplyTaper bookends)
#define XLAL_ERROR(...)
int int XLALPrintWarning(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EINVAL
end
REAL4 * data
REAL8 * data