Loading [MathJax]/extensions/tex2jax.js
LALBurst 2.0.7.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Macros Modules Pages
EPSearch.c
Go to the documentation of this file.
1/*
2 *
3 * Copyright (C) 2007 Brady, P. and Kipp Cannon
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
21/*
22 * ============================================================================
23 *
24 * Preamble
25 *
26 * ============================================================================
27 */
28
29
30#include <complex.h>
31#include <math.h>
32
33
34#include <gsl/gsl_blas.h>
35#include <gsl/gsl_matrix.h>
36#include <gsl/gsl_vector.h>
37
38
39#include <lal/Date.h>
40#include <lal/EPSearch.h>
41#include <lal/FrequencySeries.h>
42#include <lal/LALChisq.h>
43#include <lal/LALDatatypes.h>
44#include <lal/LALMalloc.h>
45#include <lal/LALStdlib.h>
46#include <lal/LIGOLwXMLArray.h>
47#include <lal/LIGOMetadataTables.h>
48#include <lal/LIGOMetadataUtils.h>
49#include <lal/RealFFT.h>
50#include <lal/SnglBurstUtils.h>
51#include <lal/TimeFreqFFT.h>
52#include <lal/TimeSeries.h>
53#include <lal/Units.h>
54#include <lal/XLALError.h>
55#include <lal/Window.h>
56
57
58static double min(double a, double b)
59{
60 return a < b ? a : b;
61}
62
63
64static double max(double a, double b)
65{
66 return a > b ? a : b;
67}
68
69
70/*
71 * ============================================================================
72 *
73 * Filter Bank
74 *
75 * ============================================================================
76 */
77
78
79typedef struct tagExcessPowerFilter {
81 double unwhitened_rms; /**< root mean square of the unwhitened time series corresponding to this filter */
83
84
85typedef struct tagLALExcessPowerFilterBank {
88 REAL8Sequence *twice_channel_overlap; /**< twice the inner product of filters for neighbouring channels; twice_channel_overlap[0] is twice the inner product of the filters for channels 0 and 1, and so on (for n channels, there are n - 1 channel_overlaps) */
89 REAL8Sequence *unwhitened_cross; /**< the mean square cross terms for wide channels (indices same as for twice_channel_overlap) */
91
92
93/**
94 * From the power spectral density function, generate the comb of channel
95 * filters for the time-frequency plane --- an excess power filter bank.
96 */
98 double filter_deltaF,
99 double flow,
100 double channel_bandwidth,
101 int n_channels,
102 const REAL8FrequencySeries *psd,
103 const REAL8Sequence *two_point_spectral_correlation
104)
105{
107 ExcessPowerFilter *basis_filters;
108 REAL8Sequence *twice_channel_overlap;
109 REAL8Sequence *unwhitened_cross;
110 int i;
111
112 new = malloc(sizeof(*new));
113 basis_filters = calloc(n_channels, sizeof(*basis_filters));
114 twice_channel_overlap = XLALCreateREAL8Sequence(n_channels - 1);
115 unwhitened_cross = XLALCreateREAL8Sequence(n_channels - 1);
116 if(!new || !basis_filters || !twice_channel_overlap || !unwhitened_cross) {
117 free(new);
118 free(basis_filters);
119 XLALDestroyREAL8Sequence(twice_channel_overlap);
120 XLALDestroyREAL8Sequence(unwhitened_cross);
122 }
123
124 new->n_filters = n_channels;
125 new->basis_filters = basis_filters;
126 new->twice_channel_overlap = twice_channel_overlap;
127 new->unwhitened_cross = unwhitened_cross;
128
129 for(i = 0; i < n_channels; i++) {
130 basis_filters[i].fseries = XLALCreateExcessPowerFilter(flow + i * channel_bandwidth, channel_bandwidth, psd, two_point_spectral_correlation);
131 if(!basis_filters[i].fseries) {
132 while(i--)
133 XLALDestroyCOMPLEX16FrequencySeries(basis_filters[i].fseries);
134 free(new);
135 XLALDestroyREAL8Sequence(twice_channel_overlap);
136 XLALDestroyREAL8Sequence(unwhitened_cross);
138 }
139
140 /* compute the unwhitened root mean square for this channel */
141 basis_filters[i].unwhitened_rms = sqrt(XLALExcessPowerFilterInnerProduct(basis_filters[i].fseries, basis_filters[i].fseries, two_point_spectral_correlation, psd) * filter_deltaF / 2);
142 }
143
144 /* compute the cross terms for the channel normalizations and
145 * unwhitened mean squares */
146 for(i = 0; i < new->n_filters - 1; i++) {
147 twice_channel_overlap->data[i] = 2 * XLALExcessPowerFilterInnerProduct(basis_filters[i].fseries, basis_filters[i + 1].fseries, two_point_spectral_correlation, NULL);
148 unwhitened_cross->data[i] = XLALExcessPowerFilterInnerProduct(basis_filters[i].fseries, basis_filters[i + 1].fseries, two_point_spectral_correlation, psd) * psd->deltaF;
149 }
150
151 return new;
152}
153
154
155/**
156 * Destroy and excess power filter bank.
157 */
160)
161{
162 if(bank) {
163 if(bank->basis_filters) {
164 int i;
165 for(i = 0; i < bank->n_filters; i++)
167 free(bank->basis_filters);
168 }
171 }
172
173 free(bank);
174}
175
176
177/*
178 * ============================================================================
179 *
180 * Timing Arithmetic
181 *
182 * ============================================================================
183 */
184
185
186/**
187 * Round target_length down so that an integer number of intervals of
188 * length segment_length, each shifted by segment_shift with respect to the
189 * interval preceding it, fits into the result.
190 */
192 int target_length,
193 int segment_length,
194 int segment_shift
195)
196{
197 unsigned segments;
198
199 /*
200 * check input
201 */
202
203 if(segment_length < 1) {
204 XLALPrintError("segment_length < 1");
206 }
207 if(segment_shift < 1) {
208 XLALPrintError("segment_shift < 1");
210 }
211
212 /*
213 * trivial case
214 */
215
216 if(target_length < segment_length)
217 return 0;
218
219 /*
220 * do the arithmetic
221 */
222
223 segments = (target_length - segment_length) / segment_shift;
224
225 return segments * segment_shift + segment_length;
226}
227
228
229/**
230 * Compute and return the timing parameters for an excess power analysis.
231 * Pass NULL for any optional pointer to not compute and return that
232 * parameter. The return is 0 on success, negative on failure.
233 */
235 int window_length, /**< Number of samples in a window used for the time-frequency plane */
236 int max_tile_length, /**< Number of samples in the tile of longest duration */
237 double fractional_tile_shift, /**< Number of samples by which the start of the longest tile is shifted from the start of the tile preceding it, as a fraction of its length */
238 int *psd_length, /**< (optional) User's desired number of samples to use in computing a PSD estimate. Will be replaced with actual number of samples to use in computing a PSD estimate (rounded down to be comensurate with the windowing). */
239 int *psd_shift, /**< (optional) Number of samples by which the start of a PSD is to be shifted from the start of the PSD that preceded it in order that the tiling pattern continue smoothly across the boundary. */
240 int *window_shift, /**< Number of samples by which the start of a time-frequency plane window is shifted from the window preceding it in order that the tiling pattern continue smoothly across the boundary. */
241 int *window_pad, /**< How many samples at the start and end of each window are treated as padding, and will not be covered by the tiling. */
242 int *tiling_length /**< How many samples will be covered by the tiling. */
243)
244{
245 int max_tile_shift = fractional_tile_shift * max_tile_length;
246
247 /*
248 * check input parameters
249 */
250
251 if(window_length % 4 != 0) {
252 XLALPrintError("window_length is not a multiple of 4");
254 }
255 if(max_tile_length < 1) {
256 XLALPrintError("max_tile_length < 1");
258 }
259 if(fractional_tile_shift <= 0) {
260 XLALPrintError("fractional_tile_shift <= 0");
262 }
263 if(fmod(fractional_tile_shift * max_tile_length, 1) != 0) {
264 XLALPrintError("fractional_tile_shift * max_tile_length not an integer");
266 }
267 if(max_tile_shift < 1) {
268 XLALPrintError("fractional_tile_shift * max_tile_length < 1");
270 }
271
272 /*
273 * discard first and last 4096 samples
274 *
275 * FIXME. this should be tied to the sample frequency and
276 * time-frequency plane's channel spacing. multiplying the time
277 * series by a window has the effect of convolving the Fourier
278 * transform of the data by the F.T. of the window, and we don't
279 * want this to blur the spectrum by an amount larger than 1
280 * channel --- a delta function in the spectrum should remain
281 * confined to a single bin. a channel width of 2 Hz means the
282 * notch feature created in the time series by the window must be
283 * at least .5 s long to not result in undesired leakage. at a
284 * sample frequency of 8192 samples / s, it must be at least 4096
285 * samples long (2048 samples at each end of the time series). to
286 * be safe, we double that to 4096 samples at each end.
287 */
288
289 *window_pad = 4096;
290
291 /*
292 * tiling covers the remainder, rounded down to fit an integer
293 * number of tiles
294 */
295
296 *tiling_length = window_length - 2 * *window_pad;
297 *tiling_length = XLALOverlappedSegmentsCommensurate(*tiling_length, max_tile_length, max_tile_shift);
298 if(*tiling_length <= 0) {
299 XLALPrintError("window_length too small for tiling, must be >= 2 * %d + %d", *window_pad, max_tile_length);
301 }
302
303 /*
304 * now re-compute window_pad from rounded-off tiling_length
305 */
306
307 *window_pad = (window_length - *tiling_length) / 2;
308 if(*tiling_length + 2 * *window_pad != window_length) {
309 XLALPrintError("window_length does not permit equal padding before and after tiling");
311 }
312
313 /*
314 * adjacent tilings overlap so that their largest tiles overlap the
315 * same as within each tiling
316 */
317
318 *window_shift = *tiling_length - (max_tile_length - max_tile_shift);
319 if(*window_shift < 1) {
320 XLALPrintError("window_shift < 1");
322 }
323
324 /*
325 * compute the adjusted PSD length if desired
326 */
327
328 if(psd_length) {
329 *psd_length = XLALOverlappedSegmentsCommensurate(*psd_length, window_length, *window_shift);
330 if(*psd_length < 0)
332
333 *psd_shift = *psd_length - (window_length - *window_shift);
334 if(*psd_shift < 1) {
335 XLALPrintError("psd_shift < 1");
337 }
338 } else if(psd_shift) {
339 /* for safety */
340 *psd_shift = -1;
341 /* can't compute psd_shift without psd_length input */
343 }
344
345 return 0;
346}
347
348
349/*
350 * ============================================================================
351 *
352 * Time-Frequency Plane Create / Destroy
353 *
354 * ============================================================================
355 */
356
357
358/**
359 * A time-frequency plane
360 */
361
362
363typedef struct tagREAL8TimeFrequencyPlaneTiles {
364 unsigned max_length;
365 unsigned min_channels;
366 unsigned max_channels;
367 unsigned tiling_start;
368 unsigned tiling_end;
372
373
374typedef struct tagREAL8TimeFrequencyPlane {
375 char name[LALNameLength]; /**< name of data from which this was computed */
376 LIGOTimeGPS epoch; /**< epoch of data from which this was computed */
377 double deltaT; /**< time resolution of the plane */
378 double fseries_deltaF; /**< input frequency series' resolution */
379 double deltaF; /**< TF plane's frequency resolution (channel spacing) */
380 double flow; /**< low frequency boundary of TF plane */
381 gsl_matrix *channel_data; /**< channel data. each channel is placed into its own column. channel_data[i * channels + j] corresponds to time epoch + i * deltaT and the frequency band [flow + j * deltaF, flow + (j + 1) * deltaF) */
382 REAL8Sequence *channel_buffer; /**< re-usable holding area for the data for a single channel */
384 REAL8TimeFrequencyPlaneTiles tiles; /**< time-frequency plane's tiling information */
385 REAL8Window *window; /**< time-domain window applied to input time series for tapering edges to 0 */
386 int window_shift; /**< by how many samples a window's start should be shifted from the start of the window preceding it */
387 REAL8Sequence *two_point_spectral_correlation; /**< two-point spectral correlation of the whitened frequency series, computed from the time-domain window function */
389
390
391/**
392 * Create and initialize a time-frequency plane object.
393 */
394
395
397 unsigned tseries_length, /**< length of time series from which TF plane will be computed */
398 double tseries_deltaT, /**< sample rate of time series */
399 double flow, /**< minimum frequency to search for */
400 double bandwidth, /**< bandwidth of TF plane */
401 double tiling_fractional_stride, /**< overlap of adjacent tiles */
402 double max_tile_bandwidth, /**< largest tile's bandwidth */
403 double max_tile_duration, /**< largest tile's duration */
404 const REAL8FFTPlan *plan /**< forward plan whose length is tseries_length */
405)
406{
408 gsl_matrix *channel_data;
409 REAL8Sequence *channel_buffer;
410 REAL8Sequence *unwhitened_channel_buffer;
411 REAL8Window *tukey;
412 REAL8Sequence *correlation;
413
414 /*
415 * resolution of FT of input time series
416 */
417
418 const double fseries_deltaF = 1.0 / (tseries_length * tseries_deltaT);
419
420 /*
421 * time-frequency plane's channel spacing
422 */
423
424 const double deltaF = 1 / max_tile_duration * tiling_fractional_stride;
425
426 /*
427 * total number of channels
428 */
429
430 const int channels = round(bandwidth / deltaF);
431
432 /*
433 * stride
434 */
435
436 const unsigned inv_fractional_stride = round(1.0 / tiling_fractional_stride);
437
438 /*
439 * tile size limits
440 */
441
442 const unsigned min_length = round((1 / max_tile_bandwidth) / tseries_deltaT);
443 const unsigned max_length = round(max_tile_duration / tseries_deltaT);
444 const unsigned min_channels = inv_fractional_stride;
445 const unsigned max_channels = round(max_tile_bandwidth / deltaF);
446
447 /*
448 * sample on which tiling starts
449 */
450
451 int tiling_start;
452
453 /*
454 * length of tiling
455 */
456
457 int tiling_length;
458
459 /*
460 * window shift
461 */
462
463 int window_shift;
464
465 /*
466 * Compute window_shift, tiling_start, and tiling_length.
467 */
468
469 if(XLALEPGetTimingParameters(tseries_length, max_tile_duration / tseries_deltaT, tiling_fractional_stride, NULL, NULL, &window_shift, &tiling_start, &tiling_length) < 0)
471
472 /*
473 * Make sure that input parameters are reasonable, and that a
474 * complete tiling is possible.
475 *
476 * Note that because all tile durations are integer power of two
477 * multiples of the smallest duration, if the largest duration fits
478 * an integer number of times in the tiling length, then all tile
479 * sizes do so there's no need to test them all. Likewise for the
480 * bandwidths.
481 *
482 * FIXME: these tests require an integer number of non-overlapping
483 * tiles to fit, which is stricter than required; only need an
484 * integer number of overlapping tiles to fit, but then probably
485 * have to test all sizes separately.
486 */
487
488 if((flow < 0) ||
489 (bandwidth <= 0) ||
490 (deltaF <= 0) ||
491 (inv_fractional_stride * tiling_fractional_stride != 1) ||
492 (fmod(max_tile_duration, tseries_deltaT) != 0) ||
493 (fmod(deltaF, fseries_deltaF) != 0) ||
494 (tseries_deltaT <= 0) ||
495 (channels * deltaF != bandwidth) ||
496 (min_length * tseries_deltaT != (1 / max_tile_bandwidth)) ||
497 (min_length % inv_fractional_stride != 0) ||
498 (tiling_length % max_length != 0) ||
499 (channels % max_channels != 0)) {
500 XLALPrintError("unable to construct time-frequency tiling from input parameters\n");
502 }
503
504 /*
505 * Allocate memory.
506 */
507
508 plane = XLALMalloc(sizeof(*plane));
509 channel_data = gsl_matrix_alloc(tseries_length, channels);
510 channel_buffer = XLALCreateREAL8Sequence(tseries_length);
511 unwhitened_channel_buffer = XLALCreateREAL8Sequence(tseries_length);
512 tukey = XLALCreateTukeyREAL8Window(tseries_length, (tseries_length - tiling_length) / (double) tseries_length);
513 if(tukey)
514 correlation = XLALREAL8WindowTwoPointSpectralCorrelation(tukey, plan);
515 else
516 /* error path */
517 correlation = NULL;
518 if(!plane || !channel_data || !channel_buffer || !unwhitened_channel_buffer || !tukey || !correlation) {
519 XLALFree(plane);
520 if(channel_data)
521 gsl_matrix_free(channel_data);
522 XLALDestroyREAL8Sequence(channel_buffer);
523 XLALDestroyREAL8Sequence(unwhitened_channel_buffer);
525 XLALDestroyREAL8Sequence(correlation);
527 }
528
529 /*
530 * Initialize the structure
531 */
532
533 plane->name[0] = '\0';
534 XLALGPSSetREAL8(&plane->epoch, 0.0);
535 plane->deltaT = tseries_deltaT;
536 plane->fseries_deltaF = fseries_deltaF;
537 plane->deltaF = deltaF;
538 plane->flow = flow;
539 plane->channel_data = channel_data;
540 plane->channel_buffer = channel_buffer;
541 plane->unwhitened_channel_buffer = unwhitened_channel_buffer;
542 plane->tiles.max_length = max_length;
543 plane->tiles.min_channels = min_channels;
544 plane->tiles.max_channels = max_channels;
545 plane->tiles.tiling_start = tiling_start;
546 plane->tiles.tiling_end = tiling_start + tiling_length;
547 plane->tiles.inv_fractional_stride = inv_fractional_stride;
548 plane->tiles.dof_per_pixel = 2 * tseries_deltaT * deltaF;
549 plane->window = tukey;
550 plane->window_shift = window_shift;
551 plane->two_point_spectral_correlation = correlation;
552
553 /*
554 * Success
555 */
556
557 return plane;
558}
559
560
561/**
562 * Free a time-frequency plane object.
563 */
564
565
568)
569{
570 if(plane) {
571 if(plane->channel_data)
572 gsl_matrix_free(plane->channel_data);
577 }
578 XLALFree(plane);
579}
580
581
582/*
583 * ============================================================================
584 *
585 * Time-Frequency Plane Projection
586 *
587 * ============================================================================
588 */
589
590
591/*
592 * Multiply the data by the filter. The check that the frequency
593 * resolutions and units are compatible is omitted because it is implied by
594 * the calling code.
595 */
596
597
599 COMPLEX16Sequence *outputseq,
600 const COMPLEX16FrequencySeries *inputseries,
601 const COMPLEX16FrequencySeries *filterseries
602)
603{
604 /* find bounds of common frequencies */
605 const double flo = max(filterseries->f0, inputseries->f0);
606 const double fhi = min(filterseries->f0 + filterseries->data->length * filterseries->deltaF, inputseries->f0 + inputseries->data->length * inputseries->deltaF);
607 double complex *output = outputseq->data + (int) round((flo - inputseries->f0) / inputseries->deltaF);
608 double complex *last = outputseq->data + (int) round((fhi - inputseries->f0) / inputseries->deltaF);
609 const double complex *input = inputseries->data->data + (int) round((flo - inputseries->f0) / inputseries->deltaF);
610 const double complex *filter = filterseries->data->data + (int) round((flo - filterseries->f0) / filterseries->deltaF);
611
612 if(outputseq->length != inputseries->data->length)
614
615 if(((unsigned) (output - outputseq->data) > outputseq->length) || (last - outputseq->data < 0))
616 /* inputseries and filterseries don't intersect */
617 memset(outputseq->data, 0, outputseq->length * sizeof(*outputseq->data));
618 else {
619 /* output = inputseries * conj(filter) */
620 memset(outputseq->data, 0, (output - outputseq->data) * sizeof(*outputseq->data));
621 for(; output < last; output++, input++, filter++)
622 *output = *input * conj(*filter);
623 memset(last, 0, (outputseq->length - (last - outputseq->data)) * sizeof(*outputseq->data));
624 }
625
626 return outputseq;
627}
628
629
630/*
631 * Project a frequency series onto the comb of channel filters
632 */
633
634
637 const LALExcessPowerFilterBank *filter_bank,
638 const COMPLEX16FrequencySeries *fseries,
639 const REAL8FFTPlan *reverseplan
640)
641{
642 COMPLEX16Sequence *fcorr;
643 unsigned i;
644
645 /* check input parameters */
646 if((fmod(plane->deltaF, fseries->deltaF) != 0.0) ||
647 (fmod(plane->flow - fseries->f0, fseries->deltaF) != 0.0))
649
650 /* make sure the frequency series spans an appropriate band */
651 if((plane->flow < fseries->f0) ||
652 (plane->flow + plane->channel_data->size2 * plane->deltaF > fseries->f0 + fseries->data->length * fseries->deltaF))
654
655 /* create temporary vectors */
656 fcorr = XLALCreateCOMPLEX16Sequence(fseries->data->length);
657 if(!fcorr)
659
660#if 0
661 /* diagnostic code to dump data for the \hat{s}_{k} histogram */
662 {
663 unsigned k;
664 FILE *f = fopen("sk.dat", "a");
665 for(k = plane->flow / fseries->deltaF; k < (plane->flow + plane->channel_data->size2 * plane->deltaF) / fseries->deltaF; k++)
666 fprintf(f, "%g\n%g\n", fseries->data->data[k].re, fseries->data->data[k].im);
667 fclose(f);
668 }
669#endif
670#if 0
671 /* diagnostic code to dump data for the \hat{s}_{k}
672 * \hat{s}^{*}_{k'} histogram */
673 {
674 unsigned k, dk;
675 FILE *f = fopen("sksk.dat", "a");
676 for(dk = 0; dk < 100; dk++) {
677 double avg_r = 0;
678 double avg_i = 0;
679 for(k = plane->flow / fseries->deltaF; k + dk < (plane->flow + plane->channel_data->size2 * plane->deltaF) / fseries->deltaF; k++) {
680 double dr = fseries->data->data[k].re;
681 double di = fseries->data->data[k].im;
682 double dkr = fseries->data->data[k + dk].re;
683 double dki = fseries->data->data[k + dk].im;
684 avg_r += dr * dkr + di * dki;
685 avg_i += di * dkr - dr * dki;
686 }
687 avg_r /= k - plane->flow / fseries->deltaF;
688 avg_i /= k - plane->flow / fseries->deltaF;
689 fprintf(f, "%d %g %g\n", dk, avg_r, avg_i);
690 }
691 fclose(f);
692 }
693#endif
694
695 /* loop over the time-frequency plane's channels */
696 for(i = 0; i < plane->channel_data->size2; i++) {
697 unsigned j;
698 /* cross correlate the input data against the channel
699 * filter by taking their product in the frequency domain
700 * and then inverse transforming to the time domain to
701 * obtain an SNR time series. Note that
702 * XLALREAL8ReverseFFT() omits the factor of 1 / (N Delta
703 * t) in the inverse transform. */
704 apply_filter(fcorr, fseries, filter_bank->basis_filters[i].fseries);
705 if(XLALREAL8ReverseFFT(plane->channel_buffer, fcorr, reverseplan)) {
708 }
709 /* interleave the result into the channel_data array */
710 for(j = 0; j < plane->channel_buffer->length; j++)
711 gsl_matrix_set(plane->channel_data, j, i, plane->channel_buffer->data[j]);
712 }
713
714 /* clean up */
716
717 /* set the name and epoch of the TF plane */
718 strncpy(plane->name, fseries->name, LALNameLength);
719 plane->epoch = fseries->epoch;
720
721 /* success */
722 return 0;
723}
724
725
726/*
727 * ============================================================================
728 *
729 * Tile Analysis
730 *
731 * ============================================================================
732 */
733
734
736 const LALExcessPowerFilterBank *filter_bank,
737 unsigned channel,
738 unsigned channels
739)
740{
741 unsigned i;
742 double mean_square = 0;
743
744 for(i = channel; i < channel + channels; i++)
745 mean_square += pow(filter_bank->basis_filters[i].unwhitened_rms, 2);
746
747 return mean_square;
748}
749
750
751/*
752 * Convert time-frequency tile info to a SnglBurst row.
753 */
754
755
757 const REAL8TimeFrequencyPlane *plane,
758 double tile_start, /* in samples, allowed to be non-integer */
759 double tile_length, /* in samples, allowed to be non-integer */
760 double f_centre,
761 double bandwidth,
762 double h_rss,
763 double E,
764 double d,
765 double confidence
766)
767{
769
770 if(!event)
772
773 event->next = NULL;
774 strncpy(event->ifo, plane->name, 2);
775 event->ifo[2] = '\0';
776 strncpy(event->search, "excesspower", LIGOMETA_SEARCH_MAX);
777 event->search[LIGOMETA_SEARCH_MAX - 1] = '\0';
778 strncpy(event->channel, plane->name, LIGOMETA_CHANNEL_MAX);
779 event->channel[LIGOMETA_CHANNEL_MAX - 1] = '\0';
780 event->start_time = plane->epoch;
781 XLALGPSAdd(&event->start_time, tile_start * plane->deltaT);
782 event->duration = tile_length * plane->deltaT;
783 event->peak_time = event->start_time;
784 XLALGPSAdd(&event->peak_time, event->duration / 2);
785 event->bandwidth = bandwidth;
786 event->central_freq = f_centre;
787 /* FIXME: put h_rss into the "hrss" column */
788 event->amplitude = h_rss;
789 event->snr = E / d - 1;
790 /* -ln P(event | stationary Gaussian white noise) */
791 event->confidence = confidence;
792
793 return event;
794}
795
796
798 const REAL8TimeFrequencyPlane *plane,
799 const LALExcessPowerFilterBank *filter_bank,
800 SnglBurst *head,
801 double confidence_threshold
802)
803{
804 gsl_vector filter_output = {
805 .size = plane->tiles.tiling_end - plane->tiles.tiling_start,
806 .stride = plane->channel_data->size2,
807 .data = NULL,
808 .block = NULL,
809 .owner = 0
810 };
811 gsl_vector_view filter_output_view;
812 gsl_vector *channel_buffer;
813 gsl_vector *unwhitened_channel_buffer;
814 unsigned channel;
815 unsigned channels;
816 unsigned channel_end;
817 double h_rss;
818 double confidence;
819 /* number of degrees of freedom in tile = number of
820 * "virtual pixels" in tile. */
821 double tile_dof;
822 unsigned i;
823
824 /*
825 * create work spaces
826 */
827
828 channel_buffer = gsl_vector_alloc(filter_output.size);
829 unwhitened_channel_buffer = gsl_vector_alloc(filter_output.size);
830 if(!channel_buffer || !unwhitened_channel_buffer) {
831 if(channel_buffer)
832 gsl_vector_free(channel_buffer);
833 if(unwhitened_channel_buffer)
834 gsl_vector_free(unwhitened_channel_buffer);
836 }
837
838 /*
839 * enter loops. note: this is a quadruply-nested loop that is not
840 * indented to help fit the code on a terminal display.
841 */
842
843 for(channels = plane->tiles.min_channels; channels <= plane->tiles.max_channels; channels *= 2) {
844 /* compute distance between "virtual pixels" for this
845 * (wide) channel */
846 const unsigned stride = round(1.0 / (channels * plane->tiles.dof_per_pixel));
847
848 for(channel_end = (channel = 0) + channels; channel_end <= plane->channel_data->size2; channel_end = (channel += channels / plane->tiles.inv_fractional_stride) + channels) {
849 /* the root mean square of the "virtual channel",
850 * \sqrt{\mu^{2}} in the algorithm description */
851 const double sample_rms = sqrt(channels * plane->deltaF / plane->fseries_deltaF + XLALREAL8SequenceSum(filter_bank->twice_channel_overlap, channel, channels - 1));
852 /* the root mean square of the "uwapprox" quantity computed
853 * below, which is proportional to an approximation of the
854 * unwhitened time series. */
855 double uwsample_rms;
856 /* true unwhitened root mean square for this channel. the
857 * ratio of this squared to uwsample_rms^2 is the
858 * correction factor to be applied to uwapprox^2 to convert
859 * it to an approximation of the square of the unwhitened
860 * channel */
861 const double strain_rms = sqrt(compute_unwhitened_mean_square(filter_bank, channel, channels) + XLALREAL8SequenceSum(filter_bank->unwhitened_cross, channel, channels - 1));
862
863 /* compute uwsample_rms */
864 uwsample_rms = compute_unwhitened_mean_square(filter_bank, channel, channels);
865 for(i = channel; i < channel_end - 1; i++)
866 uwsample_rms += filter_bank->twice_channel_overlap->data[i] * filter_bank->basis_filters[i].unwhitened_rms * filter_bank->basis_filters[i + 1].unwhitened_rms * plane->fseries_deltaF / plane->deltaF;
867 uwsample_rms = sqrt(uwsample_rms);
868
869 /* reconstruct the time series and unwhitened time series
870 * for this (possibly multi-filter) channel. both time
871 * series are normalized so that each sample has a mean
872 * square of 1 */
873 filter_output.data = plane->channel_data->data + filter_output.stride * plane->tiles.tiling_start + channel;
874 filter_output_view = gsl_vector_subvector_with_stride(&filter_output, 0, stride, filter_output.size / stride);
875 gsl_vector_set_zero(channel_buffer);
876 gsl_vector_set_zero(unwhitened_channel_buffer);
877 channel_buffer->size = unwhitened_channel_buffer->size = filter_output_view.vector.size;
878 for(i = channel; i < channel_end; filter_output_view.vector.data++, i++) {
879 gsl_blas_daxpy(1.0 / sample_rms, &filter_output_view.vector, channel_buffer);
880 gsl_blas_daxpy(filter_bank->basis_filters[i].unwhitened_rms * sqrt(plane->fseries_deltaF / plane->deltaF) / uwsample_rms, &filter_output_view.vector, unwhitened_channel_buffer);
881 }
882
883#if 0
884 /* diagnostic code to dump data for the s_{j} histogram */
885 {
886 FILE *f = fopen("sj.dat", "a");
887 for(i = 0; i < channel_buffer->size; i++)
888 fprintf(f, "%g\n", gsl_vector_get(unwhitened_channel_buffer, i));
889 fclose(f);
890 }
891#endif
892
893 /* square the samples in the channel time series because
894 * from now on that's all we'll need */
895 for(i = 0; i < channel_buffer->size; i++) {
896 gsl_vector_set(channel_buffer, i, pow(gsl_vector_get(channel_buffer, i), 2));
897 gsl_vector_set(unwhitened_channel_buffer, i, pow(gsl_vector_get(unwhitened_channel_buffer, i), 2));
898 }
899
900 /* start with at least 2 degrees of freedom */
901 for(tile_dof = 2; tile_dof <= plane->tiles.max_length / stride; tile_dof *= 2) {
902 unsigned start;
903 for(start = 0; start + tile_dof <= channel_buffer->size; start += tile_dof / plane->tiles.inv_fractional_stride) {
904 /* compute sum of squares, and unwhitened sum of squares
905 * (samples have already been squared) */
906 double sumsquares = 0;
907 double uwsumsquares = 0;
908 for(i = start; i < start + tile_dof; i++) {
909 sumsquares += gsl_vector_get(channel_buffer, i);
910 uwsumsquares += gsl_vector_get(unwhitened_channel_buffer, i);
911 }
912
913 /* compute statistical confidence */
914 /* FIXME: the 0.62 is an empirically determined
915 * degree-of-freedom fudge factor. figure out what its
916 * origin is, and account for it correctly. it's most
917 * likely due to the time-frequency plane pixels not being
918 * independent of one another as a consequence of a
919 * non-zero inner product of the time-domain impulse
920 * response of the channel filter for adjacent pixels */
921 confidence = -XLALLogChisqCCDF(sumsquares * .62, tile_dof * .62);
922 if(XLALIsREAL8FailNaN(confidence)) {
923 gsl_vector_free(channel_buffer);
924 gsl_vector_free(unwhitened_channel_buffer);
926 }
927
928 /* record tiles whose statistical confidence is above
929 * threshold and that have real-valued h_rss */
930 if((confidence >= confidence_threshold) && (uwsumsquares >= tile_dof)) {
931 SnglBurst *oldhead = head;
932
933 /* compute h_rss */
934 h_rss = sqrt((uwsumsquares - tile_dof) * (stride * plane->deltaT)) * strain_rms;
935
936 /* add new event to head of linked list */
937 head = XLALTFTileToBurstEvent(plane, plane->tiles.tiling_start + (start - 0.5) * stride, tile_dof * stride, plane->flow + (channel + .5 * channels) * plane->deltaF, channels * plane->deltaF, h_rss, sumsquares, tile_dof, confidence);
938 if(!head) {
939 gsl_vector_free(channel_buffer);
940 gsl_vector_free(unwhitened_channel_buffer);
942 }
943 head->next = oldhead;
944 }
945 }
946 }
947 }
948 }
949
950 /* success */
951 gsl_vector_free(channel_buffer);
952 gsl_vector_free(unwhitened_channel_buffer);
953 return head;
954}
955
956
957/*
958 * ============================================================================
959 *
960 * Entry Point
961 *
962 * ============================================================================
963 */
964
965
966/**
967 * Generate a linked list of burst events from a time series.
968 */
970 LIGOLwXMLStream *diagnostics,
971 const REAL8TimeSeries *tseries,
972 REAL8Window *window,
973 double flow,
974 double bandwidth,
975 double confidence_threshold,
976 double fractional_stride,
977 double maxTileBandwidth,
978 double maxTileDuration
979)
980{
981 SnglBurst *head = NULL;
982 int errorcode = 0;
983 int start_sample;
985 REAL8FFTPlan *fplan;
986 REAL8FFTPlan *rplan;
988 REAL8TimeSeries *cuttseries = NULL;
989 LALExcessPowerFilterBank *filter_bank = NULL;
990 REAL8TimeFrequencyPlane *plane = NULL;
991
992 /*
993 * Construct forward and reverse FFT plans, storage for the PSD,
994 * the time-frequency plane, and a tiling. Note that the flat part
995 * of the Tukey window needs to match the locations of the tiles as
996 * specified by the tiling_start parameter of XLALCreateTFPlane.
997 * The metadata for the two frequency series will be filled in
998 * later, so it doesn't all have to be correct here.
999 */
1000
1001 fplan = XLALCreateForwardREAL8FFTPlan(window->data->length, 1);
1002 rplan = XLALCreateReverseREAL8FFTPlan(window->data->length, 1);
1003 psd = XLALCreateREAL8FrequencySeries("PSD", &tseries->epoch, 0, 0, &lalDimensionlessUnit, window->data->length / 2 + 1);
1004 fseries = XLALCreateCOMPLEX16FrequencySeries(tseries->name, &tseries->epoch, 0, 0, &lalDimensionlessUnit, window->data->length / 2 + 1);
1005 if(fplan)
1006 plane = XLALCreateTFPlane(window->data->length, tseries->deltaT, flow, bandwidth, fractional_stride, maxTileBandwidth, maxTileDuration, fplan);
1007 if(!fplan || !rplan || !psd || !fseries || !plane) {
1008 errorcode = XLAL_EFUNC;
1009 goto error;
1010 }
1011
1012#if 0
1013 /* diagnostic code to replace the input time series with stationary
1014 * Gaussian white noise. the normalization is such that it yields
1015 * unit variance frequency components without a call to the
1016 * whitening function. */
1017 {
1018 unsigned i;
1019 static RandomParams *rparams = NULL;
1020 if(!rparams)
1022 XLALNormalDeviates(tseries->data, rparams);
1023 for(i = 0; i < tseries->data->length; i++)
1024 tseries->data->data[i] *= sqrt(0.5 / tseries->deltaT);
1025 }
1026#endif
1027#if 0
1028 /* diagnostic code to disable the tapering window */
1029 {
1030 unsigned i = plane->window->data->length;
1033 }
1034#endif
1035
1036 /*
1037 * Compute the average spectrum.
1038 *
1039 * FIXME: is using windowShift here correct? we have to, otherwise
1040 * the time series' lengths are inconsistent
1041 */
1042
1043 if(XLALREAL8AverageSpectrumMedian(psd, tseries, plane->window->data->length, plane->window_shift, plane->window, fplan) < 0) {
1044 errorcode = XLAL_EFUNC;
1045 goto error;
1046 }
1047
1048 if(diagnostics)
1049 XLALWriteLIGOLwXMLArrayREAL8FrequencySeries(diagnostics, NULL, psd);
1050
1051 /*
1052 * Construct the time-frequency plane's channel filters.
1053 */
1054
1055 XLALPrintInfo("%s(): constructing channel filters\n", __func__);
1056 filter_bank = XLALCreateExcessPowerFilterBank(psd->deltaF, plane->flow, plane->deltaF, plane->channel_data->size2, psd, plane->two_point_spectral_correlation);
1057 if(!filter_bank) {
1058 errorcode = XLAL_EFUNC;
1059 goto error;
1060 }
1061
1062 /*
1063 * Loop over data applying excess power method.
1064 */
1065
1066 for(start_sample = 0; start_sample + plane->window->data->length <= tseries->data->length; start_sample += plane->window_shift) {
1067 /*
1068 * Verbosity.
1069 */
1070
1071 XLALPrintInfo("%s(): ", __func__);
1072 XLALPrintProgressBar(start_sample / (double) (tseries->data->length - plane->window->data->length));
1073 XLALPrintInfo(" complete\n");
1074
1075 /*
1076 * Extract a window-length of data from the time series.
1077 */
1078
1079 cuttseries = XLALCutREAL8TimeSeries(tseries, start_sample, plane->window->data->length);
1080 if(!cuttseries) {
1081 errorcode = XLAL_EFUNC;
1082 goto error;
1083 }
1084 XLALPrintInfo("%s(): analyzing %u samples (%.9lf s) at offset %u (%.9lf s) from epoch %d.%09u s\n", __func__, cuttseries->data->length, cuttseries->data->length * cuttseries->deltaT, start_sample, start_sample * cuttseries->deltaT, tseries->epoch.gpsSeconds, tseries->epoch.gpsNanoSeconds);
1085 if(diagnostics)
1086 XLALWriteLIGOLwXMLArrayREAL8TimeSeries(diagnostics, NULL, cuttseries);
1087
1088 /*
1089 * Window and DFT the time series.
1090 */
1091
1092 XLALPrintInfo("%s(): computing the Fourier transform\n", __func__);
1093 if(!XLALUnitaryWindowREAL8Sequence(cuttseries->data, plane->window)) {
1094 errorcode = XLAL_EFUNC;
1095 goto error;
1096 }
1097 if(XLALREAL8TimeFreqFFT(fseries, cuttseries, fplan)) {
1098 errorcode = XLAL_EFUNC;
1099 goto error;
1100 }
1101 XLALDestroyREAL8TimeSeries(cuttseries);
1102 cuttseries = NULL;
1103
1104 /*
1105 * Normalize the frequency series to the average PSD.
1106 */
1107
1108#if 1
1109 XLALPrintInfo("%s(): normalizing to the average spectrum\n", __func__);
1110 if(!XLALWhitenCOMPLEX16FrequencySeries(fseries, psd)) {
1111 errorcode = XLAL_EFUNC;
1112 goto error;
1113 }
1114 if(diagnostics)
1115 XLALWriteLIGOLwXMLArrayCOMPLEX16FrequencySeries(diagnostics, "whitened", fseries);
1116#endif
1117
1118 /*
1119 * Compute the time-frequency plane from the frequency
1120 * series and channel filters.
1121 */
1122
1123 XLALPrintInfo("%s(): projecting data onto time-frequency plane\n", __func__);
1124 if(XLALFreqSeriesToTFPlane(plane, filter_bank, fseries, rplan)) {
1125 errorcode = XLAL_EFUNC;
1126 goto error;
1127 }
1128
1129 /*
1130 * Compute the excess power for each time-frequency tile
1131 * using the data in the time-frequency plane, and add
1132 * those tiles whose confidence is above threshold to the
1133 * trigger list. Note that because it is possible for
1134 * there to be 0 triggers found, we can't check for errors
1135 * by testing for head == NULL.
1136 */
1137
1138 XLALPrintInfo("%s(): computing the excess power for each tile\n", __func__);
1140 head = XLALComputeExcessPower(plane, filter_bank, head, confidence_threshold);
1141 if(xlalErrno) {
1142 errorcode = XLAL_EFUNC;
1143 goto error;
1144 }
1145 }
1146
1147 /*
1148 * Memory clean-up.
1149 */
1150
1151 XLALPrintInfo("%s(): done\n", __func__);
1152
1153 error:
1157 XLALDestroyREAL8TimeSeries(cuttseries);
1160 XLALDestroyTFPlane(plane);
1161 if(errorcode) {
1163 XLAL_ERROR_NULL(errorcode);
1164 }
1165 return(head);
1166}
static double max(double a, double b)
Definition: EPSearch.c:64
static SnglBurst * XLALTFTileToBurstEvent(const REAL8TimeFrequencyPlane *plane, double tile_start, double tile_length, double f_centre, double bandwidth, double h_rss, double E, double d, double confidence)
Definition: EPSearch.c:756
static void XLALDestroyExcessPowerFilterBank(LALExcessPowerFilterBank *bank)
Destroy and excess power filter bank.
Definition: EPSearch.c:158
static double compute_unwhitened_mean_square(const LALExcessPowerFilterBank *filter_bank, unsigned channel, unsigned channels)
Definition: EPSearch.c:735
static REAL8TimeFrequencyPlane * XLALCreateTFPlane(unsigned tseries_length, double tseries_deltaT, double flow, double bandwidth, double tiling_fractional_stride, double max_tile_bandwidth, double max_tile_duration, const REAL8FFTPlan *plan)
Create and initialize a time-frequency plane object.
Definition: EPSearch.c:396
static LALExcessPowerFilterBank * XLALCreateExcessPowerFilterBank(double filter_deltaF, double flow, double channel_bandwidth, int n_channels, const REAL8FrequencySeries *psd, const REAL8Sequence *two_point_spectral_correlation)
From the power spectral density function, generate the comb of channel filters for the time-frequency...
Definition: EPSearch.c:97
static void XLALDestroyTFPlane(REAL8TimeFrequencyPlane *plane)
Free a time-frequency plane object.
Definition: EPSearch.c:566
static int XLALFreqSeriesToTFPlane(REAL8TimeFrequencyPlane *plane, const LALExcessPowerFilterBank *filter_bank, const COMPLEX16FrequencySeries *fseries, const REAL8FFTPlan *reverseplan)
Definition: EPSearch.c:635
static SnglBurst * XLALComputeExcessPower(const REAL8TimeFrequencyPlane *plane, const LALExcessPowerFilterBank *filter_bank, SnglBurst *head, double confidence_threshold)
Definition: EPSearch.c:797
static double min(double a, double b)
Definition: EPSearch.c:58
static COMPLEX16Sequence * apply_filter(COMPLEX16Sequence *outputseq, const COMPLEX16FrequencySeries *inputseries, const COMPLEX16FrequencySeries *filterseries)
Definition: EPSearch.c:598
int XLALWriteLIGOLwXMLArrayREAL8TimeSeries(LIGOLwXMLStream *xml, const char *comment, const REAL8TimeSeries *series)
int XLALWriteLIGOLwXMLArrayCOMPLEX16FrequencySeries(LIGOLwXMLStream *xml, const char *comment, const COMPLEX16FrequencySeries *series)
int XLALWriteLIGOLwXMLArrayREAL8FrequencySeries(LIGOLwXMLStream *xml, const char *comment, const REAL8FrequencySeries *series)
#define LIGOMETA_SEARCH_MAX
#define LIGOMETA_CHANNEL_MAX
SnglBurst * XLALCreateSnglBurst(void)
void XLALDestroySnglBurstTable(SnglBurst *head)
#define fprintf
const char *const name
double i
double flow
int XLALOverlappedSegmentsCommensurate(int target_length, int segment_length, int segment_shift)
Round target_length down so that an integer number of intervals of length segment_length,...
Definition: EPSearch.c:191
int XLALEPGetTimingParameters(int window_length, int max_tile_length, double fractional_tile_shift, int *psd_length, int *psd_shift, int *window_shift, int *window_pad, int *tiling_length)
Compute and return the timing parameters for an excess power analysis.
Definition: EPSearch.c:234
SnglBurst * XLALEPSearch(LIGOLwXMLStream *diagnostics, const REAL8TimeSeries *tseries, REAL8Window *window, double flow, double bandwidth, double confidence_threshold, double fractional_stride, double maxTileBandwidth, double maxTileDuration)
Generate a linked list of burst events from a time series.
Definition: EPSearch.c:969
COMPLEX16FrequencySeries * XLALCreateExcessPowerFilter(double channel_flow, double channel_width, const REAL8FrequencySeries *psd, const REAL8Sequence *correlation)
Generate the frequency domain channel filter function.
Definition: EPFilters.c:150
double XLALExcessPowerFilterInnerProduct(const COMPLEX16FrequencySeries *filter1, const COMPLEX16FrequencySeries *filter2, const REAL8Sequence *correlation, const REAL8FrequencySeries *psd)
Compute the magnitude of the inner product of two arbitrary channel filters.
Definition: EPFilters.c:73
COMPLEX16FrequencySeries * XLALCreateCOMPLEX16FrequencySeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaF, const LALUnit *sampleUnits, size_t length)
REAL8FrequencySeries * XLALCreateREAL8FrequencySeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaF, const LALUnit *sampleUnits, size_t length)
void XLALDestroyREAL8FrequencySeries(REAL8FrequencySeries *series)
void XLALDestroyCOMPLEX16FrequencySeries(COMPLEX16FrequencySeries *series)
double XLALLogChisqCCDF(double chi2, double dof)
LALNameLength
void * XLALMalloc(size_t n)
void XLALFree(void *p)
RandomParams * XLALCreateRandomParams(INT4 seed)
int XLALNormalDeviates(REAL4Vector *deviates, RandomParams *params)
static const INT4 a
int XLALREAL8ReverseFFT(REAL8Vector *output, const COMPLEX16Vector *input, const REAL8FFTPlan *plan)
void XLALDestroyREAL8FFTPlan(REAL8FFTPlan *plan)
REAL8FFTPlan * XLALCreateReverseREAL8FFTPlan(UINT4 size, int measurelvl)
REAL8FFTPlan * XLALCreateForwardREAL8FFTPlan(UINT4 size, int measurelvl)
REAL8 XLALREAL8SequenceSum(const REAL8Sequence *sequence, size_t first, size_t count)
COMPLEX16Sequence * XLALCreateCOMPLEX16Sequence(size_t length)
void XLALDestroyREAL8Sequence(REAL8Sequence *sequence)
void XLALDestroyCOMPLEX16Sequence(COMPLEX16Sequence *sequence)
REAL8Sequence * XLALCreateREAL8Sequence(size_t length)
REAL8Sequence * XLALREAL8WindowTwoPointSpectralCorrelation(const REAL8Window *window, const REAL8FFTPlan *plan)
int XLALREAL8AverageSpectrumMedian(REAL8FrequencySeries *spectrum, const REAL8TimeSeries *tseries, UINT4 seglen, UINT4 stride, const REAL8Window *window, const REAL8FFTPlan *plan)
int XLALREAL8TimeFreqFFT(COMPLEX16FrequencySeries *freq, const REAL8TimeSeries *tser, const REAL8FFTPlan *plan)
COMPLEX16FrequencySeries * XLALWhitenCOMPLEX16FrequencySeries(COMPLEX16FrequencySeries *fseries, const REAL8FrequencySeries *psd)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
REAL8TimeSeries * XLALCutREAL8TimeSeries(const REAL8TimeSeries *series, size_t first, size_t length)
const LALUnit lalDimensionlessUnit
REAL8Sequence * XLALUnitaryWindowREAL8Sequence(REAL8Sequence *sequence, const REAL8Window *window)
REAL8Window * XLALCreateTukeyREAL8Window(UINT4 length, REAL8 beta)
void XLALDestroyREAL8Window(REAL8Window *window)
REAL8Window * XLALCreateRectangularREAL8Window(UINT4 length)
#define XLAL_ERROR_NULL(...)
#define xlalErrno
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_ERROR(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
int XLALClearErrno(void)
int XLALPrintProgressBar(double)
static _LAL_INLINE_ int XLALIsREAL8FailNaN(REAL8 val)
XLAL_EBADLEN
XLAL_ENOMEM
XLAL_EDATA
XLAL_EFAULT
XLAL_EFUNC
XLAL_EINVAL
LIGOTimeGPS * XLALGPSSetREAL8(LIGOTimeGPS *epoch, REAL8 t)
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
CHAR name[LALNameLength]
COMPLEX16Sequence * data
COMPLEX16 * data
double unwhitened_rms
root mean square of the unwhitened time series corresponding to this filter
Definition: EPSearch.c:81
COMPLEX16FrequencySeries * fseries
Definition: EPSearch.c:80
REAL8Sequence * unwhitened_cross
the mean square cross terms for wide channels (indices same as for twice_channel_overlap)
Definition: EPSearch.c:89
REAL8Sequence * twice_channel_overlap
twice the inner product of filters for neighbouring channels; twice_channel_overlap[0] is twice the i...
Definition: EPSearch.c:88
ExcessPowerFilter * basis_filters
Definition: EPSearch.c:87
INT4 gpsNanoSeconds
double flow
low frequency boundary of TF plane
Definition: EPSearch.c:380
double deltaT
time resolution of the plane
Definition: EPSearch.c:377
REAL8Sequence * unwhitened_channel_buffer
UNDOCUMENTED.
Definition: EPSearch.c:383
int window_shift
by how many samples a window's start should be shifted from the start of the window preceding it
Definition: EPSearch.c:386
LIGOTimeGPS epoch
epoch of data from which this was computed
Definition: EPSearch.c:376
REAL8Window * window
time-domain window applied to input time series for tapering edges to 0
Definition: EPSearch.c:385
char name[LALNameLength]
name of data from which this was computed
Definition: EPSearch.c:375
REAL8Sequence * two_point_spectral_correlation
two-point spectral correlation of the whitened frequency series, computed from the time-domain window...
Definition: EPSearch.c:387
REAL8TimeFrequencyPlaneTiles tiles
time-frequency plane's tiling information
Definition: EPSearch.c:384
double deltaF
TF plane's frequency resolution (channel spacing)
Definition: EPSearch.c:379
REAL8Sequence * channel_buffer
re-usable holding area for the data for a single channel
Definition: EPSearch.c:382
gsl_matrix * channel_data
channel data.
Definition: EPSearch.c:381
double fseries_deltaF
input frequency series' resolution
Definition: EPSearch.c:378
A time-frequency plane.
Definition: EPSearch.c:363
REAL8Sequence * data
LIGOTimeGPS epoch
CHAR name[LALNameLength]
REAL8 * data
REAL8Sequence * data
struct tagSnglBurst * next