Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
lib/SFTClean.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2005 Badri Krishnan, Alicia Sintes, Greg Mendell
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 <libgen.h>
21#include <lal/SFTClean.h>
22#include <lal/SFTfileIO.h>
23#include <lal/LogPrintf.h>
24
25/**
26 * \author Badri Krishnan, Alicia Sintes, Greg Mendell
27 * \addtogroup SFTClean_h
28 * \brief Module containing routines for dealing with spectral disturbances in SFTs
29 *
30 * ### Description ###
31 *
32 * This module contains routines for dealing with lists of known spectral disturbances
33 * in the frequency domain, and using them to clean SFTs.
34 *
35 * The basic input is a text file containing a list of known spectral lines.
36 * NOTE: the legacy format used here is not identical with that of
37 * modern Advanced LIGO linefiles.
38 * To run this code with newer linefiles, they should first be converted into
39 * the legacy format.
40 * An example of the supported format is the following:
41 *
42 * \verbatim
43 * 0.0 0.25 4000 0.0 0.0 0.25Hzlines
44 * 0.0 60.0 20 0.5 0.5 60Hzlines
45 * 0.0 16.0 100 0.0 0.0 16Hzlines
46 * 166.7 0.0 1 0.0 0.0 Calibrationline
47 * 345.0 0.0 1 3.0 3.0 violinmodes
48 * \endverbatim
49 *
50 * The file consists of rows with 6 columns each. Each row has information about
51 * a set of spectral lines of the form \f$ f_n = f_0 + n\Delta f \f$ . The first column
52 * is the start frequency \f$ f_0 \f$ , the second column is the spacing \f$ \Delta f \f$ ,
53 * the third column is the total number of lines, the fourth column is the
54 * left-width of each line (in Hz), the fifth column is the width on the right, and
55 * the last column is a brief comment string (no spaces). If this file is meant to
56 * be used for cleaning SFTs, then certain features which the user must be aware of
57 * are explained in the documentation of the function LALCleanCOMPLEX8SFT().
58 *
59 * ### Uses ###
60 *
61 * \code
62 * void LALFindNumberHarmonics (LALStatus, LineHarmonicsInfo, CHAR)
63 * void LALReadHarmonicsInfo (LALStatus, LineHarmonicsInfo, CHAR)
64 * void LALHarmonics2Lines (LALStatus, LineNoiseInfo, LineHarmonicsInfo)
65 * void LALChooseLines (LALStatus, LineNoiseInfo, LineNoiseInfo, REAL8, REAL8)
66 * void LALCheckLines ( LALStatus, INT4, LineNoiseInfo, REAL8)
67 * void LALFindNumberLines (LALStatus, LineNoiseInfo, CHAR)
68 * void LALReadLineInfo (LALStatus, LineNoiseInfo, CHAR)
69 * void LALCleanCOMPLEX8SFT (LALStatus, SFTtype, INT4, INT4, LineNoiseInfo, RandomParams)
70 * \endcode
71 *
72 */
73
74/* REVISIONS: */
75/* 09/09/05 gam; if (nLinesOut == 0) still need outLine->nLines = nLinesOut; calling function needs to know this */
76/* 09/09/05 gam; make RandomParams *randPar a parameter for CleanCOMPLEX8SFT. Thus only need to */
77/* initialze RandomParams *randPar once and avoid repeatly opening /dev/urandom. */
78/* 09/09/05 gam; prefix function names with LAL in init status macros */
79/* 09/09/05 gam; only assert harmonicInfo and fname in LALFindNumberHarmonic and fix assert of fp. */
80/* Other pointers can be unititialized until nHarmonicSets is determined. */
81
82
83/*
84 * The functions that make up the guts of this module
85 */
86
87
88/**
89 * Looks into the input file containing list of lines, does some checks on the
90 * file format, and calculates the number of harmonic sets in this file.
91 */
92void LALFindNumberHarmonics( LALStatus *status, /**< pointer to LALStatus structure */
93 LineHarmonicsInfo *harmonicInfo, /**< list of harmonics */
94 CHAR *fname /**< input filename */ )
95{
96
97 FILE *fp = NULL;
98 CHAR dump[128];
99 INT4 harmonicCount, r, tempint;
100 REAL8 temp1, temp2, temp3, temp4;
101
102
105
106 /* make sure arguments are not null */
108 /* ASSERT (harmonicInfo->nHarmonicSets > 0, status, SFTCLEANH_EVAL, SFTCLEANH_MSGEVAL);
109 ASSERT (harmonicInfo->startFreq, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL);
110 ASSERT (harmonicInfo->gapFreq, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL);
111 ASSERT (harmonicInfo->numHarmonics, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL);
112 ASSERT (harmonicInfo->leftWing, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL);
113 ASSERT (harmonicInfo->rightWing, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL); */ /* 09/09/05 gam */
115
116 /* open harmonics file for reading */
117 fp = fopen( fname, "r" );
118 /* ASSERT (fname, status, SFTCLEANH_EFILE, SFTCLEANH_MSGEFILE); */ /* 09/09/05 gam */
120
121 harmonicCount = 0;
122
123 do {
124 r = fscanf( fp, "%lf%lf%d%lf%lf%s\n", &temp1, &temp2,
125 &tempint, &temp3, &temp4, dump );
126 /* make sure the line has the right number of entries or is EOF */
127 ASSERT( ( r == 6 ) || ( r == EOF ), status, SFTCLEANH_EHEADER, SFTCLEANH_MSGEVAL );
128 if ( r == 6 ) {
129 harmonicCount++;
130 }
131 } while ( r != EOF );
132
133 harmonicInfo->nHarmonicSets = harmonicCount;
134
135 fclose( fp );
136
138 /* normal exit */
139 RETURN( status );
140}
141
142
143/**
144 * Reads in the contents of the input line-info file and fills up
145 * the LineHarmonicsInfo structure. Appropriate memory must be allocated for
146 * this structure before this function is called.
147 */
148
149void LALReadHarmonicsInfo( LALStatus *status, /**< pointer to LALStatus structure */
150 LineHarmonicsInfo *harmonicsInfo, /**< list of harmonics */
151 CHAR *fname /**< input file */ )
152{
153 /* this reads the information about the lines: central frequency, left wing and
154 right wing */
155 FILE *fp = NULL;
156 INT4 r, count, nHarmonicSets;
157 REAL8 *startFreq = NULL;
158 REAL8 *gapFreq = NULL;
159 INT4 *numHarmonics = NULL;
160 REAL8 *leftWing = NULL;
161 REAL8 *rightWing = NULL;
162 CHAR dump[128];
163
166
167 /* make sure arguments are not null */
176
177 /* open line noise file for reading */
178 fp = fopen( fname, "r" );
180
181 nHarmonicSets = harmonicsInfo->nHarmonicSets;
182 startFreq = harmonicsInfo->startFreq;
183 gapFreq = harmonicsInfo->gapFreq;
184 numHarmonics = harmonicsInfo->numHarmonics;
185 leftWing = harmonicsInfo->leftWing;
186 rightWing = harmonicsInfo->rightWing;
187
188 /* read line information from file */
189 for ( count = 0; count < nHarmonicSets; count++ ) {
190 r = fscanf( fp, "%lf%lf%d%lf%lf%s\n", startFreq + count, gapFreq + count, numHarmonics + count,
191 leftWing + count, rightWing + count, dump );
192 if ( !( r == 6 ) ) {
194 }
195 }
196
197 fclose( fp );
198
200 /* normal exit */
201 RETURN( status );
202
203}
204
205/**
206 * Converts the list of harmonic sets into an explicit list of spectral
207 * lines.
208 */
209
210void LALHarmonics2Lines( LALStatus *status, /**< pointer to LALStatus structure */
211 LineNoiseInfo *lineInfo, /**< output list of explicit lines */
212 LineHarmonicsInfo *harmonicsInfo ) /**< input list of harmonics */
213{
214 /* this reads the information about the lines: central frequency, left wing and
215 right wing */
216
217 INT4 count1, count2, nHarmonicSets, maxCount, position;
218 REAL8 *startFreq;
219 REAL8 *gapFreq;
220 INT4 *numHarmonics;
221 REAL8 *leftWing;
222 REAL8 *rightWing;
223 REAL8 f0, deltaf, leftDeltaf, rightDeltaf;
224
225
228
229 /* make sure arguments are not null */
237
243
244 nHarmonicSets = harmonicsInfo->nHarmonicSets;
245 startFreq = harmonicsInfo->startFreq;
246 gapFreq = harmonicsInfo->gapFreq;
247 numHarmonics = harmonicsInfo->numHarmonics;
248 leftWing = harmonicsInfo->leftWing;
249 rightWing = harmonicsInfo->rightWing;
250
251 position = 0;
252 for ( count1 = 0; count1 < nHarmonicSets; count1++ ) {
253 maxCount = *( numHarmonics + count1 );
254 f0 = *( startFreq + count1 );
255 deltaf = *( gapFreq + count1 );
256 leftDeltaf = *( leftWing + count1 );
257 rightDeltaf = *( rightWing + count1 );
258 for ( count2 = 0; count2 < maxCount; count2++ ) {
259 *( lineInfo->lineFreq + count2 + position ) = f0 + count2 * deltaf;
260 *( lineInfo->leftWing + count2 + position ) = leftDeltaf;
261 *( lineInfo->rightWing + count2 + position ) = rightDeltaf;
262 }
263 position += maxCount;
264 }
265
266
268 /* normal exit */
269 RETURN( status );
270
271}
272
273
274
275
276/**
277 * Finds total number of spectral-lines contained in case the input file is
278 * a list of explicit spectral lines -- obsolete.
279 * Use instead LALFindNumberHarmonics().
280 */
281
283 LineNoiseInfo *lineInfo,
284 CHAR *fname )
285{
286 /* this function counts the number of lines present in the file "fname" and
287 checks that the format of the lines is correct */
288
289 FILE *fp = NULL;
290 REAL8 temp1, temp2, temp3;
291 INT4 lineCount, r;
292 CHAR dump[128];
293
296
297 /* make sure arguments are not null */
300
301 /* open line noise file for reading */
302 fp = fopen( fname, "r" );
304
305 lineCount = 0;
306 do {
307 r = fscanf( fp, "%lf%lf%lf%s\n", &temp1, &temp2, &temp3, dump );
308 /* make sure the line has the right number of entries or is EOF */
309 ASSERT( ( r == 4 ) || ( r == EOF ), status, SFTCLEANH_EHEADER, SFTCLEANH_MSGEVAL );
310 if ( r == 4 ) {
311 lineCount++;
312 }
313 } while ( r != EOF );
314
315 lineInfo->nLines = lineCount;
316
317 fclose( fp );
318
320 /* normal exit */
321 RETURN( status );
322}
323
324/**
325 * Reads information from file containing list of explicit lines - obsolete.
326 * Use instead LALReadHarmonicsInfo()
327 */
328
330 LineNoiseInfo *lineInfo,
331 CHAR *fname )
332{
333 /* this reads the information about the lines: central frequency, left wing and
334 right wing */
335 FILE *fp = NULL;
336 INT4 r, count, nLines;
337 REAL8 *lineFreq = NULL;
338 REAL8 *leftWing = NULL;
339 REAL8 *rightWing = NULL;
340 CHAR dump[128];
341
344
345 /* make sure arguments are not null */
352
353 /* open line noise file for reading */
354 fp = fopen( fname, "r" );
356
357 nLines = lineInfo->nLines;
358 lineFreq = lineInfo->lineFreq;
359 leftWing = lineInfo->leftWing;
360 rightWing = lineInfo->rightWing;
361 /* read line information from file */
362 for ( count = 0; count < nLines; count++ ) {
363 r = fscanf( fp, "%lf%lf%lf%s\n", lineFreq + count, leftWing + count, rightWing + count, dump );
364 if ( !( r == 4 ) ) {
366 }
367 }
368
369 fclose( fp );
370
372 /* normal exit */
373 RETURN( status );
374
375}
376
377
378/**
379 * Takes a set of spectral lines and a frequency range as input and
380 * returns those lines which lie within the specified frequency range. The output
381 * is a reduced list of spectral lines which either lie completely within the
382 * frequency range or whose wings overlap with the frequency range. This is useful
383 * for discarding unnecessary lines to save computational cost and memory.
384 */
385
386void LALChooseLines( LALStatus *status, /**< pointer to LALStatus structure */
387 LineNoiseInfo *outLine, /**< reduced list of lines */
388 LineNoiseInfo *inLine, /**< input list of lines */
389 REAL8 fMin, /**< start of frequency band */
390 REAL8 fMax /**< end of frequency band */
391 )
392{
393
394 INT4 nLinesIn, nLinesOut, j;
395 REAL8 lineFreq, leftWing, rightWing;
396
399
400 /* some sanity checks */
405 ASSERT( inLine->nLines - outLine->nLines == 0, status, SFTCLEANH_EVAL, SFTCLEANH_MSGEVAL );
408
409 nLinesIn = inLine->nLines;
410 nLinesOut = 0;
411 /* loop over lines in inLine structure and see if they are within bounds */
412 for ( j = 0; j < nLinesIn; j++ ) {
413 lineFreq = inLine->lineFreq[j];
414 leftWing = inLine->leftWing[j];
415 rightWing = inLine->rightWing[j];
416 if ( ( lineFreq >= fMin ) && ( lineFreq <= fMax ) ) {
417 outLine->lineFreq[nLinesOut] = lineFreq;
418 outLine->leftWing[nLinesOut] = leftWing;
419 outLine->rightWing[nLinesOut] = rightWing;
420 nLinesOut++;
421 } else if ( ( lineFreq < fMin ) && ( lineFreq + rightWing > fMin ) ) {
422 outLine->lineFreq[nLinesOut] = lineFreq;
423 outLine->leftWing[nLinesOut] = leftWing;
424 outLine->rightWing[nLinesOut] = rightWing;
425 nLinesOut++;
426 } else if ( ( lineFreq > fMax ) && ( lineFreq - leftWing < fMax ) ) {
427 outLine->lineFreq[nLinesOut] = lineFreq;
428 outLine->leftWing[nLinesOut] = leftWing;
429 outLine->rightWing[nLinesOut] = rightWing;
430 nLinesOut++;
431 }
432 }
433
434 /* if there are no lines inband then free memory */
435 if ( nLinesOut == 0 ) {
436 outLine->nLines = nLinesOut; /* 09/09/05 gam; calling function needs to know this. */
437 LALFree( outLine->lineFreq );
438 LALFree( outLine->leftWing );
439 LALFree( outLine->rightWing );
440 } else { /* else reallocate memory for outLine */
441 outLine->nLines = nLinesOut;
442 outLine->lineFreq = ( REAL8 * )LALRealloc( outLine->lineFreq, nLinesOut * sizeof( REAL8 ) );
443 outLine->leftWing = ( REAL8 * )LALRealloc( outLine->leftWing, nLinesOut * sizeof( REAL8 ) );
444 outLine->rightWing = ( REAL8 * )LALRealloc( outLine->rightWing, nLinesOut * sizeof( REAL8 ) );
445 }
446
448 /* normal exit */
449 RETURN( status );
450}
451
452#define TRUE (1==1)
453#define FALSE (1==0)
454
455/**
456 * Function to count how many lines affect a given frequency. Input is a
457 * list of lines and a frequency. The output is an integer which is equal to the
458 * number of lines which intersect this frequency. An output of zero indicates
459 * that the frequencty is not influenced by the lines. Note that the doppler
460 * broadening of the lines is taken into account while deciding whether the
461 * frequency is affected or not.
462 */
463
464void LALCheckLines( LALStatus *status, /**< pointer to LALStatus structure */
465 INT4 *countL, /**< number of lines affecting frequency */
466 LineNoiseInfo *lines, /**< list of lines */
467 REAL8 freq ) /**< frequency to be checked */
468{
469
470 INT4 nLines, j;
471 REAL8 lineFreq, leftWing, rightWing, doppler;
472
475
476 /* sanity checks */
480
481 /* loop over lines and check if freq is affected by the lines */
482 nLines = lines->nLines;
483 *countL = 0;
484 for ( j = 0; j < nLines; j++ ) {
485 lineFreq = lines->lineFreq[j];
486 leftWing = lines->leftWing[j];
487 rightWing = lines->rightWing[j];
488 /* add doppler band to wings */
489 doppler = VTOT * ( lineFreq + rightWing );
490 leftWing += doppler;
491 rightWing += doppler;
492 /* now chech if freq lies in range */
493 if ( ( freq <= lineFreq + rightWing ) && ( freq >= lineFreq - leftWing ) ) {
494 *countL += 1;
495 }
496 }
497
499 /* normal exit */
500 RETURN( status );
501}
502
503
504/**
505 * Function for cleaning a SFT given a set of known spectral disturbances.
506 * The algorithm is the following. For each
507 * spectral line, first the central frequency of the line is converted to a
508 * bin index by round(tBase * freq). If the wings are set to zero, then only this
509 * central bin is cleaned. Note that if the frequency lies between two exactly
510 * resolved frequencies, then only one of these bins is cleaned. The user must
511 * know about the SFT timebase and make sure that the central frequency is an
512 * exactly resolved one. The wingsize is calculated in bins according to
513 * floor(tBase * wingsize). This is done separately for the left and right wings.
514 * Note the use of the floor function. If the wingsize corresponds to say 2.5 bins, then
515 * only 2 bins will be cleaned in addition to the central frequency.
516 *
517 * Having decided which bins are to be cleaned, the next step is to produce random noise
518 * to replace the data in these bins. The fake random noise must mimic the
519 * behavior of the true noise in the vicinity of the spectral disturbance, and we must
520 * therefore estimate the noise floor in the vicinity of the disturbance.
521 * The user specifies a "window size" for cleaning, and this determines how many data
522 * points from the SFT are to be used for estimating this noise floor.
523 * Consider the number of frequency bins on each side of the spectral disturbance
524 * (excluding the wings) given by the user specified window size. The function calculates
525 * the SFT power in these bins and calculates their median. The median is then converted
526 * to a standard deviation for the real and imaginary parts of the SFT data,
527 * taking into account the median bias. There is also a width parameter. This is
528 * an upper limit on the number of bins that will be cleaned on either wing. Thus, if
529 * width is specified to say 3, then only a maximum 3 bins will be cleaned on either side
530 * irrespective of the actual wing size specified. This parameter is present
531 * for historical reasons, and should probably be removed. Currently, it is recommended
532 * to set this sufficiently large (larger that any wing size in bins) so that
533 * it has no effect.
534 *
535 * ### Some "features" that must be kept in mind ###
536 *
537 * The following is part of a email sent to pulgroup on 4/10/05. Some of these points
538 * have already been mentioned above.
539 *
540 * i) If the width of the line to be cleaned is specified to be zero and if the central frequency is midway between two exactly resolved bins, then the code
541 * will only clean one frequency bin and not both as it perhaps should.
542 *
543 * ii) The wings size is converted from Hz to frequency bins using the floor function. So some bins are being dropped at the edges due to rounding off.
544 *
545 * iii) The cleaning uses data from neighboring bins to generate random noise. This is a problem if there are other spectral disturbances in the
546 * neighborhood or if the frequency bin is at the edge of the SFT. Shouldn't one make sure that the data used to generate the random number are
547 * un-contaminated?
548 *
549 * Regarding the first two points, the user is supposed to know the properties of the SFTs which are being cleaned and the list of lines is meant to be
550 * tailored for a particular set of SFTs. Therefore, the user should know the timebaseline of the SFT to make sure that the central frequency value being
551 * specified is a resolved frequency bin and
552 * the wings should be specified correctly. In many cases, the size of the wings, when it is non-zero, is somewhat uncertain, and this uncertainty is often
553 * larger that this rounding off error.
554 *
555 * Perhaps one should specify the frequency bin index of the central frequency value and the wing size also in bins, but this makes the code more cumbersome
556 * and non-intuitive to use.
557 *
558 * Both of these points can be handled by documenting the code better, so that the user knows exactly what is being done and chooses the input
559 * appropriately . I will do this as soon as possible.
560 *
561 * The third point is more difficult. Currently, the code calculates the *median* of the power in the neighboring bins and uses that to generate a random
562 * number with the appropriate standard deviation.
563 *
564 * Let us first consider the cases when there are other spectral disturbances in the neighborhood so that the median estimate might be corrupted. When
565 * there are only a small number of narrow (only few bins) disturbances in
566 * the neighborhood, the use of the median is meant to eliminate the effects of these lines. However, this might not work for the cases when there is a
567 * broad spectral disturbance or when there are a large number of narrow disturbances.
568 *
569 * If there are a large number of narrow spectral disturbances very close to each other, it might make more sense to group them together and consider them
570 * to be one single broad disturbance; we probably won't trust a detection near these lines anyway.
571 *
572 * In the case of a broad spectral feature, it will certainly corrupt the median value and the random number generated won't be correct. The alternative is
573 * to skip the broad feature and take only undisturbed bins further away. This might be ok, but recall that the purpose of the cleaning is to replace a
574 * spectral disturbance with a random number whose distribution is similar to the noise in the *neighborhood* of the disturbance. For colored noise, if we
575 * have to go very far away in frequency to get a undisturbed frequency bin, then the random number distribution won't be correct either.
576 * Edge effects are taken care by making sure that the SFT being read in is large enough. There
577 * must be extra wings to the SFT equal to the window size used for cleaning. If the edge effects are important, then the code using the cleaning routines
578 * must read in the extra bins.
579 *
580 */
581
582void LALCleanCOMPLEX8SFT( LALStatus *status,/**< pointer to LALStatus structure */
583 SFTtype *sft, /**< SFT to be cleaned */
584 INT4 width, /**< maximum width to be cleaned -- set sufficiently large if all bins in each line are to be cleaned*/
585 INT4 window,/**< window size for noise floor estimation in vicinity of a line */
586 LineNoiseInfo *lineInfo, /**< list of lines */
587 RandomParams *randPar /**< parameters for generating random noise */ )
588{
589 /* function to clean the SFT based on the line information read earlier */
590
591 INT4 nLines, count, leftCount, rightCount, lineBin, minBin, maxBin, k, tempk;
592 INT4 leftWingBins, rightWingBins, length, sumBins;
593 REAL8 deltaF, f0, tBase, bias;
594 REAL8 stdPow, medianPow;
595 REAL8 *tempDataPow = NULL;
596 REAL8 *lineFreq = NULL;
597 REAL8 *leftWing = NULL;
598 REAL8 *rightWing = NULL;
599 COMPLEX8 *inData;
600 /* FILE *fp=NULL;
601 INT4 seed, ranCount;
602 RandomParams *randPar=NULL; */ /* 09/09/05 gam; randPar now a function argument */
603 static REAL4Vector *ranVector = NULL;
604 REAL4 *randVal;
605 /* --------------------------------------------- */
608
609 /* Make sure the arguments are not NULL: */
611 inData = sft->data->data;
620 length = sft->data->length;
622
623 /* get the value of RngMedBias from the window size */
624 TRY( LALRngMedBias( status->statusPtr, &bias, 2 * window ), status );
625
626 /* copy pointers from input */
627 nLines = lineInfo->nLines;
628 lineFreq = lineInfo->lineFreq;
629 leftWing = lineInfo->leftWing;
630 rightWing = lineInfo->rightWing;
631
632 deltaF = sft->deltaF;
633 tBase = 1.0 / deltaF;
634 f0 = sft->f0;
635 minBin = lround( f0 / deltaF );
636 maxBin = minBin + length - 1;
637
638 /* allocate memory for storing sft power */
639 tempDataPow = LALMalloc( 2 * window * sizeof( REAL8 ) );
640
641 /* 09/09/05 gam; randPar now a function argument */
642 /* fp=fopen("/dev/urandom", "r");
643 ASSERT(fp, status, SFTCLEANH_EFILE, SFTCLEANH_MSGEFILE);
644
645 ranCount = fread(&seed, sizeof(seed), 1, fp);
646 ASSERT(ranCount==1, status, SFTCLEANH_EREAD, SFTCLEANH_MSGEREAD);
647
648 fclose(fp); */
649
650 /* calculate total number of bins to see how many random numbers must be generated */
651 sumBins = 0;
652 for ( count = 0; count < nLines; count++ ) {
653 {
654 INT4 tempSumBins;
655 tempSumBins = floor( tBase * leftWing[count] ) + floor( tBase * rightWing[count] );
656 sumBins += tempSumBins < 2 * width ? tempSumBins : 2 * width;
657 }
658 }
659
660 /* TRY ( LALCreateRandomParams (status->statusPtr, &randPar, seed), status); */ /* 09/09/05 gam; randPar now a function argument */
661 TRY( LALCreateVector( status->statusPtr, &ranVector, 2 * ( sumBins + nLines ) ), status );
662 TRY( LALNormalDeviates( status->statusPtr, ranVector, randPar ), status );
663 /* TRY ( LALDestroyRandomParams (status->statusPtr, &randPar), status); */ /* 09/09/05 gam; randPar now a function argument */
664
665 tempk = 0;
666 /* loop over the lines */
667 for ( count = 0; count < nLines; count++ ) {
668
669 /* find frequency bins for line frequency and wings */
670 lineBin = lround( tBase * lineFreq[count] );
671 leftWingBins = floor( tBase * leftWing[count] );
672 rightWingBins = floor( tBase * rightWing[count] );
673
674 /* check that central frequency of the line is within band of sft */
675 if ( ( lineBin >= minBin ) && ( lineBin <= maxBin ) ) {
676
677 /* cut wings if wider than width parameter */
678 if ( ( leftWingBins > width ) || ( rightWingBins > width ) ) {
679 LogPrintf( LOG_NORMAL, "%s: Cutting wings of line %d/%d from [-%d,+%d] to width=%d.\n", __func__, count, nLines, leftWingBins, rightWingBins, width );
680 }
681 leftWingBins = leftWingBins < width ? leftWingBins : width;
682 rightWingBins = rightWingBins < width ? rightWingBins : width;
683
684 /* estimate the sft power in "window" # of bins each side */
685 if ( 2 * window > ( maxBin - minBin ) ) {
686 LogPrintf( LOG_NORMAL, "%s: Window of +-%d bins around lineBin=%d does not fit within SFT range [%d,%d], noise floor estimation will be compromised.\n", __func__, window, lineBin, minBin, maxBin );
687 }
688 if ( ( window < leftWingBins ) || ( window <= rightWingBins ) ) {
689 LogPrintf( LOG_NORMAL, "%s: Window of +-%d bins around lineBin=%d does not extend further than line wings [-%d,+%d], noise floor estimation will be compromised by the very same line that is supposed to be cleaned.\n", __func__, window, lineBin, leftWingBins, rightWingBins );
690 }
691 for ( k = 0; k < window ; k++ ) {
692 if ( maxBin - lineBin - rightWingBins - k > 0 ) {
693 inData = sft->data->data + lineBin - minBin + rightWingBins + k + 1;
694 } else {
695 inData = sft->data->data + length - 1;
696 }
697
698 tempDataPow[k] = ( crealf( *inData ) ) * ( crealf( *inData ) ) + ( cimagf( *inData ) ) * ( cimagf( *inData ) );
699
700 if ( lineBin - minBin - leftWingBins - k > 0 ) {
701 inData = sft->data->data + lineBin - minBin - leftWingBins - k - 1;
702 } else {
703 inData = sft->data->data;
704 }
705
706 tempDataPow[k + window] = ( crealf( *inData ) ) * ( crealf( *inData ) ) + ( cimagf( *inData ) ) * ( cimagf( *inData ) );
707 }
708
709 gsl_sort( tempDataPow, 1, 2 * window );
710 medianPow = gsl_stats_median_from_sorted_data( tempDataPow, 1, 2 * window );
711 stdPow = sqrt( medianPow / ( 2 * bias ) );
712
713 /* set sft value at central frequency to noise */
714 inData = sft->data->data + lineBin - minBin;
715
716 randVal = ranVector->data + tempk;
717 *( inData ) = crectf( stdPow * ( *randVal ), cimagf( *( inData ) ) );
718 tempk++;
719
720 randVal = ranVector->data + tempk;
721 *( inData ) = crectf( crealf( *( inData ) ), stdPow * ( *randVal ) );
722 tempk++;
723
724 /* now go left and set the left wing to noise */
725 /* make sure that we are always within the sft band */
726 /* and set bins to zero only if Wing width is smaller than "width" */
727 for ( leftCount = 0; leftCount < leftWingBins; leftCount++ ) {
728 if ( ( lineBin - minBin - leftCount > 0 ) ) {
729 inData = sft->data->data + lineBin - minBin - leftCount - 1;
730
731 randVal = ranVector->data + tempk;
732 *( inData ) = crectf( stdPow * ( *randVal ), cimagf( *( inData ) ) );
733 tempk++;
734
735 randVal = ranVector->data + tempk;
736 *( inData ) = crectf( crealf( *( inData ) ), stdPow * ( *randVal ) );
737 tempk++;
738 }
739 }
740
741 /* now go right making sure again to stay within the sft band */
742 for ( rightCount = 0; rightCount < rightWingBins; rightCount++ ) {
743 if ( ( maxBin - lineBin - rightCount > 0 ) ) {
744 inData = sft->data->data + lineBin - minBin + rightCount + 1;
745
746 randVal = ranVector->data + tempk;
747 *( inData ) = crectf( stdPow * ( *randVal ), cimagf( *( inData ) ) );
748 tempk++;
749
750 randVal = ranVector->data + tempk;
751 *( inData ) = crectf( crealf( *( inData ) ), stdPow * ( *randVal ) );
752 tempk++;
753 }
754 }
755
756 }
757 } /* end loop over lines */
758
759 /* free memory */
760 LALFree( tempDataPow );
761 TRY( LALDestroyVector( status->statusPtr, &ranVector ), status );
762
764 /* normal exit */
765 RETURN( status );
766}
767
768
769
770
771/**
772 * Function to clean a sft vector -- calls LALCleanCOMPLEX8SFT repeatedly for each
773 * sft in vector
774 */
775void LALCleanSFTVector( LALStatus *status, /**< pointer to LALStatus structure */
776 SFTVector *sftVect, /**< SFTVector to be cleaned */
777 INT4 width, /**< maximum width to be cleaned -- set sufficiently large if all bins in each line are to be cleaned*/
778 INT4 window, /**< window size for noise floor estimation in vicinity of a line */
779 LineNoiseInfo *lineInfo, /**< list of lines */
780 RandomParams *randPar /**< parameters for generating random noise */ )
781{
782
783 UINT4 k;
784
787
799
800 for ( k = 0; k < sftVect->length; k++ ) {
801 TRY( LALCleanCOMPLEX8SFT( status->statusPtr, sftVect->data + k, width, window, lineInfo, randPar ), status );
802 }
803
805 /* normal exit */
806 RETURN( status );
807}
808
809
810/**
811 * Function to clean a sft vector -- calls LALCleanCOMPLEX8SFT repeatedly for each
812 * sft in vector
813 */
814void LALCleanMultiSFTVect( LALStatus *status, /**< pointer to LALStatus structure */
815 MultiSFTVector *multVect, /**< SFTVector to be cleaned */
816 INT4 width, /**< maximum width to be cleaned -- set sufficiently large if all bins in each line are to be cleaned*/
817 INT4 window, /**< window size for noise floor estimation in vicinity of a line */
818 LineNoiseInfo *lineInfo, /**< list of lines */
819 RandomParams *randPar /**< parameters for generating random noise */ )
820{
821
822 UINT4 k;
823
826
837
838
839 for ( k = 0; k < multVect->length; k++ ) {
840 TRY( LALCleanSFTVector( status->statusPtr, multVect->data[k], width, window, lineInfo, randPar ), status );
841 }
842
844 /* normal exit */
845 RETURN( status );
846}
847
848
849/**
850 * function to remove lines from a sft vector given a file
851 * containing list of lines
852 */
853void LALRemoveKnownLinesInSFTVect( LALStatus *status, /**< pointer to LALStatus structure */
854 SFTVector *sftVect, /**< SFTVector to be cleaned */
855 INT4 width, /**< maximum width to be cleaned -- set sufficiently large if all bins in each line are to be cleaned*/
856 INT4 window, /**< window size for noise floor estimation in vicinity of a line */
857 CHAR *linefile, /**< file with list of lines */
858 RandomParams *randPar ) /**< for creating random numbers */
859{
860
861
862 static LineNoiseInfo lines, lines2;
864 INT4 nLines = 0, count1, nHarmonicSets;
865
868
871
872
879
880 f_min = sftVect->data[0].f0;
881 deltaF = sftVect->data->deltaF;
882 numBins = sftVect->data->data->length;
884
885 TRY( LALFindNumberHarmonics( status->statusPtr, &harmonics, linefile ), status );
886 nHarmonicSets = harmonics.nHarmonicSets;
887
888 if ( nHarmonicSets > 0 ) { /* nothing to do otherwise */
889 harmonics.startFreq = ( REAL8 * )LALMalloc( harmonics.nHarmonicSets * sizeof( REAL8 ) );
890 harmonics.gapFreq = ( REAL8 * )LALMalloc( harmonics.nHarmonicSets * sizeof( REAL8 ) );
891 harmonics.numHarmonics = ( INT4 * )LALMalloc( harmonics.nHarmonicSets * sizeof( INT4 ) );
892 harmonics.leftWing = ( REAL8 * )LALMalloc( harmonics.nHarmonicSets * sizeof( REAL8 ) );
893 harmonics.rightWing = ( REAL8 * )LALMalloc( harmonics.nHarmonicSets * sizeof( REAL8 ) );
894
895
896 TRY( LALReadHarmonicsInfo( status->statusPtr, &harmonics, linefile ), status );
897
898 nLines = 0;
899 for ( count1 = 0; count1 < nHarmonicSets; count1++ ) {
900 nLines += *( harmonics.numHarmonics + count1 );
901 }
902
903 lines.nLines = nLines;
904 lines.lineFreq = ( REAL8 * )LALMalloc( nLines * sizeof( REAL8 ) );
905 lines.leftWing = ( REAL8 * )LALMalloc( nLines * sizeof( REAL8 ) );
906 lines.rightWing = ( REAL8 * )LALMalloc( nLines * sizeof( REAL8 ) );
907
908 TRY( LALHarmonics2Lines( status->statusPtr, &lines, &harmonics ), status );
909
910
911 lines2.nLines = nLines;
912 lines2.lineFreq = ( REAL8 * )LALMalloc( nLines * sizeof( REAL8 ) );
913 lines2.leftWing = ( REAL8 * )LALMalloc( nLines * sizeof( REAL8 ) );
914 lines2.rightWing = ( REAL8 * )LALMalloc( nLines * sizeof( REAL8 ) );
915
916 TRY( LALChooseLines( status->statusPtr, &lines2, &lines, f_min, f_max ), status );
917 nLines = lines2.nLines;
918
919 /* clean the sft vector if there were any lines between f_min and f_max*/
920 if ( nLines > 0 ) {
921 TRY( LALCleanSFTVector( status->statusPtr, sftVect, width, window, &lines2, randPar ), status );
922
923 /* if nLines2 == 0 then it is freed inside LALChooseLines -- change this? */
924 LALFree( lines2.lineFreq );
925 LALFree( lines2.leftWing );
926 LALFree( lines2.rightWing );
927
928 }
929
930 /* free memory */
931 LALFree( lines.lineFreq );
932 LALFree( lines.leftWing );
933 LALFree( lines.rightWing );
934
935 LALFree( harmonics.startFreq );
936 LALFree( harmonics.gapFreq );
937 LALFree( harmonics.numHarmonics );
938 LALFree( harmonics.leftWing );
939 LALFree( harmonics.rightWing );
940
941 } /* if nHarmonicSets > 0 */
942
943
945 /* normal exit */
946 RETURN( status );
947}
948
949/**
950 * top level function to remove lines from a multi sft vector given a list of files
951 * containing list of known spectral lines
952 */
953void LALRemoveKnownLinesInMultiSFTVector( LALStatus *status, /**< pointer to LALStatus structure */
954 MultiSFTVector *MultiSFTVect, /**< SFTVector to be cleaned */
955 INT4 width, /**< maximum width to be cleaned */
956 INT4 window, /**< window size for noise floor estimation in vicinity of a line */
957 LALStringVector *linefiles, /**< list of per-detector files with list of lines (the basename of each file must start with a canonical IFO name) */
958 RandomParams *randPar ) /**< for creating random numbers */
959{
960
961 UINT4 k, j, numifos;
962 CHAR *ifo;
963
966
967
970 ASSERT( MultiSFTVect->length > 0, status, SFTCLEANH_EVAL, SFTCLEANH_MSGEVAL );
973
974 numifos = MultiSFTVect->length;
975
976 if ( linefiles != NULL ) {
977
980
981 /* loop over linefiles and clean the relevant SFTs */
982 for ( k = 0; k < linefiles->length; k++ ) {
983 ifo = NULL;
984 /* try to get the ifo name from the linefile name */
985 if ( ( ifo = XLALGetChannelPrefix( basename( linefiles->data[k] ) ) ) == NULL ) {
987 }
988
989 /* loop over ifos and see if any matches */
990 for ( j = 0; j < numifos; j++ ) {
991 if ( strncmp( ifo, MultiSFTVect->data[j]->data->name, 3 ) == 0 ) {
992 /* clean the sftvector which has matched */
993 TRY( LALRemoveKnownLinesInSFTVect( status->statusPtr, MultiSFTVect->data[j],
994 width, window, linefiles->data[k], randPar ), status );
995 }
996
997 } /* loop over ifos */
998
999 LALFree( ifo );
1000
1001 } /* loop over linefiles */
1002
1003 } /* if linefiles != NULL */
1004
1005
1007 /* normal exit */
1008 RETURN( status );
1009}
#define __func__
log an I/O error, i.e.
int j
int k
#define LALRealloc(p, n)
#define LALMalloc(n)
#define LALFree(p)
#define ABORT(statusptr, code, mesg)
#define TRY(func, statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define fscanf
double REAL8
#define crectf(re, im)
char CHAR
uint32_t UINT4
float complex COMPLEX8
int32_t INT4
float REAL4
#define VTOT
Total detector velocity/c TO BE CHANGED DEPENDING ON DETECTOR.
Definition: LUT.h:207
void LogPrintf(LogLevel_t, const char *format,...) _LAL_GCC_PRINTF_FORMAT_(2
LOG_NORMAL
static const INT4 r
void LALNormalDeviates(LALStatus *status, REAL4Vector *deviates, RandomParams *params)
void LALRngMedBias(LALStatus *status, REAL8 *biasFactor, INT4 blkSize)
#define SFTCLEANH_ENULL
Definition: SFTClean.h:93
#define SFTCLEANH_EHEADER
Definition: SFTClean.h:95
#define SFTCLEANH_MSGENULL
Definition: SFTClean.h:103
void LALCleanMultiSFTVect(LALStatus *status, MultiSFTVector *multVect, INT4 width, INT4 window, LineNoiseInfo *lineInfo, RandomParams *randPar)
Function to clean a sft vector – calls LALCleanCOMPLEX8SFT repeatedly for each sft in vector.
Definition: lib/SFTClean.c:814
#define SFTCLEANH_ELINENAME
Definition: SFTClean.h:98
void LALFindNumberLines(LALStatus *status, LineNoiseInfo *lineInfo, CHAR *fname)
Finds total number of spectral-lines contained in case the input file is a list of explicit spectral ...
Definition: lib/SFTClean.c:282
#define SFTCLEANH_MSGEVAL
Definition: SFTClean.h:107
void LALRemoveKnownLinesInSFTVect(LALStatus *status, SFTVector *sftVect, INT4 width, INT4 window, CHAR *linefile, RandomParams *randPar)
function to remove lines from a sft vector given a file containing list of lines
Definition: lib/SFTClean.c:853
void LALRemoveKnownLinesInMultiSFTVector(LALStatus *status, MultiSFTVector *MultiSFTVect, INT4 width, INT4 window, LALStringVector *linefiles, RandomParams *randPar)
top level function to remove lines from a multi sft vector given a list of files containing list of k...
Definition: lib/SFTClean.c:953
void LALCleanSFTVector(LALStatus *status, SFTVector *sftVect, INT4 width, INT4 window, LineNoiseInfo *lineInfo, RandomParams *randPar)
Function to clean a sft vector – calls LALCleanCOMPLEX8SFT repeatedly for each sft in vector.
Definition: lib/SFTClean.c:775
#define SFTCLEANH_EFILE
Definition: SFTClean.h:94
#define SFTCLEANH_MSGELINENAME
Definition: SFTClean.h:108
void LALChooseLines(LALStatus *status, LineNoiseInfo *outLine, LineNoiseInfo *inLine, REAL8 fMin, REAL8 fMax)
Takes a set of spectral lines and a frequency range as input and returns those lines which lie within...
Definition: lib/SFTClean.c:386
#define SFTCLEANH_EVAL
Definition: SFTClean.h:97
void LALReadLineInfo(LALStatus *status, LineNoiseInfo *lineInfo, CHAR *fname)
Reads information from file containing list of explicit lines - obsolete.
Definition: lib/SFTClean.c:329
void LALCheckLines(LALStatus *status, INT4 *countL, LineNoiseInfo *lines, REAL8 freq)
Function to count how many lines affect a given frequency.
Definition: lib/SFTClean.c:464
void LALFindNumberHarmonics(LALStatus *status, LineHarmonicsInfo *harmonicInfo, CHAR *fname)
Looks into the input file containing list of lines, does some checks on the file format,...
Definition: lib/SFTClean.c:92
void LALReadHarmonicsInfo(LALStatus *status, LineHarmonicsInfo *harmonicsInfo, CHAR *fname)
Reads in the contents of the input line-info file and fills up the LineHarmonicsInfo structure.
Definition: lib/SFTClean.c:149
void LALHarmonics2Lines(LALStatus *status, LineNoiseInfo *lineInfo, LineHarmonicsInfo *harmonicsInfo)
Converts the list of harmonic sets into an explicit list of spectral lines.
Definition: lib/SFTClean.c:210
#define SFTCLEANH_MSGEFILE
Definition: SFTClean.h:104
void LALCleanCOMPLEX8SFT(LALStatus *status, SFTtype *sft, INT4 width, INT4 window, LineNoiseInfo *lineInfo, RandomParams *randPar)
Function for cleaning a SFT given a set of known spectral disturbances.
Definition: lib/SFTClean.c:582
CHAR * XLALGetChannelPrefix(const CHAR *name)
Find the valid CW detector prefix.
Definition: SFTnaming.c:203
void LALDestroyVector(LALStatus *, REAL4Vector **)
void LALCreateVector(LALStatus *, REAL4Vector **, UINT4)
long long count
Definition: hwinject.c:371
int deltaF
CHAR name[LALNameLength]
COMPLEX8Sequence * data
A vector of COMPLEX8FrequencySeries.
COMPLEX8FrequencySeries * data
Pointer to the data array.
UINT4 length
Number of elements in array.
COMPLEX8 * data
structure for storing the contents of the input list of known spectral disturbances
Definition: SFTClean.h:143
REAL8 * gapFreq
frequency difference between adjacent harmonics in Hz
Definition: SFTClean.h:146
REAL8 * rightWing
width to the right in Hz
Definition: SFTClean.h:149
INT4 nHarmonicSets
number of sets of harmonics
Definition: SFTClean.h:144
REAL8 * leftWing
width to the left of each line in set in Hz
Definition: SFTClean.h:148
INT4 * numHarmonics
Number of harmonics.
Definition: SFTClean.h:147
REAL8 * startFreq
starting frequency of set in Hz
Definition: SFTClean.h:145
structure for storing list of spectral lines – constructed by expanding list of harmonics
Definition: SFTClean.h:132
REAL8 * lineFreq
central frequency of the line in Hz
Definition: SFTClean.h:134
REAL8 * leftWing
width to the left from central frequency in Hz
Definition: SFTClean.h:135
REAL8 * rightWing
width to the right in Hz
Definition: SFTClean.h:136
INT4 nLines
number of lines
Definition: SFTClean.h:133
A collection of SFT vectors – one for each IFO in a multi-IFO search.
Definition: SFTfileIO.h:179
UINT4 length
number of ifos
Definition: SFTfileIO.h:183
SFTVector ** data
sftvector for each ifo
Definition: SFTfileIO.h:184
REAL4 * data
double f_min
double f_max