LALPulsar  6.1.0.1-89842e6
FstatisticTools.c
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Maximillian Bensch, Reinhard Prix
3 // Copyright (C) 2014 Reinhard Prix
4 // Copyright (C) 2012, 2013, 2014 Karl Wette
5 // Copyright (C) 2007 Chris Messenger
6 // Copyright (C) 2006 John T. Whelan, Badri Krishnan
7 // Copyright (C) 2005, 2006, 2007, 2010 Reinhard Prix
8 //
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with with program; see the file COPYING. If not, write to the
21 // Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 // MA 02110-1301 USA
23 //
24 
25 // ---------- includes ----------
26 #include <gsl/gsl_vector.h>
27 #include <gsl/gsl_matrix.h>
28 #include <gsl/gsl_blas.h>
29 #include <gsl/gsl_permutation.h>
30 #include <gsl/gsl_linalg.h>
31 
32 #include <lal/ExtrapolatePulsarSpins.h>
33 
34 #include <lal/FstatisticTools.h>
35 
36 // ---------- local macro definitions ----------
37 #define SQ(x) ( (x) * (x) )
38 #define MYSIGN(x) ( ((x) < 0) ? (-1.0):(+1.0) )
39 
40 
41 // ==================== function definitions ====================
42 
43 /// \addtogroup FstatisticTools_h
44 /// @{
45 
46 ///
47 /// Estimate the amplitude parameters of a pulsar CW signal, given its phase parameters,
48 /// constituent parts of the \f$ \mathcal{F} \f$ -statistic, and antenna pattern matrix.
49 ///
50 /// \note Parameter-estimation based on large parts on Yousuke's notes and implemention (in CFSv1),
51 /// extended for error-estimation.
52 ///
53 int
54 XLALEstimatePulsarAmplitudeParams( PulsarCandidate *pulsarParams, ///< [in,out] Pulsar candidate parameters.
55  const LIGOTimeGPS *FaFb_refTime, ///< [in] Reference time of \f$ F_a \f$ and \f$ F_b \f$ , may differ from pulsar candidate reference time.
56  const COMPLEX8 Fa, ///< [in] Complex \f$ \mathcal{F} \f$ -statistic amplitude \f$ F_a \f$ .
57  const COMPLEX8 Fb, ///< [in] Complex \f$ \mathcal{F} \f$ -statistic amplitude \f$ F_b \f$ .
58  const AntennaPatternMatrix *Mmunu ///< [in] Antenna pattern matrix \f$ M_{\mu\nu} \f$ .
59  )
60 {
61 
62  REAL8 A1h, A2h, A3h, A4h;
63  REAL8 Ad, Bd, Cd, Dd, Ed;
64  REAL8 normAmu;
65  REAL8 A1check, A2check, A3check, A4check;
66 
67  REAL8 Asq, Da, disc;
68  REAL8 aPlus, aCross;
69  REAL8 Ap2, Ac2;
70  REAL8 beta;
71  REAL8 phi0, psi;
72  REAL8 b1, b2, b3;
73 
74  REAL8 cosphi0, sinphi0, cos2psi, sin2psi;
75 
76  REAL8 tolerance = LAL_REAL4_EPS;
77 
78  gsl_vector *x_mu, *A_Mu;
79  gsl_matrix *M_Mu_Nu;
80  gsl_matrix *Jh_Mu_nu;
81  gsl_permutation *permh;
82  gsl_matrix *tmp, *tmp2;
83  int signum;
84 
85  XLAL_CHECK( pulsarParams != NULL, XLAL_EINVAL );
86  XLAL_CHECK( FaFb_refTime != NULL, XLAL_EINVAL );
87  XLAL_CHECK( isfinite( creal( Fa ) ) && isfinite( cimag( Fb ) ), XLAL_EDOM,
88  "Fa = (%g, %g) is not finite", creal( Fa ), cimag( Fa ) );
89  XLAL_CHECK( isfinite( creal( Fb ) ) && isfinite( cimag( Fb ) ), XLAL_EDOM,
90  "Fb = (%g, %g) is not finite", creal( Fb ), cimag( Fb ) );
91  XLAL_CHECK( Mmunu != NULL, XLAL_EINVAL );
92 
93  Ad = Mmunu->Ad;
94  Bd = Mmunu->Bd;
95  Cd = Mmunu->Cd;
96  Ed = Mmunu->Ed;
97  Dd = Ad * Bd - Cd * Cd - Ed * Ed;
98 
99  normAmu = 2.0 / sqrt( 2.0 * Mmunu->Sinv_Tsft ); // generally *very* small!!
100 
101  // ----- GSL memory allocation -----
102  XLAL_CHECK( ( x_mu = gsl_vector_calloc( 4 ) ) != NULL, XLAL_ENOMEM );
103  XLAL_CHECK( ( A_Mu = gsl_vector_calloc( 4 ) ) != NULL, XLAL_ENOMEM );
104  XLAL_CHECK( ( M_Mu_Nu = gsl_matrix_calloc( 4, 4 ) ) != NULL, XLAL_ENOMEM );
105  XLAL_CHECK( ( Jh_Mu_nu = gsl_matrix_calloc( 4, 4 ) ) != NULL, XLAL_ENOMEM );
106 
107  XLAL_CHECK( ( permh = gsl_permutation_calloc( 4 ) ) != NULL, XLAL_ENOMEM );
108  XLAL_CHECK( ( tmp = gsl_matrix_calloc( 4, 4 ) ) != NULL, XLAL_ENOMEM );
109  XLAL_CHECK( ( tmp2 = gsl_matrix_calloc( 4, 4 ) ) != NULL, XLAL_ENOMEM );
110 
111  // ----- fill vector x_mu
112  gsl_vector_set( x_mu, 0, creal( Fa ) ); // x_1
113  gsl_vector_set( x_mu, 1, creal( Fb ) ); // x_2
114  gsl_vector_set( x_mu, 2, - cimag( Fa ) ); // x_3
115  gsl_vector_set( x_mu, 3, - cimag( Fb ) ); // x_4
116 
117  // ----- fill matrix M^{mu,nu} [symmetric: use UPPER HALF ONLY!!]
118  gsl_matrix_set( M_Mu_Nu, 0, 0, Bd / Dd );
119  gsl_matrix_set( M_Mu_Nu, 1, 1, Ad / Dd );
120  gsl_matrix_set( M_Mu_Nu, 0, 1, - Cd / Dd );
121 
122  gsl_matrix_set( M_Mu_Nu, 0, 3, - Ed / Dd );
123  gsl_matrix_set( M_Mu_Nu, 1, 2, Ed / Dd );
124 
125  gsl_matrix_set( M_Mu_Nu, 2, 2, Bd / Dd );
126  gsl_matrix_set( M_Mu_Nu, 3, 3, Ad / Dd );
127  gsl_matrix_set( M_Mu_Nu, 2, 3, - Cd / Dd );
128 
129  // get (un-normalized) MLE's for amplitudes A^mu = M^{mu,nu} x_nu
130 
131  /* GSL-doc: int gsl_blas_dsymv (CBLAS_UPLO_t Uplo, double alpha, const gsl_matrix * A,
132  * const gsl_vector * x, double beta, gsl_vector * y )
133  *
134  * compute the matrix-vector product and sum: y = alpha A x + beta y
135  * for the symmetric matrix A. Since the matrix A is symmetric only its
136  * upper half or lower half need to be stored. When Uplo is CblasUpper
137  * then the upper triangle and diagonal of A are used, and when Uplo
138  * is CblasLower then the lower triangle and diagonal of A are used.
139  */
140  XLAL_CHECK( gsl_blas_dsymv( CblasUpper, 1.0, M_Mu_Nu, x_mu, 0.0, A_Mu ) == 0, XLAL_EERR );
141 
142  A1h = gsl_vector_get( A_Mu, 0 );
143  A2h = gsl_vector_get( A_Mu, 1 );
144  A3h = gsl_vector_get( A_Mu, 2 );
145  A4h = gsl_vector_get( A_Mu, 3 );
146 
147  Asq = SQ( A1h ) + SQ( A2h ) + SQ( A3h ) + SQ( A4h );
148  Da = A1h * A4h - A2h * A3h;
149  disc = sqrt( SQ( Asq ) - 4.0 * SQ( Da ) );
150 
151  Ap2 = 0.5 * ( Asq + disc );
152  aPlus = sqrt( Ap2 ); // not yet normalized
153 
154  Ac2 = 0.5 * ( Asq - disc );
155  aCross = sqrt( Ac2 );
156  aCross *= MYSIGN( Da ); // not yet normalized
157 
158  beta = aCross / aPlus;
159 
160  b1 = A4h - beta * A1h;
161  b2 = A3h + beta * A2h;
162  b3 = - A1h + beta * A4h ;
163 
164  psi = 0.5 * atan( b1 / b2 ); // in [-pi/4,pi/4] (gauge used also by TDS)
165  phi0 = atan( b2 / b3 ); // in [-pi/2,pi/2]
166 
167  // Fix remaining sign-ambiguity by checking sign of reconstructed A1
168  A1check = aPlus * cos( phi0 ) * cos( 2.0 * psi ) - aCross * sin( phi0 ) * sin( 2 * psi );
169  if ( A1check * A1h < 0 ) {
170  phi0 += LAL_PI;
171  }
172 
173  cosphi0 = cos( phi0 );
174  sinphi0 = sin( phi0 );
175  cos2psi = cos( 2 * psi );
176  sin2psi = sin( 2 * psi );
177 
178  // check numerical consistency of estimated Amu and reconstructed
179  A1check = aPlus * cosphi0 * cos2psi - aCross * sinphi0 * sin2psi;
180  A2check = aPlus * cosphi0 * sin2psi + aCross * sinphi0 * cos2psi;
181  A3check = - aPlus * sinphi0 * cos2psi - aCross * cosphi0 * sin2psi;
182  A4check = - aPlus * sinphi0 * sin2psi + aCross * cosphi0 * cos2psi;
183 
184  if ( ( fabs( ( A1check - A1h ) / A1h ) > tolerance ) ||
185  ( fabs( ( A2check - A2h ) / A2h ) > tolerance ) ||
186  ( fabs( ( A3check - A3h ) / A3h ) > tolerance ) ||
187  ( fabs( ( A4check - A4h ) / A4h ) > tolerance ) ) {
188  if ( lalDebugLevel )
189  XLALPrintError( "WARNING %s(): Difference between estimated and reconstructed Amu exceeds tolerance of %g\n",
190  __func__, tolerance );
191  }
192 
193  // ========== Estimate the errors ==========
194 
195  // ----- compute derivatives \partial A^\mu / \partial A^\nu, where
196  // we consider the output-variables A^\nu = (aPlus, aCross, phi0, psi)
197  // where aPlus = 0.5 * h0 * (1 + cosi^2) and aCross = h0 * cosi
198  {
199  // Eqn (114) in T0900149 v5
200  // ----- A1 = aPlus * cosphi0 * cos2psi - aCross * sinphi0 * sin2psi; -----
201  gsl_matrix_set( Jh_Mu_nu, 0, 0, cosphi0 * cos2psi ); /* dA1/daPlus */
202  gsl_matrix_set( Jh_Mu_nu, 0, 1, - sinphi0 * sin2psi ); /* dA1/daCross */
203  gsl_matrix_set( Jh_Mu_nu, 0, 2, A3h ); /* dA1/dphi0 */
204  gsl_matrix_set( Jh_Mu_nu, 0, 3, - 2.0 * A2h ); /* dA1/dpsi */
205 
206  // ----- A2 = aPlus * cosphi0 * sin2psi + aCross * sinphi0 * cos2psi; -----
207  gsl_matrix_set( Jh_Mu_nu, 1, 0, cosphi0 * sin2psi ); /* dA2/daPlus */
208  gsl_matrix_set( Jh_Mu_nu, 1, 1, sinphi0 * cos2psi ); /* dA2/daCross */
209  gsl_matrix_set( Jh_Mu_nu, 1, 2, A4h ); /* dA2/dphi0 */
210  gsl_matrix_set( Jh_Mu_nu, 1, 3, 2.0 * A1h ); /* dA2/dpsi */
211 
212  // ----- A3 = - aPlus * sinphi0 * cos2psi - aCross * cosphi0 * sin2psi; -----
213  gsl_matrix_set( Jh_Mu_nu, 2, 0, - sinphi0 * cos2psi ); /* dA3/daPlus */
214  gsl_matrix_set( Jh_Mu_nu, 2, 1, - cosphi0 * sin2psi ); /* dA3/daCross */
215  gsl_matrix_set( Jh_Mu_nu, 2, 2, - A1h ); /* dA3/dphi0 */
216  gsl_matrix_set( Jh_Mu_nu, 2, 3, - 2.0 * A4h ); /* dA3/dpsi */
217 
218  // ----- A4 = - aPlus * sinphi0 * sin2psi + aCross * cosphi0 * cos2psi; -----
219  gsl_matrix_set( Jh_Mu_nu, 3, 0, - sinphi0 * sin2psi ); /* dA4/daPlus */
220  gsl_matrix_set( Jh_Mu_nu, 3, 1, cosphi0 * cos2psi ); /* dA4/daCross */
221  gsl_matrix_set( Jh_Mu_nu, 3, 2, - A2h ); /* dA4/dphi0 */
222  gsl_matrix_set( Jh_Mu_nu, 3, 3, 2.0 * A3h ); /* dA4/dpsi */
223  }
224 
225  // ----- compute inverse matrices Jh^{-1} by LU-decomposition -----
226  XLAL_CHECK( gsl_linalg_LU_decomp( Jh_Mu_nu, permh, &signum ) == 0, XLAL_EERR );
227 
228  // inverse matrix
229  XLAL_CHECK( gsl_linalg_LU_invert( Jh_Mu_nu, permh, tmp ) == 0, XLAL_EERR );
230  gsl_matrix_memcpy( Jh_Mu_nu, tmp );
231 
232  // ----- compute Jh^-1 . Minv . (Jh^-1)^T -----
233 
234  /* GSL-doc: gsl_blas_dgemm (CBLAS_TRANSPOSE_t TransA, CBLAS_TRANSPOSE_t TransB, double alpha,
235  * const gsl_matrix *A, const gsl_matrix *B, double beta, gsl_matrix *C)
236  * These functions compute the matrix-matrix product and sum
237  * C = \alpha op(A) op(B) + \beta C
238  * where op(A) = A, A^T, A^H for TransA = CblasNoTrans, CblasTrans, CblasConjTrans
239  * and similarly for the parameter TransB.
240  */
241 
242  // first tmp = Minv . (Jh^-1)^T
243  XLAL_CHECK( gsl_blas_dgemm( CblasNoTrans, CblasTrans, 1.0, M_Mu_Nu, Jh_Mu_nu, 0.0, tmp ) == 0, XLAL_EERR );
244  // then J^-1 . tmp , store result in tmp2
245  XLAL_CHECK( gsl_blas_dgemm( CblasNoTrans, CblasNoTrans, 1.0, Jh_Mu_nu, tmp, 0.0, tmp2 ) == 0, XLAL_EERR );
246  gsl_matrix_memcpy( Jh_Mu_nu, tmp2 );
247 
248  // ===== debug-output resulting matrices =====
249  // propagate initial-phase from Fstat-reference-time to refTime of Doppler-params
250  // XLALExtrapolatePulsarPhase() guarantees propagated phi0 is in [0, 2*pi]
251  const REAL8 dtau = XLALGPSDiff( &pulsarParams->Doppler.refTime, FaFb_refTime );
253 
254  // fill candidate-struct with the obtained signal-parameters and error-estimations
255  pulsarParams->Amp.aPlus = normAmu * aPlus;
256  pulsarParams->Amp.aCross = normAmu * aCross;
257  pulsarParams->Amp.phi0 = phi0;
258  pulsarParams->Amp.psi = psi;
259 
260  // read out principal estimation-errors from diagonal elements of inverse Fisher-matrix
261  pulsarParams->dAmp.aPlus = normAmu * sqrt( gsl_matrix_get( Jh_Mu_nu, 0, 0 ) );
262  pulsarParams->dAmp.aCross = normAmu * sqrt( gsl_matrix_get( Jh_Mu_nu, 1, 1 ) );
263  pulsarParams->dAmp.phi0 = sqrt( gsl_matrix_get( Jh_Mu_nu, 2, 2 ) );
264  pulsarParams->dAmp.psi = sqrt( gsl_matrix_get( Jh_Mu_nu, 3, 3 ) );
265  // return also the full Amplitude-Fisher matrix: invert Jh_Mu_nu
266  XLAL_CHECK( gsl_linalg_LU_decomp( Jh_Mu_nu, permh, &signum ) == 0, XLAL_EERR );
267  XLAL_CHECK( gsl_linalg_LU_invert( Jh_Mu_nu, permh, tmp ) == 0, XLAL_EERR );
268  pulsarParams->AmpFisherMatrix = tmp;
269 
270  // ----- free GSL memory -----
271  gsl_vector_free( x_mu );
272  gsl_vector_free( A_Mu );
273  gsl_matrix_free( M_Mu_Nu );
274  gsl_matrix_free( Jh_Mu_nu );
275  gsl_permutation_free( permh );
276  gsl_matrix_free( tmp2 );
277 
278  return XLAL_SUCCESS;
279 
280 } // XLALEstimatePulsarAmplitudeParams()
281 
282 ///
283 /// Convert amplitude params from 'physical' coordinates \f$ (h_0, \cos\iota, \psi, \phi_0) \f$ into
284 /// 'canonical' coordinates \f$ A^\mu = (A_1, A_2, A_3, A_4) \f$ . The equations can be found in
285 /// \cite JKS98 or \cite Prix07 Eq.(2).
286 ///
287 int
288 XLALAmplitudeParams2Vect( PulsarAmplitudeVect A_Mu, ///< [out] Canonical amplitude coordinates \f$ A^\mu = (A_1, A_2, A_3, A_4) \f$ .
289  const PulsarAmplitudeParams Amp ///< [in] Physical amplitude params \f$ (h_0, \cos\iota, \psi, \phi_0) \f$ .
290  )
291 {
292 
293  REAL8 aPlus = Amp.aPlus;
294  REAL8 aCross = Amp.aCross;
295  REAL8 cos2psi = cos( 2.0 * Amp.psi );
296  REAL8 sin2psi = sin( 2.0 * Amp.psi );
297  REAL8 cosphi0 = cos( Amp.phi0 );
298  REAL8 sinphi0 = sin( Amp.phi0 );
299 
300  XLAL_CHECK( A_Mu != NULL, XLAL_EINVAL );
301 
302  A_Mu[0] = aPlus * cos2psi * cosphi0 - aCross * sin2psi * sinphi0;
303  A_Mu[1] = aPlus * sin2psi * cosphi0 + aCross * cos2psi * sinphi0;
304  A_Mu[2] = -aPlus * cos2psi * sinphi0 - aCross * sin2psi * cosphi0;
305  A_Mu[3] = -aPlus * sin2psi * sinphi0 + aCross * cos2psi * cosphi0;
306 
307  return XLAL_SUCCESS;
308 
309 } // XLALAmplitudeParams2Vect()
310 
311 ///
312 /// Compute amplitude params \f$ (h_0, \cos\iota, \psi, \phi_0) \f$ from amplitude-vector \f$ A^\mu = (A_1, A_2, A_3, A_4) \f$ .
313 /// Adapted from algorithm in XLALEstimatePulsarAmplitudeParams().
314 ///
315 int
316 XLALAmplitudeVect2Params( PulsarAmplitudeParams *Amp, ///< [out] Physical amplitude params \f$ (h_0, \cos\iota, \psi, \phi_0) \f$ .
317  const PulsarAmplitudeVect A_Mu ///< [in] Canonical amplitude coordinates \f$ A^\mu = (A_1, A_2, A_3, A_4) \f$ .
318  )
319 {
320 
321  REAL8 psiRet, phi0Ret;
322 
323  REAL8 A1, A2, A3, A4, Asq, Da, disc;
324  REAL8 Ap2, Ac2, aPlus, aCross;
325  REAL8 beta, b1, b2, b3;
326 
327  XLAL_CHECK( A_Mu != NULL, XLAL_EINVAL );
328  XLAL_CHECK( Amp != NULL, XLAL_EINVAL );
329 
330  A1 = A_Mu[0];
331  A2 = A_Mu[1];
332  A3 = A_Mu[2];
333  A4 = A_Mu[3];
334 
335  Asq = SQ( A1 ) + SQ( A2 ) + SQ( A3 ) + SQ( A4 );
336  Da = A1 * A4 - A2 * A3;
337 
338  disc = sqrt( SQ( Asq ) - 4.0 * SQ( Da ) );
339 
340  Ap2 = 0.5 * ( Asq + disc );
341  aPlus = sqrt( Ap2 );
342 
343  Ac2 = 0.5 * ( Asq - disc );
344  aCross = MYSIGN( Da ) * sqrt( Ac2 );
345 
346  beta = aCross / aPlus;
347 
348  b1 = A4 - beta * A1;
349  b2 = A3 + beta * A2;
350  b3 = - A1 + beta * A4 ;
351 
352  // amplitude params in LIGO conventions
353  psiRet = 0.5 * atan2( b1, b2 ); /* [-pi/2,pi/2] */
354  phi0Ret = atan2( b2, b3 ); /* [-pi, pi] */
355 
356  // Fix remaining sign-ambiguity by checking sign of reconstructed A1
357  REAL8 A1check = aPlus * cos( phi0Ret ) * cos( 2.0 * psiRet ) - aCross * sin( phi0Ret ) * sin( 2 * psiRet );
358  if ( A1check * A1 < 0 ) {
359  phi0Ret += LAL_PI;
360  }
361 
362  // make unique by fixing the gauge to be psi in [-pi/4, pi/4], phi0 in [0, 2*pi]
363  while ( psiRet > LAL_PI_4 ) {
364  psiRet -= LAL_PI_2;
365  phi0Ret -= LAL_PI;
366  }
367  while ( psiRet < - LAL_PI_4 ) {
368  psiRet += LAL_PI_2;
369  phi0Ret += LAL_PI;
370  }
371  while ( phi0Ret < 0 ) {
372  phi0Ret += LAL_TWOPI;
373  }
374 
375  while ( phi0Ret > LAL_TWOPI ) {
376  phi0Ret -= LAL_TWOPI;
377  }
378 
379  // Return final answer
380  Amp->aPlus = aPlus;
381  Amp->aCross = aCross;
382  Amp->psi = psiRet;
383  Amp->phi0 = phi0Ret;
384 
385  return XLAL_SUCCESS;
386 
387 } // XLALAmplitudeVect2Params()
388 
389 
390 
391 /**
392  * Calculates the 'optimal' / perfect-match squared signal-to-noise ratio (SNR^2) for a CW signal for
393  * given PulsarAmplitudeParameters 'pap' and Antenna Pattern Matrix 'Mmunu'.
394  * The computed 'SNR' is related to the expectation value of the coherent F-statistic 'F' via
395  * E[2F] = 4 + SNR^2 for a template perfectly matching the signal, ie SNR^2 = (signal|signal).
396  */
397 REAL8
398 XLALComputeOptimalSNR2FromMmunu( const PulsarAmplitudeParams pap, /**< [in] PulsarAmplitudeParameter {aPlus, aCross, psi, phi0} */
399  const AntennaPatternMatrix Mmunu /**< [in] Antenna-pattern Matrix */
400  )
401 {
402  // Calculate the SNR using the expressions from the 'CFSv2 notes' T0900149-v5
403  // https://dcc.ligo.org/LIGO-T0900149-v5/public, namely Eqs.(77)-(80), keeping in mind
404  // that Mmunu.{Ad,Bd,Cd} = Nsft * {A,B,C}, and Tdata = Nsft * Tsft
405 
406  REAL8 cos2psi = cos( 2.0 * pap.psi );
407  REAL8 sin2psi = sin( 2.0 * pap.psi );
408  REAL8 cos2psiSq = SQ( cos2psi );
409  REAL8 sin2psiSq = SQ( sin2psi );
410 
411  REAL8 h0sq_al1 = SQ( pap.aPlus ) * cos2psiSq + SQ( pap.aCross ) * sin2psiSq; // Eq.(78) generalised to (aPlus,aCross)
412  REAL8 h0sq_al2 = SQ( pap.aPlus ) * sin2psiSq + SQ( pap.aCross ) * cos2psiSq; // Eq.(79) generalised to (aPlus,aCross)
413  REAL8 h0sq_al3 = ( SQ( pap.aPlus ) - SQ( pap.aCross ) ) * sin2psi * cos2psi; // Eq.(80) generalised to (aPlus,aCross)
414 
415  // SNR^2: Eq.(77)
416  REAL8 rho2 = ( h0sq_al1 * Mmunu.Ad + h0sq_al2 * Mmunu.Bd + 2.0 * h0sq_al3 * Mmunu.Cd ) * Mmunu.Sinv_Tsft;
417 
418  return rho2;
419 
420 } // XLALComputeOptimalSNR2FromMmunu()
421 
422 /// @}
#define __func__
log an I/O error, i.e.
#define MYSIGN(x)
#define SQ(x)
const double b1
const double b2
const double rho2
int XLALExtrapolatePulsarPhase(REAL8 *phi1, const PulsarSpins fkdot1, const REAL8 phi0, const REAL8 dtau)
Extrapolate phase from to , given the spins fkdot1 at .
int XLALEstimatePulsarAmplitudeParams(PulsarCandidate *pulsarParams, const LIGOTimeGPS *FaFb_refTime, const COMPLEX8 Fa, const COMPLEX8 Fb, const AntennaPatternMatrix *Mmunu)
Estimate the amplitude parameters of a pulsar CW signal, given its phase parameters,...
int XLALAmplitudeParams2Vect(PulsarAmplitudeVect A_Mu, const PulsarAmplitudeParams Amp)
Convert amplitude params from 'physical' coordinates into 'canonical' coordinates .
REAL8 XLALComputeOptimalSNR2FromMmunu(const PulsarAmplitudeParams pap, const AntennaPatternMatrix Mmunu)
Calculates the 'optimal' / perfect-match squared signal-to-noise ratio (SNR^2) for a CW signal for gi...
int XLALAmplitudeVect2Params(PulsarAmplitudeParams *Amp, const PulsarAmplitudeVect A_Mu)
Compute amplitude params from amplitude-vector .
#define LAL_PI_2
#define LAL_PI
#define LAL_TWOPI
#define LAL_PI_4
#define LAL_REAL4_EPS
double REAL8
float complex COMPLEX8
#define lalDebugLevel
REAL8 PulsarAmplitudeVect[4]
Struct for 'canonical' coordinates in amplitude-params space A^mu = {A1, A2, A3, A4}.
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFUNC
XLAL_EERR
XLAL_EDOM
XLAL_EINVAL
REAL8 XLALGPSDiff(const LIGOTimeGPS *t1, const LIGOTimeGPS *t0)
Struct holding the "antenna-pattern" matrix , in terms of the multi-detector scalar product.
Definition: LALComputeAM.h:127
REAL8 Sinv_Tsft
normalization-factor (using single-sided PSD!)
Definition: LALComputeAM.h:133
Type containing the JKS 'amplitude parameters' {h0, cosi, phi0, psi}.
REAL8 aCross
Signal amplitude (cross)
REAL8 psi
polarization angle psi
REAL8 aPlus
Signal amplitude (plus)
REAL8 phi0
initial signal-phase (at some reference time)
Type containing a "candidate": parameter-space point with estimated errors and Fstat-value/significan...
PulsarAmplitudeParams dAmp
amplitude-parameters and error-estimates
PulsarAmplitudeParams Amp
gsl_matrix * AmpFisherMatrix
Fisher-matrix of amplitude-subspace: has more info than dAmp!
PulsarDopplerParams Doppler
PulsarSpins fkdot
Intrinsic spins: [Freq, f1dot, f2dot, ...
LIGOTimeGPS refTime
Reference time of pulsar parameters (in SSB!)