LALPulsar  6.1.0.1-b72065a
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  */
92 void 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 
103  INITSTATUS( status );
105 
106  /* make sure arguments are not null */
107  ASSERT( harmonicInfo, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL );
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 
149 void 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 
164  INITSTATUS( status );
166 
167  /* make sure arguments are not null */
168  ASSERT( harmonicsInfo, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL );
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 
210 void 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 
226  INITSTATUS( status );
228 
229  /* make sure arguments are not null */
230  ASSERT( harmonicsInfo, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL );
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 
294  INITSTATUS( status );
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 
342  INITSTATUS( status );
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 
386 void 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 
397  INITSTATUS( status );
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 
464 void 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 
473  INITSTATUS( status );
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 
582 void 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  /* --------------------------------------------- */
606  INITSTATUS( status );
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  */
775 void 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 
785  INITSTATUS( status );
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  */
814 void 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 
824  INITSTATUS( status );
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  */
853 void 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 
867  UINT4 numBins;
868 
869  INITSTATUS( status );
871 
872 
879 
880  f_min = sftVect->data[0].f0;
881  deltaF = sftVect->data->deltaF;
882  numBins = sftVect->data->data->length;
883  f_max = f_min + deltaF * numBins;
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  */
953 void 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 
964  INITSTATUS( status );
966 
967 
968  ASSERT( MultiSFTVect, status, SFTCLEANH_ENULL, SFTCLEANH_MSGENULL );
970  ASSERT( MultiSFTVect->length > 0, status, SFTCLEANH_EVAL, SFTCLEANH_MSGEVAL );
973 
974  numifos = MultiSFTVect->length;
975 
976  if ( linefiles != NULL ) {
977 
978  ASSERT( linefiles->length > 0, status, SFTCLEANH_EVAL, SFTCLEANH_MSGEVAL );
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 }
1010 
#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