Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
Skymap.c
Go to the documentation of this file.
1/*
2 *
3 * Copyright (C) 2008 Antony Searle
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 * Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20#include <math.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <limits.h>
24
25#include <gsl/gsl_linalg.h>
26
27#include <lal/LALConstants.h>
28#include <lal/LALMalloc.h>
29#include <lal/XLALError.h>
30#include <lal/DetResponse.h>
31#include <lal/Skymap.h>
32
33// Convenience functions for tiny stack vectors and matrices
34
35// Dot product of 3-vectors
36
37static double dot3(double a[3], double b[3])
38{
39 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
40}
41
42// Inverse of a 2x2 matrix
43
44static void inv22(double a[2][2], double b[2][2])
45{
46 double c = b[0][0] * b[1][1] - b[0][1] * b[1][0];
47 a[0][0] = b[1][1] / c;
48 a[0][1] = -b[0][1] / c;
49 a[1][0] = -b[1][0] / c;
50 a[1][1] = b[0][0] / c;
51}
52
53// Determinant of a 2x2 matrix
54
55static double det22(double a[2][2])
56{
57 return a[0][0] * a[1][1] - a[0][1] * a[1][0];
58}
59
60// Coordinate transformation theta,phi -> x,y,z
61
62void XLALSkymapCartesianFromSpherical(double a[3], double b[2])
63{
64 a[0] = sin(b[0]) * cos(b[1]);
65 a[1] = sin(b[0]) * sin(b[1]);
66 a[2] = cos(b[0]);
67}
68
69// Coordinate transformation x,y,z -> theta,phi
70
71void XLALSkymapSphericalFromCartesian(double a[2], double b[3])
72{
73 a[0] = acos(b[2]);
74 a[1] = atan2(b[1], b[0]);
75}
76
77// Time of arrival at a detector, relative to center of Earth, for signals
78// from a given (unit) direction
79
80static double site_time(LALDetector* site, double direction[3])
81{
82 return -dot3(site->location, direction) / LAL_C_SI;
83}
84
85// Plus and cross polarization response of a detector for signals from a
86// given direction
87
88static void site_response(double f[2], const LALDetector* site, double direction[3])
89{
90 double thetaphi[2];
91 XLALSkymapSphericalFromCartesian(thetaphi, direction);
92 XLALComputeDetAMResponse(&f[0], &f[1], site->response, thetaphi[1], LAL_PI_2 - thetaphi[0], 0, 0);
93}
94
95// XLALSkymapLogSumExp(a, b) computes log(exp(a) + exp(b)) but will not
96// overflow for a or b > ~300
97//
98// For a > b, we use the identity
99//
100// log(exp(a) + exp(b)
101// = log(exp(a) * (1 + exp(b) / exp(a)))
102// = a + log(1 + exp(b - a))
103// = a + log1p(exp(b - a))
104//
105// where b - a < 0 and exp(b - a) cannot overflow (though it may
106// underflow).
107//
108// And for a < b
109//
110// log(exp(a) + exp(b))
111// = log(exp(b) * (exp(a) / exp(b) + 1))
112// = b + log(exp(a - b) + 1)
113// = b + log1p(exp(a - b))
114//
115// If neither a < b nor a > b, we either have equality or both values
116// are (the same) plus or minus infinity. Forming (a - b) in the case of
117// infinities results in a NaN, so we must use a third expression
118//
119// log(exp(a) + exp(b))
120// = log(exp(a) + exp(a))
121// = log(2 * exp(a))
122// = log(2) + a
123
124double XLALSkymapLogSumExp(double a, double b)
125{
126 return (a < b) ?
127 (b + log1p(exp(a - b))) :
128 ((b < a) ? (a + log1p(exp(b - a))) : (a + log(2)));
129}
130
131// Find the maximum of a sequence of doubles and return a pointer to it
132
133static double* findmax(double* begin, double* end)
134{
135 double* p;
136 double* m;
137 m = begin;
138 for (p = begin; p != end; ++p)
139 {
140 if (*m < *p)
141 {
142 m = p;
143 }
144 }
145 return m;
146}
147
148// Find log sum_i exp(a[i])) given max_i a[i], using the same technique as
149// XLALSkymapLogSumExp to accumulate the result without overflowing for
150// a[i] > ~300
151
152static double logtotalexpwithmax(double* begin, double* end, double m)
153{
154 double t;
155 double* p;
156 t = 0;
157 for (p = begin; p != end; ++p)
158 {
159 t += exp(*p - m);
160 }
161 return m + log(t);
162}
163
164// Find log sum_i exp(a[i]) using findmax and logtotalexpwithmax
165
166double XLALSkymapLogTotalExp(double* begin, double* end)
167{
168 return logtotalexpwithmax(begin, end, *findmax(begin, end));
169}
170
171// To cubic interpolate
172// x(0 <= t <= 1)
173// from
174// x[-1], x[0], x[1], x[2]
175// we compute
176// w_t[-1], w_t[0], w_t[1], w_t[2]
177// such that
178// x(t) = sum_i x[i] w_t[i]
179
180double XLALSkymapInterpolate(double t, double* x)
181{
182 int whole = floor(t);
183 t -= whole;
184
185 double h[4], w[4];
186
187 // Hermite basis functions at t
188
189 h[0] = (1. + 2. * t) * (1. - t) * (1. - t);
190 h[1] = t * (1. - t) * (1. - t);
191 h[2] = t * t * (3. - 2. * t);
192 h[3] = t * t * (t - 1.);
193
194 // Weights
195
196 w[0] = -0.5 * h[1];
197 w[1] = h[0] - 0.5 * h[3];
198 w[2] = h[2] + 0.5 * h[1];
199 w[3] = 0.5 * h[3];
200
201 double y = 0;
202 int i;
203
204 for (i = 0; i != 4; ++i)
205 {
206 y += x[whole + i - 1] * w[i];
207 }
208
209 return y;
210
211
212}
213
214// Construct an XLALSkymap2PlanType in the given memory from
215// sample frequency of matched filter timeseries
216// number of detectors
217// list of detector LAL ID numbers
218
219void XLALSkymapPlanConstruct(int sampleFrequency, int n, int* detectors, XLALSkymapPlanType* plan)
220{
221 int i;
222
223 plan->sampleFrequency = sampleFrequency;
224 plan->n = n;
225
226 for (i = 0; i != plan->n; ++i)
227 {
228 plan->site[i] = lalCachedDetectors[detectors[i]];
229 }
230
231}
232
233// Construct an XLALSkymap2DirectionProperties object in the given memory
234// from
235// a plan
236// a theta, phi tuple
237
239 XLALSkymapPlanType* plan,
240 double directions[2],
242 )
243{
244 double x[3];
245 int j;
246
247 // Convert theta, phi direction to cartesian
249
250 for (j = 0; j != plan->n; ++j)
251 {
252 // Delay (in seconds)
253 properties->delay[j] = site_time(plan->site + j, x);
254 // Plus and cross polarization responses
255 site_response(properties->f[j], plan->site + j, x);
256 }
257}
258
259// Construct a XLALSkymap2Kernel object in the given memory from
260// a plan
261// direction properties (time delays, interpolation weights and
262// antenna patterns)
263// the noise-weighted inner product of the template with itself
264
266 XLALSkymapPlanType* plan,
268 double* wSw,
270 )
271{
272
273 int i, j, k, l;
274
275 //
276 // W = diag(w.S_j^{-1}.w)
277 //
278 // F (F^T W F + I) F^T
279 //
280
281 double a[2][2]; // F^T W F
282 double b[2][2]; // inv(A)
283
284 // Compute the kernel
285
286 // F^T W F + I
287
288 for (i = 0; i != 2; ++i)
289 {
290 for (j = 0; j != 2; ++j)
291 {
292 a[i][j] = ((i == j) ? 1.0 : 0.0);
293 for (k = 0; k != plan->n; ++k)
294 {
295 a[i][j] += properties->f[k][i] * wSw[k] * properties->f[k][j];
296 }
297 }
298 }
299
300 // (F^T W F + I)^{-1}
301
302 inv22(b, a);
303
304 // F (F^T W F + I)^{-1} F^T
305
306 for (i = 0; i != plan->n; ++i)
307 {
308 for (j = 0; j != plan->n; ++j)
309 {
310 kernel->k[i][j] = 0.0;
311 for (k = 0; k != 2; ++k)
312 {
313 for (l = 0; l != 2; ++l)
314 {
315 kernel->k[i][j] += properties->f[i][k] * b[k][l] * properties->f[j][l];
316 }
317 }
318 }
319 }
320
321 kernel->logNormalization = 0.5 * log(det22(b));
322
323}
324
325// Construct a XLALSkymapKernel object in the given memory from
326// a plan
327// direction properties (time delays, interpolation weights and
328// antenna patterns)
329// the noise-weighted inner product of the template with itself
330// the amplitude calibration error
331
333 XLALSkymapPlanType* plan,
335 double* wSw,
336 double* error,
338 )
339{
340
341 int i, j, k;
342
343 double a[XLALSKYMAP_N][XLALSKYMAP_N];
344
345 // compute the signal covariance matrix
346
347 for (i = 0; i != plan->n; ++i)
348 {
349 for (j = 0; j != plan->n; ++j)
350 {
351 a[i][j] = 0;
352 for (k = 0; k != 2; ++k)
353 {
354 a[i][j] += properties->f[i][k] * properties->f[j][k]; // antenna factors
355 }
356 a[i][j] *= wSw[i] * wSw[j]; // snr factors
357 }
358 a[i][i] *= 1 + error[i] * error[i]; // error factors
359 a[i][i] += wSw[i]; // noise covariance
360 }
361
362 // invert the covariance
363
364 gsl_matrix_view m = gsl_matrix_view_array_with_tda(a[0], plan->n, plan->n, XLALSKYMAP_N);
365 gsl_permutation* p = gsl_permutation_alloc(plan->n);
366 int s;
367
368 gsl_linalg_LU_decomp(&m.matrix, p, &s);
369
370 gsl_matrix_view inverse = gsl_matrix_view_array_with_tda(kernel->k[0], plan->n, plan->n, XLALSKYMAP_N);
371
372 gsl_linalg_LU_invert(&m.matrix, p, &inverse.matrix);
373
374 gsl_permutation_free(p);
375
376 // subtract inverse signal covariance from inverse noise covariance
377
378 for (i = 0; i != plan->n; ++i)
379 {
380 for (j = 0; j != plan->n; ++j)
381 {
382 kernel->k[i][j] = -kernel->k[i][j];
383 }
384 kernel->k[i][i] += 1. / wSw[i];
385 }
386
387 // log normalization
388
389 kernel->logNormalization = 0;
390 for (i = 0; i != plan->n; ++i)
391 {
392 // accumulate the log determinant of the noise covariance
393 kernel->logNormalization += log(wSw[i]);
394 }
395 kernel->logNormalization -= gsl_linalg_LU_lndet(&m.matrix); // log determinant of the signal covariance
396 kernel->logNormalization *= 0.5; // square root
397
398}
399
400// Compute the marginalization integral over a_plus and a_cross for the
401// system described by
402// a plan
403// a direction's properties
404// a kernel
405// a matched filter time series for each detector
406// a signal arrival time
407
409 XLALSkymapPlanType* plan,
411 XLALSkymapKernelType* kernel,
412 double** xSw,
413 double tau,
414 double* posterior
415 )
416{
417 double a;
418 int i, j;
419
420 double x[XLALSKYMAP_N];
421
422 // Interpolate the matched filter values
423
424 for (i = 0; i != plan->n; ++i)
425 {
426 x[i] = XLALSkymapInterpolate((tau + properties->delay[i]) * plan->sampleFrequency, xSw[i]);
427 }
428
429 // This implementation does not exploit the symmetry of the expression
430
431 // Compute x^T.K.x
432
433 a = 0;
434
435 for (i = 0; i != plan->n; ++i)
436 {
437 for (j = 0; j != plan->n; ++j)
438 {
439 a += x[i] * kernel->k[i][j] * x[j];
440 }
441 }
442
443 // Scale and apply the normalization
444
445 *posterior = 0.5 * a + kernel->logNormalization;
446
447}
static double site_time(LALDetector *site, double direction[3])
Definition: Skymap.c:80
void XLALSkymapDirectionPropertiesConstruct(XLALSkymapPlanType *plan, double directions[2], XLALSkymapDirectionPropertiesType *properties)
Definition: Skymap.c:238
static void site_response(double f[2], const LALDetector *site, double direction[3])
Definition: Skymap.c:88
static double * findmax(double *begin, double *end)
Definition: Skymap.c:133
static double det22(double a[2][2])
Definition: Skymap.c:55
void XLALSkymapSphericalFromCartesian(double a[2], double b[3])
Definition: Skymap.c:71
void XLALSkymapUncertainKernelConstruct(XLALSkymapPlanType *plan, XLALSkymapDirectionPropertiesType *properties, double *wSw, double *error, XLALSkymapKernelType *kernel)
Definition: Skymap.c:332
double XLALSkymapLogTotalExp(double *begin, double *end)
Definition: Skymap.c:166
double XLALSkymapLogSumExp(double a, double b)
Definition: Skymap.c:124
static void inv22(double a[2][2], double b[2][2])
Definition: Skymap.c:44
double XLALSkymapInterpolate(double t, double *x)
Definition: Skymap.c:180
void XLALSkymapApply(XLALSkymapPlanType *plan, XLALSkymapDirectionPropertiesType *properties, XLALSkymapKernelType *kernel, double **xSw, double tau, double *posterior)
Definition: Skymap.c:408
static double logtotalexpwithmax(double *begin, double *end, double m)
Definition: Skymap.c:152
static double dot3(double a[3], double b[3])
Definition: Skymap.c:37
void XLALSkymapPlanConstruct(int sampleFrequency, int n, int *detectors, XLALSkymapPlanType *plan)
Definition: Skymap.c:219
void XLALSkymapKernelConstruct(XLALSkymapPlanType *plan, XLALSkymapDirectionPropertiesType *properties, double *wSw, XLALSkymapKernelType *kernel)
Definition: Skymap.c:265
void XLALSkymapCartesianFromSpherical(double a[3], double b[2])
Definition: Skymap.c:62
#define XLALSKYMAP_N
Definition: Skymap.h:45
static REAL8TimeSeries * error(const REAL8TimeSeries *s1, const REAL8TimeSeries *s0)
static double f(double theta, double y, double xi)
Definition: XLALMarcumQ.c:258
const LALDetector lalCachedDetectors[LAL_NUM_DETECTORS]
Pre-existing detectors.
void XLALComputeDetAMResponse(double *fplus, double *fcross, const REAL4 D[3][3], const double ra, const double dec, const double psi, const double gmst)
An implementation of the detector response formulae in Anderson et al PRD 63 042003 (2001) .
Definition: DetResponse.c:44
#define LAL_PI_2
pi/2
Definition: LALConstants.h:181
#define LAL_C_SI
Speed of light in vacuum, m s^-1.
Definition: LALConstants.h:198
static const INT4 m
Definition: Random.c:80
static const INT4 a
Definition: Random.c:79
Detector structure.
Definition: LALDetectors.h:278
double f[XLALSKYMAP_N][2]
Definition: Skymap.h:77
double delay[XLALSKYMAP_N]
Definition: Skymap.h:78
double logNormalization
Definition: Skymap.h:93
double k[XLALSKYMAP_N][XLALSKYMAP_N]
Definition: Skymap.h:92
int sampleFrequency
Definition: Skymap.h:60
LALDetector site[XLALSKYMAP_N]
Definition: Skymap.h:62
enum @4 site