polka.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Bruce Allen, Bernd Machenschalk, Reinhard Prix, Xavier Siemens
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /*********************************************************************************/
00021 /*                     polka - the pulsar koinzidenz analysis code               */
00022 /*                                                                               */
00023 /*                                     X. Siemens                                */
00024 /*                   (takes in two Fstats file to look for coincidence)          */
00025 /*                                                                               */
00026 /*                                  UWM - March  2004                            */
00027 /*********************************************************************************/
00028 
00029 
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <math.h>
00034 
00035 #include <lal/LALDatatypes.h>
00036 #include <lal/LALMalloc.h>
00037 #include <lal/LALConstants.h>
00038 #include <lal/LALStatusMacros.h>
00039 #include <lal/ConfigFile.h>
00040 
00041 #include <lalapps.h>
00042 
00043 #include "getopt.h"
00044 
00045 RCSID ("$Id: polka.c,v 1.49 2007/06/08 15:29:51 bema Exp $");
00046 
00047 
00048 /* some error codes and messages */
00049 #define POLKAC_ENULL            1
00050 #define POLKAC_ENONULL          2
00051 #define POLKAC_ESYS             3
00052 #define POLKAC_EINVALIDFSTATS   4
00053 #define POLKAC_EMEM             5
00054 
00055 #define POLKAC_MSGENULL         "Arguments contained an unexpected null pointer"
00056 #define POLKAC_MSGENONULL       "Input pointer was not NULL"
00057 #define POLKAC_MSGESYS          "System call failed (probably file IO"
00058 #define POLKAC_MSGEINVALIDFSTATS "Invalid Fstats file"
00059 #define POLKAC_MSGEMEM          "Sorry, ran out of memory... bye."
00060 
00061 #ifndef USE_BOINC
00062 #define USE_BOINC 0
00063 #endif
00064 
00065 #if USE_BOINC
00066 #include "boinc_api.h"
00067 #include "filesys.h"
00068 
00069 #define fopen boinc_fopen
00070 extern CHAR *Outputfilename;
00071 #endif
00072 
00073 struct PolkaCommandLineArgsTag 
00074 {
00075   char *FstatsFile1; /* Names of Fstat files to be read in */
00076   char *FstatsFile2;
00077   char *FstatsFile3; /* Names of Fstat files to be read in to compute false alarm */
00078   char *FstatsFile4;
00079   char *OutputFile;
00080   REAL8 Deltaf;      /* Size of coincidence window in Hz */
00081   REAL8 DeltaAlpha;  /* Size of coincidence window in radians */
00082   REAL8 DeltaDelta;  /* Size of coincidence window in radians */
00083   REAL8 fmin;        /* Minimum frequency of candidate in first IFO */
00084   REAL8 fmax;        /* Maximum frequency of candidate in first IFO */
00085   UINT4 EAH;         /* Einstein at home flag for alternative output */ 
00086 } PolkaCommandLineArgs;
00087 
00088 typedef struct CandidateTag 
00089 {
00090   UINT4 length;    /* number of candidates in list */
00091   REAL8 *f;        /* Frequency */
00092   REAL8 *Alpha;    /* longitude */
00093   REAL8 *Delta;    /* latitude */
00094   REAL8 *F;        /* Maximum value of F for the cluster */
00095   REAL8 *fa;       /* false alarm probability for that candidate */
00096   UINT4 *Ctag;     /* tag for candidate if it's been found in coincidence */
00097   INT4  *CtagCounter;     /* contains the cumulative sum of coincident candidates so far */
00098 } CandidateList;
00099 
00100 typedef struct CoincidentCandidateTag 
00101 {
00102   REAL8 f1;             /* Frequencies */
00103   REAL8 f2;
00104   REAL8 Alpha1;         /* longitude */
00105   REAL8 Alpha2;
00106   REAL8 Delta1;         /* latitude */
00107   REAL8 Delta2;
00108   REAL8 F1;             /* Maximum value of F for the cluster */
00109   REAL8 F2;
00110   REAL8 fa;             /* false alarm probabilities for that candidate */
00111   REAL8 fa1;
00112   REAL8 fa2;            
00113 } CoincidentCandidate;
00114 
00115 typedef struct CoincidentPairsTag 
00116 {
00117   UINT4 c1;             /* number in Fstats file that corresponds to first member of pair */
00118   UINT4 c2;             /* number in Fstats file that corresponds to second member of pair */
00119   REAL8 fa;             /* joint false alarm for that pair */
00120 } CoincidentPairs;
00121 
00122 
00123 int ReadCommandLine(int argc,char *argv[],struct PolkaCommandLineArgsTag *CLA);
00124 int ReadCandidateFiles(struct PolkaCommandLineArgsTag CLA);
00125 int compare1F(const void *ip, const void *jp);
00126 int compare2F(const void *ip, const void *jp);
00127 int compare3F(const void *ip, const void *jp);
00128 int compare4F(const void *ip, const void *jp);
00129 int compare2f(const void *ip, const void *jp);
00130 int compareCCfa(const void *ip, const void *jp);
00131 int compareCPfa(const void *ip, const void *jp);
00132 void locate(double xx[], int n, double x, int *j, int *indices);
00133 void ReadOneCandidateFile (LALStatus *stat, CandidateList *CList, const char *fname);
00134 
00135 extern INT4 lalDebugLevel;
00136 
00137 CandidateList CList1, CList2, CList3, CList4; /* treat up to 4 candidate files */
00138 
00139 CoincidentCandidate *CC;
00140 CoincidentPairs *CP;
00141 
00142 #ifndef FALSE
00143 #define FALSE (1==0)
00144 #endif
00145 #ifndef TRUE
00146 #define TRUE  (1==1)
00147 #endif
00148 
00149 /* main() mapped to polka() if using boinc */
00150 #if USE_BOINC
00151 int polka(int argc,char *argv[])
00152 #else
00153 int main(int argc,char *argv[]) 
00154 #endif
00155 {
00156   INT4 *indices1F=NULL,*indices2f=NULL,*indices2F=NULL,*indicesCCfa=NULL,*indices3F=NULL,*indices4F=NULL;
00157   REAL8 MaxAngularDistance;
00158   UINT4 i;
00159   UINT4 numCoincidences = 0;
00160   FILE *fpOut;
00161   BOOLEAN haveFile3 = FALSE;
00162   BOOLEAN haveFile4 = FALSE;
00163 #if USE_BOINC
00164   static char resolved_filename[256];
00165 #endif
00166   lalDebugLevel = 1;
00167 
00168   /* Reads command line arguments */
00169   if (ReadCommandLine(argc,argv,&PolkaCommandLineArgs)) return 1;
00170 
00171   /* define some shortcuts for convenience */
00172   haveFile3 = (PolkaCommandLineArgs.FstatsFile3 != NULL);
00173   haveFile4 = (PolkaCommandLineArgs.FstatsFile4 != NULL);
00174 
00175   /* Reads in candidare files */
00176   if (ReadCandidateFiles(PolkaCommandLineArgs)) return 2;
00177 
00178   /* Prepare list of coincident candidates */
00179 
00180   /* create arrays of indices */
00181   if (!(indices1F=(INT4 *)LALMalloc(sizeof(INT4) * CList1.length))){
00182     fprintf(stderr,"Unable to allocate index array in main\n");
00183     return 1;
00184   }
00185   if (!(indices2F=(INT4 *)LALMalloc(sizeof(INT4) * CList2.length))){
00186     fprintf(stderr,"Unable to allocate index array in main\n");
00187     return 1;
00188   }
00189   if (!(indices2f=(INT4 *)LALMalloc(sizeof(INT4) * CList2.length))){
00190     fprintf(stderr,"Unable to allocate index array in main\n");
00191     return 1;
00192   }
00193 
00194   /* populate arrays of indices */
00195   for (i=0;i<CList1.length;i++) indices1F[i]=i;
00196   for (i=0;i<CList2.length;i++) indices2F[i]=i;
00197   for (i=0;i<CList2.length;i++) indices2f[i]=i;
00198 
00199   /* sort arrays of indices in DECREASING order*/
00200   qsort((void *)indices1F, (size_t)CList1.length, sizeof(int), compare1F);
00201   qsort((void *)indices2F, (size_t)CList2.length, sizeof(int), compare2F);
00202   qsort((void *)indices2f, (size_t)CList2.length, sizeof(int), compare2f);
00203 
00204   if ( haveFile3 )
00205     {
00206       if (!(indices3F=(INT4 *)LALMalloc(sizeof(INT4)*CList3.length))){
00207         fprintf(stderr,"Unable to allocate index array in main\n");
00208         return 1;
00209       }
00210       for (i=0;i<CList3.length;i++) indices3F[i]=i;
00211       qsort((void *)indices3F, (size_t)CList3.length, sizeof(int), compare3F);
00212     }      
00213   if ( haveFile4 )
00214     {
00215       if (!(indices4F=(INT4 *)LALMalloc(sizeof(INT4)*CList4.length))){
00216         fprintf(stderr,"Unable to allocate index array in main\n");
00217         return 1;
00218       }
00219       for (i=0;i<CList4.length;i++) indices4F[i]=i;
00220       qsort((void *)indices4F, (size_t)CList4.length, sizeof(int), compare4F);
00221     }      
00222 
00223   numCoincidences = 0; /* kounts koinzident events */
00224   MaxAngularDistance=sqrt(pow(PolkaCommandLineArgs.DeltaAlpha,2)+pow(PolkaCommandLineArgs.DeltaDelta,2))+1e-8;
00225 
00226   /* go through list */
00227 
00228   if (CList1.length !=0 && CList2.length !=0 )
00229     {
00230       for (i=0; i < CList1.length; i++)
00231         {
00232           REAL8 f1min,f1max,difff;
00233           REAL8 f1,Alpha1,Delta1,F1;
00234           int if2min,if2max,f;
00235 
00236           /* Minimum and maximum frequencies acceptable for coincidence */
00237           f1 = CList1.f[indices1F[i]];
00238           /* if candidate frequency does not lie within bounds specified by user go to next in list */
00239           if(f1 < PolkaCommandLineArgs.fmin || f1 > PolkaCommandLineArgs.fmax) continue;
00240 
00241           f1min=f1-PolkaCommandLineArgs.Deltaf;
00242           f1max=f1+PolkaCommandLineArgs.Deltaf;
00243           
00244           /* Find nearest index to f1min and f1max; function explained below */
00245           locate(CList2.f,CList2.length,f1min,&if2min,indices2f);
00246           locate(CList2.f,CList2.length,f1max,&if2max,indices2f);
00247 
00248           /* look for repeats in the frequency and make sure we include them in our search for coincidences */
00249           /* This potential problem was pointed out by Peter Shawhan during the code review */ 
00250           /* look only until second to last */
00251           while ( (if2min < (int)CList2.length-2) && (CList2.f[indices2f[if2min]] == CList2.f[indices2f[if2min+1]]) )
00252             if2min++;
00253           /* then check last one separately to avoid seg faults */
00254           if ( (if2min == (int)CList2.length-2) && (CList2.f[indices2f[if2min]] == CList2.f[indices2f[if2min+1]]))
00255             if2min++;
00256           /* look only until second  */
00257           while ( (if2max > 1) && (CList2.f[indices2f[if2max]] == CList2.f[indices2f[if2max-1]]) )
00258             if2max--;
00259           /* then check first one separately to avoid seg faults */
00260           if ( (if2max == 1) && (CList2.f[indices2f[if2max]] == CList2.f[indices2f[if2max-1]]))
00261             if2max--;
00262 
00263           /* alpha */
00264           Alpha1=CList1.Alpha[indices1F[i]];
00265           /* delta */
00266           Delta1=CList1.Delta[indices1F[i]];
00267           /* F */
00268           F1=CList1.F[indices1F[i]];
00269       
00270           for (f=if2max; f <= if2min; f++)
00271             {
00272               REAL8 Alpha2=CList2.Alpha[indices2f[f]],Delta2=CList2.Delta[indices2f[f]];
00273               REAL8 n1[3],n2[3],AngularDistance;
00274               REAL8 cosAngularDistance;
00275           
00276               n1[0]=cos(Alpha1)*cos(Delta1);
00277               n1[1]=sin(Alpha1)*cos(Delta1);
00278               n1[2]=sin(Delta1);
00279               
00280               n2[0]=cos(Alpha2)*cos(Delta2);
00281               n2[1]=sin(Alpha2)*cos(Delta2);
00282               n2[2]=sin(Delta2);
00283               
00284               cosAngularDistance=n1[0]*n2[0]+n1[1]*n2[1]+n1[2]*n2[2];
00285               if (cosAngularDistance  >  1.0) cosAngularDistance =  1.0;
00286               if (cosAngularDistance  < -1.0) cosAngularDistance = -1.0;
00287               
00288               AngularDistance=acos(cosAngularDistance);
00289 
00290               difff=fabs(f1 - CList2.f[indices2f[f]]);
00291               
00292               /* check difference in frequencies because we're not guaranteed 
00293                  sufficient closeness at the edges of array */
00294               if ( difff <= PolkaCommandLineArgs.Deltaf) 
00295                 {
00296                   if ( AngularDistance <= MaxAngularDistance )
00297                     {   
00298                       int j;
00299                       CoincidentCandidate *thisCC;
00300                       CoincidentPairs *thisCP;
00301 
00302                       /* tag the candidates that have been found in coincidence */
00303                       CList1.Ctag[indices1F[i]]=1;
00304                       CList2.Ctag[indices2f[f]]=1;
00305                   
00306                       /* seems we found a coincident candidate: let's make space for it to be stored */
00307                       numCoincidences ++;
00308                       if ( (CC = LALRealloc ( CC, numCoincidences * sizeof(CoincidentCandidate) )) == NULL) {
00309                         fprintf (stderr, "Error: ran out of memory ... goodbye.\n");
00310                         return 1;       /* got lazy here.. */
00311                       }
00312                       if ( (CP = LALRealloc ( CP, numCoincidences * sizeof(CoincidentPairs) )) == NULL) {
00313                         fprintf (stderr, "Error: ran out of memory ... goodbye.\n");
00314                         return 1;       /* got lazy here.. */
00315                       }
00316                       
00317                       thisCC = &(CC[ numCoincidences - 1]);     /* point to current new coincidences */
00318                       thisCP = &(CP[ numCoincidences - 1]);     /* point to current new coincidences */
00319                       
00320                       thisCC->f1 = f1;
00321                       thisCC->Alpha1 = Alpha1;
00322                       thisCC->Delta1 =Delta1;
00323                       thisCC->F1 = F1;
00324 
00325                       if ( haveFile3 )
00326                         {
00327                           locate(CList3.F,CList3.length,thisCC->F1,&j,indices3F);
00328                           thisCC->fa1=(REAL8)(j+1)/(REAL8)CList3.length;
00329                         }
00330                       else thisCC->fa1=(REAL8)(i+1)/(REAL8)CList1.length;
00331 
00332                       thisCC->f2=CList2.f[indices2f[f]];
00333                       thisCC->Alpha2=CList2.Alpha[indices2f[f]];
00334                       thisCC->Delta2=CList2.Delta[indices2f[f]];
00335                       thisCC->F2=CList2.F[indices2f[f]];
00336 
00337                       if ( haveFile4 )
00338                         {
00339                           locate(CList4.F,CList4.length,thisCC->F2,&j,indices4F);
00340                           thisCC->fa2=(REAL8)(j+1)/(REAL8)CList4.length;
00341                         }else{
00342                           locate(CList2.F,CList2.length,thisCC->F2,&j,indices2F);
00343                           thisCC->fa2=(REAL8)(j+1)/(REAL8)CList2.length;
00344                         }
00345                       
00346                       thisCC->fa = thisCC->fa1 * thisCC->fa2;
00347                       
00348                       thisCP->c1=indices1F[i];
00349                       thisCP->c2=indices2f[f];
00350                       thisCP->fa=thisCC->fa;
00351 
00352                     }
00353                 }
00354             }
00355       /* next candidate for 1st ifo */
00356         }     
00357     }
00358 
00359 
00360   /* allocate space */
00361   if (numCoincidences != 0){ 
00362     if (!(indicesCCfa=(INT4 *)LALMalloc(sizeof(INT4) * numCoincidences))){
00363       fprintf(stderr,"Unable to allocate index array in main\n");
00364       return 1;
00365     }
00366   }
00367 
00368   for (i=0; i < numCoincidences; i++) 
00369     indicesCCfa[i]=i;
00370 
00371   /* open and write the file */
00372 #if USE_BOINC
00373   if (boinc_resolve_filename(PolkaCommandLineArgs.OutputFile, resolved_filename, sizeof(resolved_filename))) {
00374     fprintf(stderr,
00375             "Can't resolve file \"%s\"\n"
00376             "If running a non-BOINC test, create [INPUT] or touch [OUTPUT] file\n",
00377             PolkaCommandLineArgs.OutputFile);
00378     boinc_finish(2);
00379   }
00380   fpOut=fopen(resolved_filename,"w");
00381 #else
00382   fpOut=fopen(PolkaCommandLineArgs.OutputFile,"w");      
00383 #endif
00384   if (!PolkaCommandLineArgs.EAH)
00385     {
00386       /* sort in increasing probability of joint false alarm */
00387       qsort((void *)indicesCCfa, (size_t)numCoincidences, sizeof(int), compareCCfa);
00388       for (i=0; i < numCoincidences; i++) 
00389         {
00390           UINT4 k = indicesCCfa[i];  /* print out ordered by joint significance */
00391           fprintf(fpOut,"%1.15e %e %e %e %e %1.15e %e %e %e %e %e\n",
00392                   CC[k].f1, CC[k].Alpha1, CC[k].Delta1,
00393                   CC[k].F1, CC[k].fa1,
00394                   CC[k].f2, CC[k].Alpha2, CC[k].Delta2,
00395                   CC[k].F2, CC[k].fa2, CC[k].fa);
00396         }
00397     }else{
00398       fprintf(fpOut,"%%1\n");
00399       {
00400         int k=-1;    
00401         for (i=0; i < CList1.length; i++)
00402           {
00403             if (CList1.Ctag[i]) 
00404               {
00405                 k++;
00406                 fprintf(fpOut,"%16.12f %10.8f %10.8f %20.17f\n",
00407                         CList1.f[i],CList1.Alpha[i],CList1.Delta[i],CList1.F[i]);
00408                 CList1.CtagCounter[i]=k;
00409               }
00410           }
00411       }
00412       fprintf(fpOut,"%%2\n");
00413       {
00414         int k=-1;
00415         for (i=0; i < CList2.length; i++)
00416           {
00417             if (CList2.Ctag[i]) 
00418               {
00419                 k++;
00420                 fprintf(fpOut,"%16.12f %10.8f %10.8f %20.17f\n",
00421                         CList2.f[i],CList2.Alpha[i],CList2.Delta[i],CList2.F[i]);  
00422                 CList2.CtagCounter[i]=k;
00423               }    
00424           }
00425       }
00426       fprintf(fpOut,"%%coincidences\n");
00427       /* sort in increasing probability of joint false alarm */
00428       qsort((void *)indicesCCfa, (size_t)numCoincidences, sizeof(int), compareCPfa);
00429       
00430       for (i=0; i < numCoincidences; i++) 
00431         {
00432           UINT4 k = indicesCCfa[i];  /* print out ordered by joint significance */
00433           fprintf(fpOut,"%d %d %e\n",
00434                   CList1.CtagCounter[CP[k].c1],CList2.CtagCounter[CP[k].c2],CP[k].fa);
00435         }
00436 
00437 /*       for (i=0; i < numCoincidences; i++)  */
00438 /*      { */
00439 /*        UINT4 k = indicesCCfa[i];   */
00440 /*        fprintf(stdout,"%1.15le %le %le %le %le %1.15le %le %le %le %le %le\n",  */
00441 /*                CList1.f[CP[k].c1],CList1.Alpha[CP[k].c1],CList1.Delta[CP[k].c1],CList1.F[CP[k].c1],CList1.fa[CP[k].c1], */
00442 /*                CList2.f[CP[k].c2],CList2.Alpha[CP[k].c2],CList2.Delta[CP[k].c2],CList2.F[CP[k].c2],CList2.fa[CP[k].c2],CP[k].fa); */
00443 /*      } */
00444       /* cat polka_out-short | awk '{print $1" "$2" "$3" "$4" "$6" "$7" "$8" "$9" "$11}' > la3 */
00445 
00446     }
00447   fprintf(fpOut,"%%DONE\n");    
00448 #if USE_BOINC
00449   /* write end marker */
00450   Outputfilename=resolved_filename;
00451 #endif
00452   fclose(fpOut);
00453 
00454   LALFree(indices1F);
00455   LALFree(indices2F);
00456   LALFree(indices2f);
00457 
00458   /* freeing a CList is a bit tedious, so we use a macro */
00459 #define freeCList(x) do { LALFree((x).f); LALFree((x).Alpha); LALFree((x).Delta); LALFree((x).F); LALFree((x).fa); LALFree((x).Ctag);LALFree((x).CtagCounter);} while(0)
00460   
00461   freeCList(CList1);
00462   freeCList(CList2);
00463   if (haveFile3 ) {
00464     freeCList(CList3);
00465     LALFree(indices3F);  
00466   }
00467   if (haveFile4 ) 
00468     {
00469       freeCList(CList4);
00470       LALFree(indices4F);  
00471     }
00472   
00473   if (numCoincidences != 0){ 
00474     LALFree ( CC );
00475     LALFree ( CP );
00476     LALFree(indicesCCfa);
00477 
00478   }
00479   
00480   LALCheckMemoryLeaks(); 
00481 
00482   return 0;
00483 
00484 }
00485 
00486 /*******************************************************************************/
00487 /* Explanation of locate
00488 
00489 the function locate returns the lower value of the two indices of the array xx
00490 that bound the value given x.
00491 
00492 consider xx to be in descending order:
00493 
00494 fmax                                      fmin
00495    |     |     |     |     |     |     |     |
00496 j: 0     1     2     3     4     5     6     7
00497 
00498             ^           ^            ^
00499          f2+Df          f2        f2-Df
00500 
00501 locate will return if2max=1 and if2min=5
00502 
00503 In this example:
00504  
00505 1) at the beginning jl=0 and ju=8
00506 
00507 2) since ju-jl > 1:
00508    jm=(0+8)/2=4
00509    since f2 > xx[4]: then ju=4
00510 
00511 3) since ju-jl > 1:
00512    jm=(0+4)/2=2
00513    since f2 < xx[2]: then jl=2
00514 
00515 4) since ju-jl > 1:
00516    jm=(2+4)/2=3
00517    since f2 < xx[3]: then jl=3
00518 
00519 5) since ju-jl=1   
00520    return j=jl=3
00521 
00522 */
00523 
00524 void locate(double xx[], int n, double x, int *j, int *indices) 
00525      /* locates x in array of xx */
00526 { 
00527 
00528  int ju,jm,jl; 
00529 
00530 
00531  if( x <= xx[indices[n-1]] ) 
00532    {
00533      *j=n-1;
00534      return;
00535    }
00536  if( x >= xx[indices[0]] ) 
00537    {
00538      *j=0;
00539      return;
00540    }
00541 
00542  jl=0;  
00543  ju=n;
00544 
00545  while (ju-jl > 1) 
00546    {
00547      jm=(ju+jl)/2;
00548      if ( x <= xx[indices[jm]] ) 
00549        jl=jm;
00550      else ju=jm; 
00551    }
00552  
00553  *j=jl;
00554 
00555 }
00556 
00557 
00558 /*******************************************************************************/
00559 
00560 /* Sorting function to sort 1st candidate into DECREASING order of F */
00561 int compare1F(const void *ip, const void *jp)
00562 {
00563   REAL8 di, dj;
00564 
00565   di=CList1.F[*(const int *)ip];
00566   dj=CList1.F[*(const int *)jp];
00567 
00568   if (di<dj)
00569     return 1;
00570   
00571   if (di==dj)
00572     return (ip < jp);
00573 
00574   return -1;
00575 }
00576 /*******************************************************************************/
00577 
00578 /* Sorting function to sort 1st candidate into DECREASING order of F */
00579 int compare2F(const void *ip, const void *jp)
00580 {
00581   REAL8 di, dj;
00582 
00583   di=CList2.F[*(const int *)ip];
00584   dj=CList2.F[*(const int *)jp];
00585 
00586   if (di<dj)
00587     return 1;
00588   
00589   if (di==dj)
00590     return (ip < jp);
00591 
00592   return -1;
00593 }
00594 
00595 /*******************************************************************************/
00596 
00597 /* Sorting function to sort 1st candidate into DECREASING order of F */
00598 int compare3F(const void *ip, const void *jp)
00599 {
00600   REAL8 di, dj;
00601 
00602   di=CList3.F[*(const int *)ip];
00603   dj=CList3.F[*(const int *)jp];
00604 
00605   if (di<dj)
00606     return 1;
00607   
00608   if (di==dj)
00609     return (ip < jp);
00610 
00611   return -1;
00612 }
00613 /*******************************************************************************/
00614 
00615 /* Sorting function to sort 1st candidate into DECREASING order of F */
00616 int compare4F(const void *ip, const void *jp)
00617 {
00618   REAL8 di, dj;
00619 
00620   di=CList4.F[*(const int *)ip];
00621   dj=CList4.F[*(const int *)jp];
00622 
00623   if (di<dj)
00624     return 1;
00625   
00626   if (di==dj)
00627     return (ip < jp);
00628 
00629   return -1;
00630 }
00631 
00632 /*******************************************************************************/
00633 
00634 /* Sorting function to sort second candidate list into DECREASING order of f */
00635 int compare2f(const void *ip, const void *jp)
00636 {
00637   REAL8 di, dj;
00638 
00639   di=CList2.f[*(const int *)ip];
00640   dj=CList2.f[*(const int *)jp];
00641 
00642   if (di<dj)
00643     return 1;
00644   
00645   if (di==dj)
00646     return (ip < jp);
00647 
00648   return -1;
00649 }
00650 /*******************************************************************************/
00651 
00652 /* Sorting function to sort second candidate list into increasing order of fa */
00653 int compareCCfa(const void *ip, const void *jp)
00654 {
00655   REAL8 di, dj;
00656 
00657   di=CC[*(const int *)ip].fa;
00658   dj=CC[*(const int *)jp].fa;
00659 
00660   if (di<dj)
00661     return -1;
00662   
00663   if (di==dj)
00664     return (ip > jp);
00665 
00666   return 1;
00667 }
00668 
00669 
00670 /*******************************************************************************/
00671 
00672 /* Sorting function to sort pair list into increasing order of fa */
00673 int compareCPfa(const void *ip, const void *jp)
00674 {
00675   REAL8 di, dj;
00676 
00677   di=CP[*(const int *)ip].fa;
00678   dj=CP[*(const int *)jp].fa;
00679 
00680   if (di<dj)
00681     return -1;
00682   
00683   if (di==dj)
00684     return (ip > jp);
00685 
00686   return 1;
00687 }
00688 
00689 
00690 /*******************************************************************************/
00691 
00692 int ReadCandidateFiles(struct PolkaCommandLineArgsTag CLA)
00693 {
00694   LALStatus status = blank_status;      /* initialize status */
00695 
00696   ReadOneCandidateFile (&status, &CList1, CLA.FstatsFile1);
00697   if (status.statusCode != 0) {
00698     REPORTSTATUS (&status);
00699     return 1;
00700   }
00701   ReadOneCandidateFile (&status, &CList2, CLA.FstatsFile2);
00702   if (status.statusCode != 0) {
00703     REPORTSTATUS (&status);
00704     return 1;
00705   }
00706 
00707   if (CLA.FstatsFile3)
00708     {
00709       ReadOneCandidateFile (&status, &CList3, CLA.FstatsFile3);
00710       if (status.statusCode != 0) {
00711         REPORTSTATUS (&status);
00712         return 1;
00713       }
00714     }
00715 
00716   if (CLA.FstatsFile4)
00717     {
00718       ReadOneCandidateFile (&status, &CList4, CLA.FstatsFile4);
00719       if (status.statusCode != 0) {
00720         REPORTSTATUS (&status);
00721         return 1;
00722       }
00723     }
00724 
00725   return 0;
00726 
00727 } /* ReadCandidateFiles() */
00728 
00729 /*******************************************************************************/
00730 
00731 
00732 int ReadCommandLine(int argc,char *argv[],struct PolkaCommandLineArgsTag *CLA) 
00733 {
00734   INT2 errflg = 0;
00735   INT4 c; 
00736   INT4 option_index = 0;
00737 
00738   const char *optstring = "h1:2:3:4:f:a:d:m:M:o:s:e:b";
00739   struct option long_options[] =
00740     {
00741       {"fstatsfile1",           required_argument, 0,   '1'},
00742       {"fstatsfile2",           required_argument, 0,   '2'},
00743       {"frequency-window",      required_argument, 0,   'f'},
00744       {"delta-window",          required_argument, 0,   'd'},
00745       {"alpha-window",          required_argument, 0,   'a'},
00746       {"fmin",                  required_argument, 0,   's'},
00747       {"fmax",                  required_argument, 0,   'e'},
00748       {"outputfile",            required_argument, 0,   'o'},
00749       {"EAHoutput",             no_argument, 0,         'b'},
00750       {"help",                  no_argument, 0,         'h'},
00751       {0, 0, 0, 0}
00752     };
00753 
00754   /* Initialize default values */
00755   CLA->FstatsFile1=NULL;
00756   CLA->FstatsFile2=NULL;
00757   CLA->FstatsFile3=NULL;
00758   CLA->FstatsFile4=NULL;
00759   CLA->OutputFile=NULL;
00760   CLA->Deltaf=0.0;
00761   CLA->DeltaAlpha=0;
00762   CLA->DeltaDelta=0;
00763   CLA->fmin=0;
00764   CLA->fmax=0;
00765   CLA->EAH=0;
00766 
00767   /* reset gnu getopt */
00768   optind = 0;
00769 
00770   /* Scan through list of command line arguments */
00771   while (1)
00772     {
00773       c = getopt_long(argc, argv, optstring, long_options, &option_index);      
00774       if (c == -1) 
00775         break;
00776       switch (c) {
00777       case '1':
00778         /* SFT directory */
00779         CLA->FstatsFile1=optarg;
00780         break;
00781       case '2':
00782         /* calibration files directory */
00783         CLA->FstatsFile2=optarg;
00784         break;
00785       case '3':
00786         /* SFT directory */
00787         CLA->FstatsFile3=optarg;
00788         break;
00789       case '4':
00790         /* calibration files directory */
00791         CLA->FstatsFile4=optarg;
00792         break;
00793       case 'o':
00794         /* calibration files directory */
00795         CLA->OutputFile=optarg;
00796         break;
00797       case 'f':
00798         /* Spin down order */
00799         CLA->Deltaf=atof(optarg);
00800         break;
00801       case 'a':
00802         /* Spin down order */
00803         CLA->DeltaAlpha=atof(optarg);
00804         break;
00805       case 's':
00806         /* Spin down order */
00807         CLA->fmin=atof(optarg);
00808         break;
00809       case 'e':
00810         /* Spin down order */
00811         CLA->fmax=atof(optarg);
00812         break;
00813       case 'd':
00814         /* Spin down order */
00815         CLA->DeltaDelta=atof(optarg);
00816         break;
00817       case 'b':
00818         /* Spin down order */
00819         CLA->EAH=1;
00820         break;
00821       case 'h':
00822         /* print usage/help message */
00823         fprintf(stderr,"Arguments are (defaults):\n");
00824         fprintf(stderr,"\t--fstatsfile1 (-1)\tSTRING\tFirst candidates Fstats file\n");
00825         fprintf(stderr,"\t--fstatsfile1 (-2)\tSTRING\tSecond candidates Fstats file\n");
00826         fprintf(stderr,"\t--fstatsfile3 (-3)\tSTRING\tFstats used to compute false alarm for -1\n");
00827         fprintf(stderr,"\t--fstatsfile4 (-4)\tSTRING\tFstats used to compute false alarm for -2\n");
00828         fprintf(stderr,"\t--outputfile  (-o)\tSTRING\tName of ouput candidates file\n");
00829         fprintf(stderr,"\t--frequency-window (-f)\tFLOAT\tFrequency window in Hz (0.0)\n");
00830         fprintf(stderr,"\t--alpha-window (-a)\tFLOAT\tAlpha window in radians (0.0)\n");
00831         fprintf(stderr,"\t--delta-window (-d)\tFLOAT\tDelta window in radians (0.0)\n");
00832         fprintf(stderr,"\t--fmin (-s)\tFLOAT\t Minimum frequency of candidate in 1st IFO\n");
00833         fprintf(stderr,"\t--fmax (-e)\tFLOAT\t Maximum frequency of candidate in 1st IFO\n");
00834         fprintf(stderr,"\t--EAHoutput (-b)\tFLAG\t Einstein at home output flag. \n");
00835         fprintf(stderr,"\t--help        (-h)\t\tThis message\n");
00836         exit(0);
00837         break;
00838       default:
00839         /* unrecognized option */
00840         errflg++;
00841         fprintf(stderr,"Unrecognized option argument %c\n",c);
00842         exit(1);
00843         break;
00844       }
00845     }
00846 
00847   if(CLA->FstatsFile1 == NULL)
00848     {
00849       fprintf(stderr,"No 1st candidates file specified; input with -1 option.\n");
00850       fprintf(stderr,"For help type ./polka -h \n");
00851       return 1;
00852     }      
00853   if(CLA->FstatsFile2 == NULL)
00854     {
00855       fprintf(stderr,"No 2nd candidates file specified; input with -2 option.\n");
00856       fprintf(stderr,"For help type ./polka -h \n");
00857       return 1;
00858     }      
00859   if(CLA->OutputFile == NULL)
00860     {
00861       fprintf(stderr,"No ouput filename specified; input with -o option.\n");
00862       fprintf(stderr,"For help type ./polka -h \n");
00863       return 1;
00864     }      
00865 
00866   if(CLA->fmin == 0.0)
00867     {
00868       fprintf(stderr,"No minimum frequency specified.\n");
00869       fprintf(stderr,"For help type ./polka -h \n");
00870       return 1;
00871     }      
00872 
00873   if(CLA->fmax == 0.0)
00874     {
00875