LAL  7.5.0.1-ec27e42
Convolution.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2007 Bernd Machenschalk, Kipp Cannon, Patrick Brady, Saikat Ray-Majumder
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 #include <complex.h>
21 #include <math.h>
22 #include <string.h>
23 #include <lal/AVFactories.h>
24 #include <lal/Calibration.h>
25 #include <lal/LALConstants.h>
26 #include <lal/TimeFreqFFT.h>
27 #include <lal/Units.h>
28 #include <lal/VectorOps.h>
29 #include <lal/Window.h>
30 #include <lal/FrequencySeries.h>
31 
32 /**
33  * \defgroup Convolution_c Module Convolution.c
34  * \ingroup lal_fft
35  * \brief Convolutions of time-series
36  */
37 
38 /** @{ */
39 
40 /**
41  *
42  * \brief Apply transfer function to time series
43  *
44  * This function returns the convolution of the time series with
45  * the frequency domain transfer function that has been supplied by
46  * the user. It zero pads the input data by a factor of two to
47  * alleviate wraparound from the FFT. This means that the transfer
48  * function must have
49  * \f[
50  * \texttt{deltaF} = 1.0 / ( 2.0 \times \texttt{strain->data->length}
51  * \times \texttt{strain->data->deltaT} )
52  * \f]
53  *
54  */
56  REAL4TimeSeries *strain,
57  COMPLEX8FrequencySeries *transfer
58  )
59 {
60  REAL4Vector *tmpWave=NULL;
61  COMPLEX8Vector *tmpFFTWave=NULL;
62  COMPLEX8FrequencySeries *tmpTransfer=NULL;
63  REAL4FFTPlan *fwdPlan=NULL, *invPlan=NULL;
64  UINT4 k;
65  UINT4 inTimeLength = 0;
66  UINT4 paddedTimeLength = 0;
67  const LALUnit countPerStrain = {0,{0,0,0,0,0,-1,1},{0,0,0,0,0,0,0}};
68  const CHAR *chname = "Temporary Transfer";
69 
70  if ( ! strain || ! transfer )
72  if ( ! strain->data || ! transfer->data )
74  if ( strain->deltaT <= 0.0 || transfer->deltaF <=0 )
76 
77  inTimeLength = strain->data->length;
78  paddedTimeLength = 2 * inTimeLength;
79 
80  tmpWave = XLALCreateREAL4Vector( paddedTimeLength );
81  if ( ! tmpWave )
83 
84  tmpFFTWave = XLALCreateCOMPLEX8Vector( inTimeLength + 1 );
85  if ( ! tmpFFTWave )
87 
88  fwdPlan = XLALCreateForwardREAL4FFTPlan( paddedTimeLength, 0 );
89  if ( ! fwdPlan )
91 
92  invPlan = XLALCreateReverseREAL4FFTPlan( paddedTimeLength, 0 );
93  if ( ! invPlan )
95 
96  /* copy the signal into zero padded data */
97  memset( tmpWave->data, 0, paddedTimeLength * sizeof(REAL4) );
98  for( k=0; k < inTimeLength; k++ )
99  {
100  tmpWave->data[k] = strain->data->data[k];
101  }
102 
103  /* Fourier transform the signal and multiply by transfer fn */
104  XLALREAL4ForwardFFT( tmpFFTWave, tmpWave, fwdPlan );
105 
106  /* make sure the transfer function has the right units and df */
107  tmpTransfer = XLALCreateCOMPLEX8FrequencySeries(chname,
108  &strain->epoch, 0.0, 1.0/(paddedTimeLength * strain->deltaT),
109  &countPerStrain, tmpFFTWave->length);
110  XLALResponseConvert( tmpTransfer, transfer );
111  XLALCCVectorMultiply( tmpFFTWave, tmpFFTWave, tmpTransfer->data );
112  XLALUnitMultiply( &strain->sampleUnits, &tmpTransfer->sampleUnits, &strain->sampleUnits);
114 
115  /* Now make sure the DC term has zero real and imaginary parts and
116  * that the nyquist term is real - (the nyquist term is the last
117  * term). This may in generaly not quite be true due to numerical
118  * rounding and accuracies so I will manually set these to the
119  * appropriate values */
120  tmpFFTWave->data[0] = 0.0;
121  tmpFFTWave->data[inTimeLength] = crealf(tmpFFTWave->data[inTimeLength]);
122 
123  memset( tmpWave->data, 0, 2*inTimeLength*sizeof(REAL4) );
124  XLALREAL4ReverseFFT( tmpWave, tmpFFTWave, invPlan );
125 
126  for( k=0; k < inTimeLength ; k++)
127  {
128  strain->data->data[k] = tmpWave->data[k] / (2 * inTimeLength);
129  }
130 
131  /* Make sure everything I allocated is deallocated below */
132  XLALDestroyREAL4Vector( tmpWave );
133  XLALDestroyCOMPLEX8Vector( tmpFFTWave );
134  XLALDestroyREAL4FFTPlan( fwdPlan );
135  XLALDestroyREAL4FFTPlan( invPlan );
136 
137  return strain;
138 }
139 
140 /**
141  * \brief SHOULD Convolve two time series, but doesn't
142  *
143  * This function does nothing yet
144  *
145  */
147  REAL4TimeSeries *strain,
148  REAL4TimeSeries *transfer
149  )
150 {
151  /*
152  REAL4Vector *tmpWave;
153  REAL4 normfac;
154  UINT4 k;
155  */
156 
157  if ( ! strain || ! transfer )
159  if ( ! strain->data || ! transfer->data )
161  if ( strain->deltaT <= 0.0 )
163  if ( transfer->data->length != strain->data->length )
165 
166  return strain;
167 }
168 
169 /** @} */
INT4 XLALResponseConvert(COMPLEX8FrequencySeries *output, COMPLEX8FrequencySeries *input)
UNDOCUMENTED.
REAL4TimeSeries * XLALRespFilt(REAL4TimeSeries *strain, COMPLEX8FrequencySeries *transfer)
Apply transfer function to time series.
Definition: Convolution.c:55
REAL4TimeSeries * XLALREAL4Convolution(REAL4TimeSeries *strain, REAL4TimeSeries *transfer)
SHOULD Convolve two time series, but doesn't.
Definition: Convolution.c:146
COMPLEX8FrequencySeries * XLALCreateCOMPLEX8FrequencySeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaF, const LALUnit *sampleUnits, size_t length)
void XLALDestroyCOMPLEX8FrequencySeries(COMPLEX8FrequencySeries *series)
char CHAR
One-byte signed integer, see Headers LAL(Atomic)Datatypes.h for more details.
uint32_t UINT4
Four-byte unsigned integer.
float REAL4
Single precision real floating-point number (4 bytes).
REAL4FFTPlan * XLALCreateReverseREAL4FFTPlan(UINT4 size, int measurelvl)
Returns a new REAL4FFTPlan for a reverse transform.
Definition: CudaRealFFT.c:130
REAL4FFTPlan * XLALCreateForwardREAL4FFTPlan(UINT4 size, int measurelvl)
Returns a new REAL4FFTPlan for a forward transform.
Definition: CudaRealFFT.c:120
void XLALDestroyREAL4FFTPlan(REAL4FFTPlan *plan)
Destroys a REAL4FFTPlan.
Definition: CudaRealFFT.c:140
int XLALREAL4ReverseFFT(REAL4Vector *output, const COMPLEX8Vector *input, const REAL4FFTPlan *plan)
Performs a reverse FFT of REAL4 data.
Definition: CudaRealFFT.c:198
int XLALREAL4ForwardFFT(COMPLEX8Vector *output, const REAL4Vector *input, const REAL4FFTPlan *plan)
Performs a forward FFT of REAL4 data.
Definition: CudaRealFFT.c:161
LALUnit * XLALUnitMultiply(LALUnit *output, const LALUnit *unit1, const LALUnit *unit2)
This function multiplies together the LALUnit structures *(input->unitOne) and *(input->unitTwo),...
Definition: UnitMultiply.c:64
void XLALDestroyREAL4Vector(REAL4Vector *vector)
REAL4Vector * XLALCreateREAL4Vector(UINT4 length)
COMPLEX8Vector * XLALCreateCOMPLEX8Vector(UINT4 length)
void XLALDestroyCOMPLEX8Vector(COMPLEX8Vector *vector)
COMPLEX8Vector * XLALCCVectorMultiply(COMPLEX8Vector *out, const COMPLEX8Vector *in1, const COMPLEX8Vector *in2)
#define XLAL_ERROR_NULL(...)
Macro to invoke a failure from a XLAL routine returning a pointer.
Definition: XLALError.h:713
@ XLAL_EBADLEN
Inconsistent or invalid length.
Definition: XLALError.h:419
@ XLAL_EFAULT
Invalid pointer.
Definition: XLALError.h:408
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_EINVAL
Invalid argument.
Definition: XLALError.h:409
See DATATYPE-FrequencySeries types for documentation.
Definition: LALDatatypes.h:899
COMPLEX8Sequence * data
Definition: LALDatatypes.h:905
Vector of type COMPLEX8, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:163
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:167
COMPLEX8 * data
Pointer to the data array.
Definition: LALDatatypes.h:168
This structure stores units in the mksA system (plus Kelvin, Strain, and ADC Count).
Definition: LALDatatypes.h:498
Time series of REAL4 data, see DATATYPE-TimeSeries types for more details.
Definition: LALDatatypes.h:570
REAL4Sequence * data
The sequence of sampled data.
Definition: LALDatatypes.h:576
LALUnit sampleUnits
The physical units of the quantity being sampled.
Definition: LALDatatypes.h:575
REAL8 deltaT
The time step between samples of the time series in seconds.
Definition: LALDatatypes.h:573
LIGOTimeGPS epoch
The start time of the time series.
Definition: LALDatatypes.h:572
Vector of type REAL4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:145
REAL4 * data
Pointer to the data array.
Definition: LALDatatypes.h:150
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:149