Пример #1
0
/* parse command line arguments using LALgetopt_long to get ring params */
int coh_PTF_parse_options(struct coh_PTF_params *params,int argc,char **argv )
{

  CHAR                         ifo[LIGOMETA_IFO_MAX];
  UINT4                        ifoNumber;
  static struct coh_PTF_params localparams;
  memset( &localparams.haveTrig, 0, LAL_NUM_IFO * sizeof(int) );
  struct LALoption                long_options[] =
  {
    { "verbose",            no_argument, &vrbflg, 1 },
    { "strain-data",        no_argument, &localparams.strainData, 1 },
    { "zero-data",          no_argument, &localparams.zeroData, 1 },
    { "theoretical-spectrum",     no_argument, &localparams.whiteSpectrum, 1 },
    { "write-raw-data",     no_argument, &localparams.writeRawData, 1 },
    { "write-data",         no_argument, &localparams.writeProcessedData, 1 },
    { "write-inv-spectrum", no_argument, &localparams.writeInvSpectrum, 1 },
    { "write-segment",      no_argument, &localparams.writeSegment, 1 },
    { "write-filter-output",no_argument, &localparams.writeFilterOutput, 1 },
    { "analyze-inj-segs-only",no_argument, &localparams.analyzeInjSegsOnly, 1 },
    { "do-null-stream",     no_argument, &localparams.doNullStream, 1 },
    { "do-trace-snr",       no_argument, &localparams.doTraceSNR, 1 },
    { "do-bank-veto",       no_argument, &localparams.doBankVeto, 1 },
    { "do-auto-veto",       no_argument, &localparams.doAutoVeto, 1 },
    { "do-chi-square",      no_argument, &localparams.doChiSquare, 1 },
    { "do-sngl-chi-tests",  no_argument, &localparams.doSnglChiSquared, 1},
    { "do-clustering",      no_argument, &localparams.clusterFlag, 1},
/*    {"g1-data",             no_argument, &(haveTrig[LAL_IFO_G1]), 1 },*/
    {"h1-data",             no_argument, &(localparams.haveTrig[LAL_IFO_H1]),1},
    {"h2-data",             no_argument, &(localparams.haveTrig[LAL_IFO_H2]),1},
    {"l1-data",             no_argument, &(localparams.haveTrig[LAL_IFO_L1]),1},
/*    {"t1-data",             no_argument, &(haveTrig[LAL_IFO_T1]), 1 },*/
    {"v1-data",             no_argument, &(localparams.haveTrig[LAL_IFO_V1]),1},
    {"face-on-analysis",    no_argument, &(localparams.faceOnAnalysis),1},
    {"face-away-analysis",    no_argument, &(localparams.faceAwayAnalysis),1},
    {"dynamic-template-length",no_argument, &(localparams.dynTempLength),1},
    {"store-amplitude-params",no_argument, &(localparams.storeAmpParams),1},
    {"analyse-segment-end", no_argument, &(localparams.analSegmentEnd),1},
    {"do-short-slides", no_argument, &(localparams.doShortSlides),1},
    { "write-sngl-inspiral-table", no_argument, &(localparams.writeSnglInspiralTable),1},
    { "help",               no_argument, 0, 'h' },
    { "version",            no_argument, 0, 'V' },
    { "simulated-data",          required_argument, 0, '6' },
    { "gps-start-time",          required_argument, 0, 'a' },
    { "gps-start-time-ns",       required_argument, 0, 'A' },
    { "gps-end-time",            required_argument, 0, 'b' },
    { "gps-end-time-ns",         required_argument, 0, 'B' },
    { "trigger-time",            required_argument, 0, '<' },
    { "trigger-time-ns",         required_argument, 0, '>' },
    { "h1-channel-name",         required_argument, 0, 'c' },
    { "h1-frame-cache",          required_argument, 0, 'D' },
    { "h2-channel-name",         required_argument, 0, 'x' },
    { "h2-frame-cache",          required_argument, 0, 'X' },
    { "l1-channel-name",         required_argument, 0, 'y' },
    { "l1-frame-cache",          required_argument, 0, 'Y' },
    { "v1-channel-name",         required_argument, 0, 'z' },
    { "v1-frame-cache",          required_argument, 0, 'Z' },
    { "low-template-freq",       required_argument, 0, 'e' },
    { "low-filter-freq",         required_argument, 0, 'H' },
    { "high-filter-freq",        required_argument, 0, 'I' },
    { "highpass-frequency",      required_argument, 0, 'E' },
    { "injection-file",          required_argument, 0, 'i' },
    { "snr-threshold",           required_argument, 0, 'j' },
    { "spin-snr-threshold",      required_argument, 0, '2' },
    { "sngl-snr-threshold",      required_argument, 0, '1' },
    { "trig-time-window",        required_argument, 0, 'J' },
    { "user-tag",                required_argument, 0, 'k' },
    { "ifo-tag",                 required_argument, 0, 'K' },
    { "non-spin-snr2-threshold", required_argument, 0, 'l' },
    { "spin-snr2-threshold",     required_argument, 0, 'L' },
    { "spin-bank",               required_argument, 0, 'm' },
    { "non-spin-bank",           required_argument, 0, 'M' },
    { "only-segment-numbers",    required_argument, 0, 'n' },
    { "only-template-numbers",   required_argument, 0, 'N' },
    { "output-file",             required_argument, 0, 'o' },
    { "bank-file",               required_argument, 0, 'O' },
    { "num-auto-chisq-points",   required_argument, 0, 'p' },
    { "auto-veto-time-step",     required_argument, 0, 'P' },
    { "num-chi-square-bins",     required_argument, 0, 'q' },
    { "chi-square-threshold",    required_argument, 0, 'Q' },
    { "random-seed",             required_argument, 0, 'r' },
    { "dynamic-range-factor",    required_argument, 0, 'R' },
    { "sample-rate",             required_argument, 0, 's' },
    { "segment-duration",        required_argument, 0, 'S' },
    { "psd-segment-duration",        required_argument, 0, '9' },
    { "bank-veto-templates",     required_argument, 0, 't' },
    { "inverse-spec-length",     required_argument, 0, 'T' },
    { "trig-start-time",         required_argument, 0, 'u' },
    { "trig-end-time",           required_argument, 0, 'U' },
    { "block-duration",          required_argument, 0, 'w' },
    { "pad-data",                required_argument, 0, 'W' },
    { "right-ascension",         required_argument, 0, 'f' },
    { "declination",             required_argument, 0, 'F' },
    { "sky-error",               required_argument, 0, 'g' },
    { "timing-accuracy",         required_argument, 0, 'G' },
    { "approximant",             required_argument, 0, 'C' },
    { "order",                   required_argument, 0, 'v' },
    { "h1-slide-segment",        required_argument, 0, '!' }, 
    { "h2-slide-segment",        required_argument, 0, '&' },
    { "l1-slide-segment",        required_argument, 0, '(' },
    { "v1-slide-segment",        required_argument, 0, ')' },
    { "sky-positions-file",      required_argument, 0, '#' },
    { "fft-level",               required_argument, 0, '|' },
    { "cluster-window",          required_argument, 0, '4' },
    { "inj-search-window",       required_argument, 0, '3' },
    { "inj-mchirp-window",       required_argument, 0, '5' },
    { "ligo-calibrated-data",    required_argument, 0, '7' }, 
    { "virgo-calibrated-data",   required_argument, 0, '8' }, 
    { "short-slide-offset",      required_argument, 0, '@' },
    { 0, 0, 0, 0 }
  };
  char args[] = "a:A:b:B:c:C:D:e:E:f:F:g:G:h:H:i:I:j:J:k:K:l:L:m:M:n:N:o:O:p:P:q:Q:r:R:s:S:t:T:u:U:v:V:w:W:x:X:y:Y:z:Z:1:2:3:4:5:6:7:8:9:<:>:!:&:(:):#:|:@";
  char *program = argv[0];

  /* set default values for parameters before parsing arguments */
  coh_PTF_default_params( &localparams );

  while ( 1 )
  {
    int option_index = 0;
    int c;

    c = LALgetopt_long_only( argc, argv, args, long_options, &option_index );
    if ( c == -1 ) /* end of options */
      break;

    switch ( c )
    {
      case 0: /* if option set a flag, nothing else to do */
        if ( long_options[option_index].flag )
          break;
        else
          error( "error parsing option %s with argument %s\n",
              long_options[option_index].name, LALoptarg );
      case 'a': /* gps-start-time */
        localparams.startTime.gpsSeconds = atol( LALoptarg );
        break;
      case 'A': /* gps-start-time-ns */
        localparams.startTime.gpsNanoSeconds = atol( LALoptarg );
        break;
      case 'b': /* gps-end-time */
        localparams.endTime.gpsSeconds = atol( LALoptarg );
        break;
      case 'B': /* gps-end-time-ns */
        localparams.endTime.gpsNanoSeconds = atol( LALoptarg );
        break;
      case '<': /* trigger-time */
        localparams.trigTime.gpsSeconds = atol( LALoptarg );
        break;
      case '>': /* trigger-time-ns */ 
        localparams.trigTime.gpsNanoSeconds = atol( LALoptarg );
        break;
      case 'c': /* h1 channel-name */
        localparams.channel[LAL_IFO_H1] = LALoptarg;
        break;
      case 'D': /* h1 frame-cache */
        localparams.dataCache[LAL_IFO_H1] = LALoptarg;
        break;
      case 'y': /* l1 channel-name */
        localparams.channel[LAL_IFO_L1] = LALoptarg;
        break;
      case 'Y': /* l1 frame-cache */
        localparams.dataCache[LAL_IFO_L1] = LALoptarg;
        break;
      case 'z': /* v1 channel-name */
        localparams.channel[LAL_IFO_V1] = LALoptarg;
        break;
      case 'Z': /* v1 frame-cache */
        localparams.dataCache[LAL_IFO_V1] = LALoptarg;
        break;
      case 'x': /* h2 channel-name */
        localparams.channel[LAL_IFO_H2] = LALoptarg;
        break;
      case 'X': /* h2 frame-cache */
        localparams.dataCache[LAL_IFO_H2] = LALoptarg;
        break;
      case 'e': /* start frequency of template generation */
        localparams.lowTemplateFrequency = atof( LALoptarg );
        break;
      case 'H': /* start frequency of matched filter */
        localparams.lowFilterFrequency = atof( LALoptarg );
        break;
      case 'I': /* End frequency of matched filter */
        localparams.highFilterFrequency = atof( LALoptarg );
        break;
      case 'E': /* highpass-frequency */
        localparams.highpassFrequency = atof( LALoptarg );
        break;
      case 'C': /* waveform approximant */
        /* This will directly fail if the approximant is not a valid one.
           However the user may get to a call to FindChirpTDTemplate and find
           out only then that the approximant is not supported in there. */
        localparams.approximant =  XLALSimInspiralGetApproximantFromString(LALoptarg);
        break;
      case '6': /* Simulated data option */
        localparams.simData = 1;
        if ( ! strcmp( "WhiteNoise",LALoptarg))
        {
          localparams.simDataType = WHITE_PSD;
        }
        else if ( ! strcmp( "ILIGONoise",LALoptarg))
        {
          localparams.simDataType = ILIGO_PSD;
        }
        else if ( ! strcmp( "ALIGONoise",LALoptarg))
        {
          localparams.simDataType = ALIGO_PSD;
        }
        else
        {
          fprintf( stderr, "invalid argument to --%s:\n"
              "unknown data type specified:"
              "%s valid options are WhiteNoise, ILIGONoise or ALIGONoise",
              long_options[option_index].name, LALoptarg );
          exit(1);
        }
        break;
      case 'v': /* PN order of waveform */        
        if ( ! strcmp( "twoPN", LALoptarg ) )
        {
          localparams.order = LAL_PNORDER_TWO;
        }
        else if ( ! strcmp( "twoPointFivePN", LALoptarg ) )
        {
          localparams.order = LAL_PNORDER_TWO_POINT_FIVE;
        }
        else if ( ! strcmp( "threePN", LALoptarg ) )
        {
          localparams.order = LAL_PNORDER_THREE;
        }
        else if ( ! strcmp( "threePointFivePN", LALoptarg ) )
        {
          localparams.order = LAL_PNORDER_THREE_POINT_FIVE;
        }
        else if ( ! strcmp( "pseudoFourPN", LALoptarg ) )
        {
          localparams.order = LAL_PNORDER_PSEUDO_FOUR;
        }
        else
        {
          fprintf( stderr, "invalid argument to --%s:\n"
              "unknown order specified: "
              "%s (must be one of twoPN, twoPointFivePN, threePN, threePointFivePN, pseudoFourPN)\n",
              long_options[option_index].name, LALoptarg );
          exit( 1 );
        }
        break;
      case 'f': /* right-ascension */
        localparams.rightAscension = atof( LALoptarg ) * LAL_PI_180;
        break;
      case 'F': /* Declination */
        localparams.declination = atof( LALoptarg ) * LAL_PI_180;
        break;
      case 'g': /* Error in declination */
        localparams.skyError = atof( LALoptarg ) * LAL_PI_180;
        break;
      case 'G': /* timing accuracy of network */
        localparams.timingAccuracy = atof( LALoptarg );
        break;
      case 'h': /* help */
        coh_PTF_usage( program );
        exit( 0 );
      case 'i': /* injection-file */
        localparams.injectFile = LALoptarg;
        break;
      case 'j':
        localparams.threshold = atof(LALoptarg);
        break;
      case '2':
        localparams.spinThreshold = atof(LALoptarg);
        break;
      case '1':
        localparams.snglSNRThreshold = atof(LALoptarg);
        break;
      case 'J':
        localparams.timeWindow = atof(LALoptarg);
        break;
      case 'k': /* user-tag */
        strncpy( localparams.userTag, LALoptarg, sizeof( localparams.userTag ) - 1 );
        break;
      case 'K': /* ifo-tag */
        strncpy( localparams.ifoTag, LALoptarg, sizeof( localparams.ifoTag ) - 1 );
        break;
      case 'l':
        localparams.nonspinSNR2threshold = atof(LALoptarg);
        break;
      case 'L':
        localparams.spinSNR2threshold = atof(LALoptarg);
        break;
      case 'm': /* spin bank */
        localparams.spinBank = 1;
        strncpy( localparams.spinBankName, LALoptarg, sizeof( localparams.spinBankName ) - 1 );
        break;
      case 'M': /* non spin bank */
        localparams.noSpinBank = 1;
        strncpy( localparams.noSpinBankName, LALoptarg, sizeof( localparams.noSpinBankName ) - 1 );
        break;
      case 'n': /* only-segment-numbers */
        localparams.segmentsToDoList = LALoptarg;
        break;
      case 'N': /* only-template-number */
        localparams.templatesToDoList = LALoptarg;
        break;
      case 'o': /* output-file */
        strncpy( localparams.outputFile, LALoptarg, sizeof( localparams.outputFile ) - 1 );
        break;
      case 'O': /* bank-file */
        localparams.bankFile = LALoptarg;
        break;
      case 'p': /* num auto chisq points */
        localparams.numAutoPoints = atoi( LALoptarg );
        break;
      case 'P': /* Auto veto time step */
        localparams.autoVetoTimeStep = atof( LALoptarg );
        break;
      case 'q': /* num chi square bins */
        localparams.numChiSquareBins = atoi( LALoptarg );
        break;
      case 'Q': 
        localparams.chiSquareCalcThreshold = atof( LALoptarg );
        break;
      case 'r': /* random seed */
        localparams.randomSeed = atoi( LALoptarg );
        break;
      case 'R': /* dynamic range factor */
        localparams.dynRangeFac = atof( LALoptarg );
        break;
      case 's': /* sample rate */
        localparams.sampleRate = atof( LALoptarg );
        break;
      case 'S': /* segment-duration */
        localparams.segmentDuration = atof( LALoptarg );
        break;
      case '9': /* PSD segment-duration */
        localparams.psdSegmentDuration = atof( LALoptarg );
        break;
      case 't': /* bank veto template bank */
        localparams.bankVetoBankName = LALoptarg;
        break;
      case 'T': /* inverse-spec-length */
        localparams.truncateDuration = atof( LALoptarg );
        break;
      case 'u': /* trig-start-time */
        localparams.trigStartTimeNS = (INT8) atol( LALoptarg ) * LAL_INT8_C(1000000000);
        break;
      case 'U': /* trig-end-time */
        localparams.trigEndTimeNS = (INT8) atol( LALoptarg ) * LAL_INT8_C(1000000000);
        break;
      case 'w': /* block-duration */
        localparams.duration = atof( LALoptarg );
        break;
      case 'W': /* pad-data */
        localparams.padData = atof( LALoptarg );
        break;
      case '!': /* h1-slide-segment */
        localparams.slideSegments[LAL_IFO_H1] = atoi( LALoptarg );
        break;
      case '&': /* h2-slide-segments */
        localparams.slideSegments[LAL_IFO_H2] = atoi( LALoptarg );
        break;
      case '(': /* l1-slide-segments */
        localparams.slideSegments[LAL_IFO_L1] = atoi( LALoptarg );
        break;
      case ')': /* v1-slide-segments */
        localparams.slideSegments[LAL_IFO_V1] = atoi( LALoptarg );
        break;
      case '@': /* Short slide offset time */
        localparams.shortSlideOffset = atoi( LALoptarg );
        break;
      case 'V': /* version */
        XLALOutputVersionString(stderr, 0);
        exit( 0 );
     case '#': /* sky grid file */
        localparams.skyPositionsFile = LALoptarg;
        break;
     case '|': /* FFT-level for plans */
        localparams.fftLevel = atoi( LALoptarg );
        break;
      case '4': /* Cluster window */
        localparams.clusterWindow = atof(LALoptarg);
        break;
      case '3': /* Injection search window */
        localparams.injSearchWindow = atof( LALoptarg );
        break;
      case '5': /* Injection search window */
        localparams.injMchirpWindow = atof( LALoptarg );
        break;
      case '7':
        if (!strcmp("real_4", LALoptarg))
        {
          localparams.ligoDoubleData = 0;
        }
        else if (!strcmp("real_8", LALoptarg))
        {
          localparams.ligoDoubleData = 1;
        }
        else
        {
          fprintf(stderr, "invalid argument to --%s:\n"
                  "unknown data type specified;\n"
                  "%s (must be one of: real_4, real_8)\n",
                  long_options[option_index].name, LALoptarg);
        }
        break;
      case '8':
        if (!strcmp("real_4", LALoptarg))
        {
          localparams.virgoDoubleData = 0;
        }
        else if (!strcmp("real_8", LALoptarg))
        {
          localparams.virgoDoubleData = 1;
        }
        else
        {
          fprintf(stderr, "invalid argument to --%s:\n"
                  "unknown data type specified;\n"
                  "%s (must be one of: real_4, real_8)\n",
                  long_options[option_index].name, LALoptarg);
        }
        break;
      case '?':
        error( "unknown error while parsing options\n" );
      default:
        error( "unknown error while parsing options\n" );
    }
  }

  if ( LALoptind < argc )
  {
    fprintf( stderr, "extraneous command line arguments:\n" );
    while ( LALoptind < argc )
      fprintf( stderr, "%s\n", argv[LALoptind++] );
    exit( 1 );
  }

  /* set number of ifos */
  localparams.numIFO = 0;

  for ( ifoNumber = 0; ifoNumber < LAL_NUM_IFO; ifoNumber++ )
  {
    if ( localparams.haveTrig[ifoNumber] )
    {
      XLALReturnIFO(ifo,ifoNumber);
      snprintf( localparams.ifoName[localparams.numIFO], LIGOMETA_IFO_MAX,\
                "%s", ifo );
      localparams.numIFO++;
    }
  }
  
  /* check for H1H2 */
  if (localparams.numIFO == 2)
  {
    if (! strcmp(localparams.ifoName[0],"H1"))
    {
      if (! strcmp(localparams.ifoName[1],"H2"))
      {
        localparams.singlePolFlag = 1;
      }
    }
  }
  /* Set the faceOn-faceAway flag */
  /* Otherwise it takes default value of 0 */
  if (localparams.faceOnAnalysis)
  {
    localparams.faceOnStatistic = 1;
  }
  else if (localparams.faceAwayAnalysis)
  {
    localparams.faceOnStatistic = 2;
  }

  /* Set the number of points in the time arrays */
  localparams.numTimePoints = floor(\
          localparams.segmentDuration * localparams.sampleRate + 0.5);
  /* Set the number of points in the frequency arrays */
  localparams.numFreqPoints = localparams.numTimePoints / 2 + 1;

  /* For now we stick to only analysing half of each segment */
  localparams.strideDuration = 0.5 * localparams.segmentDuration;

  /* FIXME: Hardcoded to 1s */
  localparams.numBufferPoints = floor(localparams.sampleRate + 0.5);

  /* Choose the start and end point of each segment for analysis */
  if (localparams.analSegmentEnd)
  { /* Want to analyse from the end of the segment */
    /* Start from the end */
    localparams.analEndPoint = localparams.numTimePoints;
    /* Remove the spectrum truncation */
    localparams.analEndPoint -= floor(\
        0.5 * localparams.truncateDuration * localparams.sampleRate + 0.5); 
    /* Remove the buffer points */
    localparams.analEndPoint -= localparams.numBufferPoints;
    /* And set the start point */
    localparams.analStartPoint = localparams.analEndPoint - \
        0.5*localparams.numTimePoints;
  }
  else
  { /* DEFAULT: Analyse the middle of the segment */
    localparams.analStartPoint = 1*localparams.numTimePoints/4;
    localparams.analEndPoint = (3*localparams.numTimePoints)/4;
  }

  localparams.analStartTime = localparams.analStartPoint / \
                                localparams.sampleRate;
  localparams.analStartPointBuf = localparams.analStartPoint\
                                  - localparams.numBufferPoints;
  localparams.analEndTime = localparams.analEndPoint / \
                                localparams.sampleRate;
  localparams.analEndPointBuf = localparams.analEndPoint\
                               + localparams.numBufferPoints;
  localparams.numAnalPoints = localparams.analEndPoint\
                             - localparams.analStartPoint;
  localparams.numAnalPointsBuf = localparams.analEndPointBuf\
                                - localparams.analStartPointBuf;
  /* Max template length is start length minus PSD truncation */
  localparams.maxTempLength = localparams.analStartTime;
  localparams.maxTempLength -= localparams.truncateDuration/2.;

  /* Determine the number of short slides */
  if (localparams.doShortSlides)
  {
    localparams.numShortSlides = 1 + localparams.numIFO * (int) floor( \
        localparams.strideDuration / \
        (localparams.shortSlideOffset * (localparams.numIFO-1)) );
  }
  else
  {
    localparams.numShortSlides = 1;
  }

  /* Set the template correction factor */
  if ( localparams.approximant == FindChirpSP)
  {
    /* Most of this gets stored in fcTmplt->fcTmpltNorm which is computed on
     * the fly. This is the correction needed to that. */
    /* First need to add ( (df)**-7./6. )**2 */
    localparams.tempCorrFac = pow(localparams.segmentDuration,14./6.); 
    /* For some reason FindChirp multiplies by a dt factor, take this out */
    localparams.tempCorrFac *= pow(localparams.sampleRate,2./6.);
  }
  else
  {
    /* Sigmasq factors are not yet available for all approximants */
    /* Set values to 1 (so this factor has no effect) and warn user */
    verbose("warning: Sigmasq correction factor is not yet available for this approximant: setting it to 1.\n");
    localparams.tempCorrFac = 1.0;
  }

  *params = localparams;

  return 0;
}
Пример #2
0
static struct options parse_command_line(int *argc, char **argv[], const ProcessTable *process, ProcessParamsTable **paramaddpoint)
{
	struct options options = options_defaults();
	int c;
	int option_index;
	struct LALoption long_options[] = {
		{"gps-end-time", required_argument, NULL, 'A'},
		{"gps-start-time", required_argument, NULL, 'B'},
		{"help", no_argument, NULL, 'C'},
		{"max-amplitude", required_argument, NULL, 'D'},
		{"min-amplitude", required_argument, NULL, 'E'},
		{"max-bandwidth", required_argument, NULL, 'F'},
		{"min-bandwidth", required_argument, NULL, 'G'},
		{"max-duration", required_argument, NULL, 'H'},
		{"min-duration", required_argument, NULL, 'I'},
		{"max-e-over-r2", required_argument, NULL, 'S'},
		{"min-e-over-r2", required_argument, NULL, 'T'},
		{"max-frequency", required_argument, NULL, 'J'},
		{"min-frequency", required_argument, NULL, 'K'},
		{"max-hrss", required_argument, NULL, 'L'},
		{"min-hrss", required_argument, NULL, 'M'},
		{"output", required_argument, NULL, 'V'},
		{"population", required_argument, NULL, 'N'},
		{"q", required_argument, NULL, 'O'},
		{"ra-dec", required_argument, NULL, 'U'},
		{"seed", required_argument, NULL, 'P'},
		{"time-step", required_argument, NULL, 'Q'},
		{"time-slide-file", required_argument, NULL, 'W'},
		{"jitter", required_argument, NULL, 'X'},
		{"user-tag", required_argument, NULL, 'R'},
		{NULL, 0, NULL, 0}
	};

	do switch(c = LALgetopt_long(*argc, *argv, "", long_options, &option_index)) {
	case 'A':
		XLALClearErrno();
		{
			LIGOTimeGPS tmp;
			XLALStrToGPS(&tmp, LALoptarg, NULL);
			options.gps_end_time = XLALGPSToINT8NS(&tmp);
		}
		if(xlalErrno) {
			fprintf(stderr, "invalid --%s (%s specified)\n", long_options[option_index].name, LALoptarg);
			exit(1);
		}
		ADD_PROCESS_PARAM(process, "lstring");
		break;

	case 'B':
		XLALClearErrno();
		{
			LIGOTimeGPS tmp;
			XLALStrToGPS(&tmp, LALoptarg, NULL);
			options.gps_start_time = XLALGPSToINT8NS(&tmp);
		}
		if(xlalErrno) {
			fprintf(stderr, "invalid --%s (%s specified)\n", long_options[option_index].name, LALoptarg);
			exit(1);
		}
		ADD_PROCESS_PARAM(process, "lstring");
		break;

	case 'C':
		print_usage();
		exit(0);

	case 'D':
		options.maxA = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'E':
		options.minA = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'F':
		options.maxbandwidth = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'G':
		options.minbandwidth = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'H':
		options.maxduration = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'I':
		options.minduration = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'J':
		options.maxf = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'K':
		options.minf = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'L':
		options.maxhrss = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'M':
		options.minhrss = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'N':
		if(!strcmp(LALoptarg, "targeted"))
			options.population = POPULATION_TARGETED;
		else if(!strcmp(LALoptarg, "string_cusp"))
			options.population = POPULATION_STRING_CUSP;
		else if(!strcmp(LALoptarg, "all_sky_sinegaussian"))
			options.population = POPULATION_ALL_SKY_SINEGAUSSIAN;
		else if(!strcmp(LALoptarg, "all_sky_btlwnb"))
			options.population = POPULATION_ALL_SKY_BTLWNB;
		else {
			fprintf(stderr, "error: unrecognized population \"%s\"", LALoptarg);
			exit(1);
		}
		ADD_PROCESS_PARAM(process, "lstring");
		break;

	case 'O':
		options.q = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'P':
		options.seed = atol(LALoptarg);
		ADD_PROCESS_PARAM(process, "int_8u");
		break;

	case 'Q':
		options.time_step = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'R':
		options.user_tag = LALoptarg;
		ADD_PROCESS_PARAM(process, "lstring");
		break;

	case 'S':
		options.maxEoverr2 = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'T':
		options.minEoverr2 = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "real_8");
		break;

	case 'U':
		{
			char *end;
			options.ra = strtod(LALoptarg, &end);
			while(isspace(*end))
				end++;
			if(*end != ',') {
				fprintf(stderr, "error: cannot parse --ra-dec \"%s\"\n", LALoptarg);
				exit(1);
			}
			options.dec = strtod(end + 1, &end);
			while(isspace(*end))
				end++;
			if(*end != '\0') {
				fprintf(stderr, "error: cannot parse --ra-dec \"%s\"\n", LALoptarg);
				exit(1);
			}
		}
		ADD_PROCESS_PARAM(process, "lstring");
		break;

	case 'V':
		options.output = LALoptarg;
		break;

	case 'W':
		options.time_slide_file = LALoptarg;
		ADD_PROCESS_PARAM(process, "lstring");
		break;

	case 'X':
		options.jitter = atof(LALoptarg);
		ADD_PROCESS_PARAM(process, "lstring");
		break;

	case 0:
		/* option sets a flag */
		break;

	case -1:
		/* end of arguments */
		break;

	case '?':
		/* unrecognized option */
		print_usage();
		exit(1);

	case ':':
		/* missing argument for an option */
		print_usage();
		exit(1);
	} while(c != -1);

	/* check some of the input parameters for consistency */
	if(options.maxA < options.minA) {
		fprintf(stderr, "error: --max-amplitude < --min-amplitude\n");
		exit(1);
	}
	if(options.maxbandwidth < options.minbandwidth) {
		fprintf(stderr, "error: --max-bandwidth < --min-bandwidth\n");
		exit(1);
	}
	if(options.maxduration < options.minduration) {
		fprintf(stderr, "error: --max-duration < --min-duration\n");
		exit(1);
	}
	if(options.maxf < options.minf) {
		fprintf(stderr, "error: --max-frequency < --min-frequency\n");
		exit(1);
	}
	if(options.maxhrss < options.minhrss) {
		fprintf(stderr, "error: --max-hrss < --min-hrss\n");
		exit(1);
	}

	if(options.gps_start_time == -1 || options.gps_end_time == -1) {
		fprintf(stderr, "--gps-start-time and --gps-end-time are both required\n");
		exit(1);
	}
	if(options.gps_end_time < options.gps_start_time) {
		fprintf(stderr, "error: --gps-end-time < --gps-start-time\n");
		exit(1);
	}
	if(!options.time_slide_file) {
		fprintf(stderr, "--time-slide-file is required\n");
		exit(1);
	}

	switch(options.population) {
	case POPULATION_TARGETED:
	case POPULATION_ALL_SKY_SINEGAUSSIAN:
	case POPULATION_ALL_SKY_BTLWNB:
	case POPULATION_STRING_CUSP:
		break;

	default:
		fprintf(stderr, "error: --population is required\n");
		exit(1);
	}

	if(!options.output) {
		int max_length = 100;	/* ARGH:  ugly */
		options.output = calloc(max_length + 1, sizeof(*options.output));
		if(options.user_tag)
			snprintf(options.output, max_length, "HL-INJECTIONS_%s-%d-%d.xml", options.user_tag, (int) (options.gps_start_time / LAL_INT8_C(1000000000)), (int) ((options.gps_end_time - options.gps_start_time) / LAL_INT8_C(1000000000)));
		else
			snprintf(options.output, max_length, "HL-INJECTIONS-%d-%d.xml", (int) (options.gps_start_time / LAL_INT8_C(1000000000)), (int) ((options.gps_end_time - options.gps_start_time) / LAL_INT8_C(1000000000)));
	}

	return options;
}
Пример #3
0
/* Internal function to parse integer strings into UINT8 magnitudes
   plus a sign. */
static UINT8
LALStringToU8AndSign(INT2 * sign, const CHAR * string, CHAR ** endptr)
{
    union {
        char *s;
        const char *cs;
    } bad;      /* there is a REASON for warnings... */
    const CHAR *here = string;  /* current position in string */
    CHAR c;     /* current character in string */
    UINT4 n = LAL_UINT8_MAXDIGITS - 1;  /* number of worry-free digits */
    UINT8 value;        /* current converted value */

    /* Skip leading space, and read sign character, if any. */
    *sign = 1;
    while (isspace(*here))
        here++;
    if (*here == '+')
        here++;
    else if (*here == '-') {
        *sign = -1;
        here++;
    }

    /* Read first digit.  Abort if it's not a digit. */
    if (isdigit((int) (c = *here))) {
        value = (UINT8) (c - '0');
        here++;
    } else {
        bad.cs = string;        /* ... and this avoids the warnings... BAD! */
        *endptr = bad.s;
        return 0;
    }

    /* Otherwise, start reading number.  Stop if we get close to
       overflowing. */
    while (isdigit((int) (c = *here)) && --n) {
        value *= LAL_INT8_C(10);
        value += (UINT8) (c - '0');
        here++;
    }

    /* Proceed with caution near overflow.  At this point, if n==0, then
       c = *here is the (LAL_UINT8_MAXDIGITS)th digit read, but value
       does not yet incorporate it. */
    if (!n) {
        here++;
        if (isdigit((int) (*here))) {
            value = LAL_UINT8_MAX;
            do
                here++;
            while (isdigit((int) (*here)));
        } else if (value > LAL_UINT8_MAX / LAL_INT8_C(10)) {
            value = LAL_UINT8_MAX;
        } else {
            UINT8 increment = (UINT8) (c - '0');
            value *= 10;
            if (value > LAL_UINT8_MAX - increment)
                value = LAL_UINT8_MAX;
            else
                value += increment;
        }
    }

    /* Return appropriate values. */
    bad.cs = here;      /* ... and this avoids the warnings... BAD! */
    *endptr = bad.s;
    return value;
}
Пример #4
0
int main( int argc, char *argv[] )
{
  /* lal initialization variables */
  LALStatus status = blank_status;

  /*  program option variables */
  CHAR *userTag = NULL;
  CHAR comment[LIGOMETA_COMMENT_MAX];
  char *ifoName = NULL;
  char *inputGlob = NULL;
  char *inputFileName = NULL;
  char *outputFileName = NULL;
  char *tamaFileName = NULL;
  char *summFileName = NULL;
  REAL4 snrStar = -1;
  SnglInspiralClusterChoice clusterchoice = none;
  INT8 cluster_dt = -1;
  char *injectFileName = NULL;
  INT8 inject_dt = -1;
  char *missedFileName = NULL;
  INT4 hardware = 0;
  int  enableTrigStartTime = 1;
  int j;
  FILE *fp = NULL;
  glob_t globbedFiles;
  int numInFiles = 0;
  char **inFileNameList;
  char line[MAX_PATH];
  int  errnum;

  UINT8 triggerInputTimeNS = 0;

  MetadataTable         proctable;
  MetadataTable         procparams;
  ProcessParamsTable   *this_proc_param;

  UINT4                 numSimEvents = 0;
  UINT4                 numSimInData = 0;
  UINT4                 numSimFound  = 0;
  UINT4                 numSimMissed = 0;
  UINT4                 numSimDiscard = 0;
  UINT4                 numSimProcessed = 0;

  SimRingdownTable     *simEventHead = NULL;
  SimRingdownTable     *thisSimEvent = NULL;
  SimRingdownTable     *missedSimHead = NULL;
  SimRingdownTable     *thisMissedSim = NULL;
  SimRingdownTable     *tmpSimEvent = NULL;
  SimRingdownTable     *prevSimEvent = NULL;

  SearchSummaryTable   *searchSummaryTable = NULL;

  UINT4                 numEvents = 0;
  UINT4                 numEventsKept = 0;
  UINT4                 numEventsInIFO = 0;
  UINT4                 numEventsCoinc = 0;
  UINT4                 numEventsDiscard = 0;
  UINT4                 numEventsProcessed = 0;
  UINT4                 numClusteredEvents = 0;

  SnglRingdownTable   **eventHandle = NULL;      
  SnglRingdownTable    *eventHead = NULL;
  SnglRingdownTable    *thisEvent = NULL;
  SnglRingdownTable    *tmpEvent = NULL;
  SnglRingdownTable    *prevEvent = NULL;

  LIGOLwXMLStream       xmlStream;
  MetadataTable         outputTable;


  /*
   *
   * initialization
   *
   */


  /* set up inital debugging values */
  lal_errhandler = LAL_ERR_EXIT;

  /* create the process and process params tables */
  proctable.processTable = (ProcessTable *) 
    calloc( 1, sizeof(ProcessTable) );
  XLALGPSTimeNow(&(proctable.processTable->start_time));

  XLALPopulateProcessTable(proctable.processTable, PROGRAM_NAME,
      lalAppsVCSIdentId, lalAppsVCSIdentStatus, lalAppsVCSIdentDate, 0);

  this_proc_param = procparams.processParamsTable = (ProcessParamsTable *) 
    calloc( 1, sizeof(ProcessParamsTable) );
  memset( comment, 0, LIGOMETA_COMMENT_MAX * sizeof(CHAR) );


  /*
   *
   * parse command line arguments
   *
   */


  while (1)
  {
    /* LALgetopt arguments */
    static struct LALoption long_options[] = 
    {
      {"verbose",             no_argument,           &vrbflg,              1 },
      {"sort-triggers",       no_argument,     &sortTriggers,              1 },
      {"help",                    no_argument,            0,              'h'},
      {"user-tag",                required_argument,      0,              'Z'},
      {"userTag",                 required_argument,      0,              'Z'},
      {"comment",                 required_argument,      0,              'c'},
      {"version",                 no_argument,            0,              'V'},
      {"glob",                    required_argument,      0,              'g'},
      {"input",                   required_argument,      0,              'i'},
      {"output",                  required_argument,      0,              'o'},
      {"data-type",               required_argument,      0,              'k'},
      {"tama-output",             required_argument,      0,              'j'},
      {"summary-file",            required_argument,      0,              'S'},
      {"snr-threshold",           required_argument,      0,              's'},
      {"cluster-algorithm",       required_argument,      0,              'C'},
      {"cluster-time",            required_argument,      0,              't'},
      {"ifo-cut",                 required_argument,      0,              'd'},
      {"injection-file",          required_argument,      0,              'I'},
      {"injection-coincidence",   required_argument,      0,              'T'},
      {"missed-injections",       required_argument,      0,              'm'},
      {"hardware-injections",     required_argument,      0,              'H'},
      {"disable-trig-start-time", no_argument,            0,              'D'},
      {0, 0, 0, 0}
    };
    int c;

    /* LALgetopt_long stores the option index here. */
    int option_index = 0;
    size_t LALoptarg_len;

    c = LALgetopt_long_only ( argc, argv, "hZ:c:d:g:i:o:j:S:s:C:Vt:I:T:m:H:D",
        long_options, &option_index );

    /* detect the end of the options */
    if ( c == - 1 )
      break;

    switch ( c )
    {
      case 0:
        /* if this option set a flag, do nothing else now */
        if ( long_options[option_index].flag != 0 )
        {
          break;
        }
        else
        {
          fprintf( stderr, "error parsing option %s with argument %s\n",
              long_options[option_index].name, LALoptarg );
          exit( 1 );
        }
        break;

      case 'h':
        fprintf( stdout, USAGE );
        exit( 0 );
        break;

      case 'Z':
        /* create storage for the usertag */
        LALoptarg_len = strlen( LALoptarg ) + 1;
        userTag = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR) );
        memcpy( userTag, LALoptarg, LALoptarg_len );

        this_proc_param = this_proc_param->next = (ProcessParamsTable *)
          calloc( 1, sizeof(ProcessParamsTable) );
        snprintf( this_proc_param->program, LIGOMETA_PROGRAM_MAX, "%s", 
            PROGRAM_NAME );
        snprintf( this_proc_param->param, LIGOMETA_PARAM_MAX, "-userTag" );
        snprintf( this_proc_param->type, LIGOMETA_TYPE_MAX, "string" );
        snprintf( this_proc_param->value, LIGOMETA_VALUE_MAX, "%s",
            LALoptarg );
        break;

      case 'c':
        if ( strlen( LALoptarg ) > LIGOMETA_COMMENT_MAX - 1 )
        {
          fprintf( stderr, "invalid argument to --%s:\n"
              "comment must be less than %d characters\n",
              long_options[option_index].name, LIGOMETA_COMMENT_MAX );
          exit( 1 );
        }
        else
        {
          snprintf( comment, LIGOMETA_COMMENT_MAX, "%s", LALoptarg);
        }
        break;

      case 'V':
        fprintf( stdout, "Single Ringdown Reader and Injection Analysis\n"
            "Patrick Brady, Duncan Brown and Steve Fairhurst\n");
        XLALOutputVersionString(stderr, 0);
        exit( 0 );
        break;

      case 'g':
        /* create storage for the input file glob */
        LALoptarg_len = strlen( LALoptarg ) + 1;
        inputGlob = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR));
        memcpy( inputGlob, LALoptarg, LALoptarg_len );
        ADD_PROCESS_PARAM( "string", "'%s'", LALoptarg );
        break;

      case 'i':
        /* create storage for the input file name */
        LALoptarg_len = strlen( LALoptarg ) + 1;
        inputFileName = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR));
        memcpy( inputFileName, LALoptarg, LALoptarg_len );
        ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        break;

      case 'o':
        /* create storage for the output file name */
        LALoptarg_len = strlen( LALoptarg ) + 1;
        outputFileName = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR));
        memcpy( outputFileName, LALoptarg, LALoptarg_len );
        ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        break;

      case 'j':
        /* create storage of the TAMA file name */
        LALoptarg_len = strlen( LALoptarg ) + 1;
        tamaFileName = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR));
        memcpy( tamaFileName, LALoptarg, LALoptarg_len );
        ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        break;

      case 'S':
        /* create storage for the summ file name */
        LALoptarg_len = strlen( LALoptarg ) + 1;
        summFileName = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR));
        memcpy( summFileName, LALoptarg, LALoptarg_len );
        ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        break;

      case 's':
        snrStar = (REAL4) atof( LALoptarg );
        if ( snrStar < 0 )
        {
          fprintf( stdout, "invalid argument to --%s:\n"
              "threshold must be >= 0: "
              "(%f specified)\n",
              long_options[option_index].name, snrStar );
          exit( 1 );
        }
        ADD_PROCESS_PARAM( "float", "%e", snrStar );
        break;

      case 'k':
        /* type of data to analyze */
        if ( ! strcmp( "playground_only", LALoptarg ) )
        {
          dataType = playground_only;
        }
        else if ( ! strcmp( "exclude_play", LALoptarg ) )
        {
          dataType = exclude_play;
        }
        else if ( ! strcmp( "all_data", LALoptarg ) )
        {
          dataType = all_data;
        }
        else
        {
          fprintf( stderr, "invalid argument to --%s:\n"
              "unknown data type, %s, specified: "
              "(must be playground_only, exclude_play or all_data)\n",
              long_options[option_index].name, LALoptarg );
          exit( 1 );
        }
        ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        break;

      case 'C':
        /* choose the clustering algorithm */
        {        
          if ( ! strcmp( "snr_and_chisq", LALoptarg ) )
          {
            clusterchoice = snr_and_chisq;
          }
          else if ( ! strcmp( "snrsq_over_chisq", LALoptarg) )
          {
            clusterchoice = snrsq_over_chisq;
          }
          else if ( ! strcmp( "snr", LALoptarg) )
          {
            clusterchoice = snr;
          }        
          else
          {
            fprintf( stderr, "invalid argument to  --%s:\n"
                "unknown clustering specified:\n "
                "%s (must be one of: snr_and_chisq, \n"
                "   snrsq_over_chisq or snr)\n",
                long_options[option_index].name, LALoptarg);
            exit( 1 );
          }
          ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        }
        break;

      case 't':
        /* cluster time is specified on command line in ms */
        cluster_dt = (INT8) atoi( LALoptarg );
        if ( cluster_dt <= 0 )
        {
          fprintf( stdout, "invalid argument to --%s:\n"
              "custer window must be > 0: "
              "(%" LAL_INT8_FORMAT " specified)\n",
              long_options[option_index].name, cluster_dt );
          exit( 1 );
        }
        ADD_PROCESS_PARAM( "int", "%" LAL_INT8_FORMAT "", cluster_dt );
        /* convert cluster time from ms to ns */
        cluster_dt *= LAL_INT8_C(1000000);
        break;

      case 'I':
        /* create storage for the injection file name */
        LALoptarg_len = strlen( LALoptarg ) + 1;
        injectFileName = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR));
        memcpy( injectFileName, LALoptarg, LALoptarg_len );
        ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        break;

      case 'd':
        LALoptarg_len = strlen( LALoptarg ) + 1;
        ifoName = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR));
        memcpy( ifoName, LALoptarg, LALoptarg_len );
        ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        break;

      case 'T':
        /* injection coincidence time is specified on command line in ms */
        inject_dt = (INT8) atoi( LALoptarg );
        if ( inject_dt < 0 )
        {
          fprintf( stdout, "invalid argument to --%s:\n"
              "injection coincidence window must be >= 0: "
              "(%" LAL_INT8_FORMAT " specified)\n",
              long_options[option_index].name, inject_dt );
          exit( 1 );
        }
        ADD_PROCESS_PARAM( "int", "%" LAL_INT8_FORMAT " ", inject_dt );
        /* convert inject time from ms to ns */
        inject_dt *= LAL_INT8_C(1000000);
        break;

      case 'm':
        /* create storage for the missed injection file name */
        LALoptarg_len = strlen( LALoptarg ) + 1;
        missedFileName = (CHAR *) calloc( LALoptarg_len, sizeof(CHAR));
        memcpy( missedFileName, LALoptarg, LALoptarg_len );
        ADD_PROCESS_PARAM( "string", "%s", LALoptarg );
        break;

      case 'H':
        hardware = (INT4) atoi( LALoptarg );
        if ( hardware <= 0 )
        {
          fprintf( stdout, "invalid argument to --%s:\n"
              "GPS start time of hardware injections must be > 0: "
              "(%d specified)\n",
              long_options[option_index].name, hardware );
          exit( 1 );
        }
        ADD_PROCESS_PARAM( "int", "%" LAL_INT4_FORMAT " ", hardware );
        break;

      case 'D':
        enableTrigStartTime = 0;
        ADD_PROCESS_PARAM( "string", "%s", " " );
        break;

      case '?':
        exit( 1 );
        break;

      default:
        fprintf( stderr, "unknown error while parsing options\n" );
        exit( 1 );
    }   
  }

  if ( LALoptind < argc )
  {
    fprintf( stderr, "extraneous command line arguments:\n" );
    while ( LALoptind < argc )
    {
      fprintf ( stderr, "%s\n", argv[LALoptind++] );
    }
    exit( 1 );
  }


  /*
   *
   * can use LALCalloc() / LALMalloc() from here
   *
   */


  /* don't buffer stdout if we are in verbose mode */
  if ( vrbflg ) setvbuf( stdout, NULL, _IONBF, 0 );

  /* fill the comment, if a user has specified it, or leave it blank */
  if ( ! *comment )
  {
    snprintf( proctable.processTable->comment, LIGOMETA_COMMENT_MAX, " " );
  }
  else
  {
    snprintf( proctable.processTable->comment, LIGOMETA_COMMENT_MAX,
        "%s", comment );
  }

  /* check that the input and output file names have been specified */
  if ( (! inputGlob && ! inputFileName) || (inputGlob && inputFileName) )
  {
    fprintf( stderr, "exactly one of --glob or --input must be specified\n" );
    exit( 1 );
  }
  if ( ! outputFileName )
  {
    fprintf( stderr, "--output must be specified\n" );
    exit( 1 );
  }

  /* check that Data Type has been specified */
  if ( dataType == unspecified_data_type )
  {
    fprintf( stderr, "Error: --data-type must be specified\n");
    exit(1);
  }

  /* check that if clustering is being done that we have all the options */
  if ( clusterchoice && cluster_dt < 0 )
  {
    fprintf( stderr, "--cluster-time must be specified if --cluster-algorithm "
        "is given\n" );
    exit( 1 );
  }
  else if ( ! clusterchoice && cluster_dt >= 0 )
  {
    fprintf( stderr, "--cluster-algorithm must be specified if --cluster-time "
        "is given\n" );
    exit( 1 );
  }

  /* check that we have all the options to do injections */
  if ( injectFileName && inject_dt < 0 )
  {
    fprintf( stderr, "--injection-coincidence must be specified if "
        "--injection-file is given\n" );
    exit( 1 );
  }
  else if ( ! injectFileName && inject_dt >= 0 )
  {
    fprintf( stderr, "--injection-file must be specified if "
        "--injection-coincidence is given\n" );
    exit( 1 );
  }

  /* save the sort triggers flag */
  if ( sortTriggers )
  {
    this_proc_param = this_proc_param->next = (ProcessParamsTable *) 
      calloc( 1, sizeof(ProcessParamsTable) ); 
    snprintf( this_proc_param->program, LIGOMETA_PROGRAM_MAX, "%s",
        PROGRAM_NAME ); 
    snprintf( this_proc_param->param, LIGOMETA_PARAM_MAX, 
        "--sort-triggers" );
    snprintf( this_proc_param->type, LIGOMETA_TYPE_MAX, "string" ); 
    snprintf( this_proc_param->value, LIGOMETA_VALUE_MAX, " " );
  }

  switch ( dataType )
  {
    case playground_only:
      if ( vrbflg )
        fprintf( stdout, "using data from playground times only\n" );
      snprintf( procparams.processParamsTable->program, 
          LIGOMETA_PROGRAM_MAX, "%s", PROGRAM_NAME );
      snprintf( procparams.processParamsTable->param,
          LIGOMETA_PARAM_MAX, "--playground-only" );
      snprintf( procparams.processParamsTable->type, 
          LIGOMETA_TYPE_MAX, "string" );
      snprintf( procparams.processParamsTable->value, 
          LIGOMETA_TYPE_MAX, " " );
      break;

    case exclude_play:
      if ( vrbflg )
        fprintf( stdout, "excluding all triggers in playground times\n" );
      snprintf( procparams.processParamsTable->program, 
          LIGOMETA_PROGRAM_MAX, "%s", PROGRAM_NAME );
      snprintf( procparams.processParamsTable->param,
          LIGOMETA_PARAM_MAX, "--exclude-play" );
      snprintf( procparams.processParamsTable->type, 
          LIGOMETA_TYPE_MAX, "string" );
      snprintf( procparams.processParamsTable->value, 
          LIGOMETA_TYPE_MAX, " " );
      break;

    case all_data:
      if ( vrbflg )
        fprintf( stdout, "using all input data\n" );
      snprintf( procparams.processParamsTable->program, 
          LIGOMETA_PROGRAM_MAX, "%s", PROGRAM_NAME );
      snprintf( procparams.processParamsTable->param,
          LIGOMETA_PARAM_MAX, "--all-data" );
      snprintf( procparams.processParamsTable->type, 
          LIGOMETA_TYPE_MAX, "string" );
      snprintf( procparams.processParamsTable->value, 
          LIGOMETA_TYPE_MAX, " " );
      break;

    default:
      fprintf( stderr, "data set not defined\n" );
      exit( 1 );
  }


  /*
   *
   * read in the injection XML file, if we are doing an injection analysis
   *
   */


  if ( injectFileName )
  {
    if ( vrbflg ) 
      fprintf( stdout, "reading injections from %s... ", injectFileName );

    simEventHead = XLALSimRingdownTableFromLIGOLw( injectFileName, 0, 0 );

    if ( vrbflg ) fprintf( stdout, "got %d injections\n", numSimEvents );

    if ( ! simEventHead )
    {
      fprintf( stderr, "error: unable to read sim_ringdown table from %s\n", 
          injectFileName );
      exit( 1 );
    }

    /* if we are doing hardware injections, increment all the start times */
    if ( hardware )
    {
      if ( vrbflg ) fprintf( stdout, 
          "incrementing GPS times of injections by %d seconds\n", hardware );

      for ( thisSimEvent = simEventHead; 
          thisSimEvent; thisSimEvent = thisSimEvent->next )
      {
        thisSimEvent->geocent_start_time.gpsSeconds += hardware;
        thisSimEvent->h_start_time.gpsSeconds       += hardware;
        thisSimEvent->l_start_time.gpsSeconds       += hardware;
      }
    }

    /* discard all injection events that are not in the data we want */
    if ( dataType != all_data )
    {
      numSimDiscard = 0;

      thisSimEvent = simEventHead;
      simEventHead = NULL;
      prevSimEvent = NULL;

      if ( vrbflg ) fprintf( stdout, "discarding injections not in data\n" );

      while ( thisSimEvent )
      {
        INT4 isPlayground = XLALINT8NanoSecIsPlayground(XLALGPSToINT8NS(&(thisSimEvent->geocent_start_time)));

        if ( (dataType == playground_only && isPlayground) || 
            (dataType == exclude_play && ! isPlayground) )
        {
          /* store the head of the linked list */
          if ( ! simEventHead ) simEventHead = thisSimEvent;

          /* keep this event */
          prevSimEvent = thisSimEvent;
          thisSimEvent = thisSimEvent->next;
          ++numSimInData;
          if ( vrbflg ) fprintf( stdout, "+" );
        }
        else
        {
          /* throw this event away */
          tmpSimEvent = thisSimEvent;
          if ( prevSimEvent ) prevSimEvent->next = thisSimEvent->next;
          thisSimEvent = thisSimEvent->next;
          LALFree( tmpSimEvent );
          ++numSimDiscard;
          if ( vrbflg ) fprintf( stdout, "-" );
        }
      }

      if ( vrbflg ) 
        fprintf( stdout, "\nusing %d (discarded %d) of %d injections\n",
            numSimInData, numSimDiscard, numSimEvents );
    }
    else
    {
      if ( vrbflg ) 
        fprintf( stdout, "using all %d injections\n", numSimInData );
      numSimInData = numSimEvents;
    }
  }


  /*
   *
   * read in the input triggers from the xml files
   *
   */


  if ( inputGlob )
  {
    /* use glob() to get a list of the input file names */
    if ( glob( inputGlob, GLOB_ERR, NULL, &globbedFiles ) )
    {
      fprintf( stderr, "error globbing files from %s\n", inputGlob );
      perror( "error:" );
      exit( 1 );
    }

    numInFiles = globbedFiles.gl_pathc;
    inFileNameList = (char **) LALCalloc( numInFiles, sizeof(char *) );

    for ( j = 0; j < numInFiles; ++j )
    {
      inFileNameList[j] = globbedFiles.gl_pathv[j];
    }
  }
  else if ( inputFileName )
  {
    /* read the list of input filenames from a file */
    fp = fopen( inputFileName, "r" );
    if ( ! fp )
    {
      fprintf( stderr, "could not open file containing list of xml files\n" );
      perror( "error:" );
      exit( 1 );
    }

    /* count the number of lines in the file */
    while ( get_next_line( line, sizeof(line), fp ) )
    {
      ++numInFiles;
    }
    rewind( fp );

    /* allocate memory to store the input file names */
    inFileNameList = (char **) LALCalloc( numInFiles, sizeof(char *) );

    /* read in the input file names */
    for ( j = 0; j < numInFiles; ++j )
    {
      inFileNameList[j] = (char *) LALCalloc( MAX_PATH, sizeof(char) );
      get_next_line( line, sizeof(line), fp );
      strncpy( inFileNameList[j], line, strlen(line) - 1);
    }

    fclose( fp );
  }
  else
  {
    fprintf( stderr, "no input file mechanism specified\n" );
    exit( 1 );
  }

  if ( vrbflg )
  {
    fprintf( stdout, "reading input triggers from:\n" );
    for ( j = 0; j < numInFiles; ++j )
    {
      fprintf( stdout, "%s\n", inFileNameList[j] );
    }
  }


  /*
   *
   * read in the triggers from the input xml files
   *
   */


  if ( injectFileName )
  {
    thisSimEvent = simEventHead;
    simEventHead = NULL;
    prevSimEvent = NULL;
    numSimDiscard = 0;
    numSimInData = 0;

    if ( vrbflg ) 
      fprintf( stdout, "discarding injections not in input data\n" );
  }

  for ( j = 0; j < numInFiles; ++j )
  {
    LIGOTimeGPS inPlay, outPlay;
    UINT8 outPlayNS, outStartNS, outEndNS, triggerTimeNS;
    INT4 trigStartTimeArg = 0;

    searchSummaryTable = XLALSearchSummaryTableFromLIGOLw( inFileNameList[j] );
    if ( ( ! searchSummaryTable ) || searchSummaryTable->next )
    {
      fprintf( stderr, 
          "error: zero or multiple search_summary tables in %s\n",
          inFileNameList[j] );
      exit( 1 );
    }

    if ( enableTrigStartTime )
    {
      /* override the value of out_start_time if there is a non-zero */
      /* --trig-start-time option in the process_params table        */
      /* this is necessary to get round a bug in early versions of   */
      /* the ringdown code                                           */

      int mioStatus;
      int pParParam;
      int pParValue;
      struct MetaioParseEnvironment parseEnv;
      const  MetaioParseEnv env = &parseEnv;

      /* open the procress_params table from the input file */
      mioStatus = MetaioOpenTable( env, inFileNameList[j], "process_params" );
      if ( mioStatus )
      {
        fprintf( stderr, "error opening process_params table from file %s\n", 
            inFileNameList[j] );
        exit( 1 );
      }

      /* figure out where the param and value columns are */
      if ( (pParParam = MetaioFindColumn( env, "param" )) < 0 )
      {
        fprintf( stderr, "unable to find column param in process_params\n" );
        MetaioClose(env);
        exit( 1 );
      }
      if ( (pParValue = MetaioFindColumn( env, "value" )) < 0 )
      {
        fprintf( stderr, "unable to find column value in process_params\n" );
        MetaioClose(env);
        exit( 1 );
      }

      /* get the trigger start time from the process params */
      while ( (mioStatus = MetaioGetRow(env)) == 1 )
      {
        if ( ! strcmp( env->ligo_lw.table.elt[pParParam].data.lstring.data, 
              "--trig-start-time" ) )
        {
          trigStartTimeArg = (INT4) 
            atoi( env->ligo_lw.table.elt[pParValue].data.lstring.data );
        }
      }

      MetaioClose( env );

      if ( trigStartTimeArg )
      {
        searchSummaryTable->out_start_time.gpsSeconds = trigStartTimeArg;
        searchSummaryTable->out_start_time.gpsNanoSeconds = 0;
        if ( vrbflg ) fprintf( stdout, "file %s has --trig-start-time %d\n",
            inFileNameList[j], trigStartTimeArg );
      }
    }

    /* compute the out time from the search summary table */
    outStartNS = XLALGPSToINT8NS ( &(searchSummaryTable->out_start_time) );
    outEndNS = XLALGPSToINT8NS ( &(searchSummaryTable->out_end_time) );
    triggerTimeNS = outEndNS - outStartNS;

    /* check for events and playground */
    if ( dataType != all_data )
    {
      LAL_CALL( LALPlaygroundInSearchSummary( &status, searchSummaryTable,
            &inPlay, &outPlay ), &status );
      outPlayNS = XLALGPSToINT8NS ( &outPlay );

      if ( dataType == playground_only )
      {
        if ( outPlayNS )
        {
          /* increment the total trigger time by the amount of playground */
          triggerInputTimeNS += outPlayNS;
        }
        else
        {
          /* skip this file as it does not contain any playground data */
          if ( vrbflg )
          {
            fprintf( stdout, "file %s not in playground, continuing\n", 
                inFileNameList[j] );
          }
          LALFree( searchSummaryTable );
          searchSummaryTable = NULL;
          continue;
        }
      }
      else if ( dataType == exclude_play )
      {
        /* increment the total trigger time by the out time minus */
        /* the time that is in the playground                     */
        triggerInputTimeNS += triggerTimeNS - outPlayNS;
      }
    }
    else
    {
      /* increment the total trigger time by the out time minus */
      triggerInputTimeNS += triggerTimeNS;
    }

    if ( injectFileName )
    {
      if ( vrbflg ) fprintf( stdout, "discarding injections not in file: " );

      /* throw away injections that are outside analyzed times */
      while ( thisSimEvent && thisSimEvent->geocent_start_time.gpsSeconds < 
          searchSummaryTable->out_end_time.gpsSeconds )
      {
        /* check if injection is before file start time */
        if ( thisSimEvent->geocent_start_time.gpsSeconds < 
            searchSummaryTable->out_start_time.gpsSeconds )
        {
          /* discard the current injection */
          if ( prevSimEvent ) prevSimEvent->next = thisSimEvent->next;
          tmpSimEvent = thisSimEvent;
          thisSimEvent = thisSimEvent->next;
          LALFree( tmpSimEvent );
          ++numSimDiscard;
          if ( vrbflg ) fprintf( stdout, "-" );
        }
        else
        {
          /* store the head of the linked list */
          if ( ! simEventHead ) simEventHead = thisSimEvent;

          /* keep this injection */
          prevSimEvent = thisSimEvent;
          thisSimEvent = thisSimEvent->next;
          ++numSimInData;
          if ( vrbflg ) fprintf( stdout, "+" );
        }
      }
      if ( vrbflg ) fprintf( stdout, "\n" );
    }


    /*
     *
     * if there are any events in the file, read them in
     *
     */


    if ( searchSummaryTable->nevents )
    {
      INT4 isPlay;

      if ( vrbflg ) fprintf( stdout, "file %s contains %d events, processing\n",
          inFileNameList[j], searchSummaryTable->nevents );

      if ( ! prevEvent )
      {
        eventHandle = &thisEvent;
      }
      else
      {
        eventHandle = &(prevEvent->next);
      }

      /* read the events from the file into a temporary list */
      XLAL_TRY( *eventHandle = XLALSnglRingdownTableFromLIGOLw( inFileNameList[j] ), errnum);
      if ( ! *eventHandle )
        switch ( errnum )
        {
          case XLAL_EDATA:
            XLALPrintError("Unable to read sngl_ringdown table from %s\n", inFileNameList[j] );
            /*LALFree(thisInputFile);*/
            XLALClearErrno();
            break;
          default:
            XLALSetErrno( errnum );
            XLAL_ERROR(XLAL_EFUNC );
        }
      
      /* only keep triggers from the data that we want to analyze */
      thisEvent = *eventHandle;
      while ( thisEvent )
      {
        numEvents++;

        isPlay = XLALINT8NanoSecIsPlayground( XLALGPSToINT8NS( &(thisEvent->start_time) ) );

        if ( (dataType == all_data || 
              (dataType == playground_only && isPlay) ||
              (dataType == exclude_play && ! isPlay))
            && ( snrStar < 0 || thisEvent->snr > snrStar) )
        {
          /* keep the trigger and increment the count of triggers */
          if ( ! eventHead ) eventHead = thisEvent;
          prevEvent = thisEvent;
          thisEvent = thisEvent->next;
          ++numEventsKept;
        }
        else
        {
          /* discard the trigger and move to the next one */
          if ( prevEvent ) prevEvent->next = thisEvent->next;
          tmpEvent = thisEvent;
          thisEvent = thisEvent->next;
          LAL_CALL ( LALFreeSnglRingdown ( &status, &tmpEvent ), &status);
        }
      }

      /* make sure that the linked list is properly terminated */
      if ( prevEvent && prevEvent->next ) prevEvent->next->next = NULL;
    }
    else
    {
      if ( vrbflg ) fprintf( stdout, "file %s contains no events, skipping\n",
          inFileNameList[j] );
    }

    LALFree( searchSummaryTable );
    searchSummaryTable = NULL;
  }

  /* discard the remaining injections which occured after the last file */
  if ( injectFileName )
  {
    if ( vrbflg ) fprintf( stdout, "kept %d injections, discarded %d\n",
        numSimInData, numSimDiscard );

    if ( prevSimEvent ) prevSimEvent->next = NULL;

    numSimDiscard = 0;
    while ( thisSimEvent )
    {
      tmpSimEvent = thisSimEvent;
      thisSimEvent = thisSimEvent->next;
      LALFree( tmpSimEvent );
      ++numSimDiscard;
      if ( vrbflg ) fprintf( stdout, "-" );
    }

    if ( vrbflg ) fprintf( stdout, "\ndiscarded %d injections at end of list\n",
        numSimDiscard );
  }


  /*
   *
   * sort the ringdown events by time
   *
   */


  if ( injectFileName || sortTriggers )
  {
    if ( vrbflg ) fprintf( stdout, "sorting ringdown trigger list..." );
    LAL_CALL( LALSortSnglRingdown( &status, &eventHead, 
          *LALCompareSnglRingdownByTime ), &status );
    if ( vrbflg ) fprintf( stdout, "done\n" );
  }


  /*
   *
   * keep only event from requested ifo
   *
   */

  if ( ifoName )
  {
    if ( vrbflg ) fprintf( stdout, 
        "keeping only triggers from %s, discarding others...", ifoName );
    LAL_CALL( LALIfoCutSingleRingdown( &status, &eventHead, ifoName ), &status );
    LALIfoCountSingleRingdown( &status, &numEventsInIFO, eventHead, 
        XLALIFONumber(ifoName) );

    if ( vrbflg ) fprintf( stdout, "done\n" );
  }

  /*
   *
   * check for events that are coincident with injections
   *
   */


  if ( injectFileName )
  {
    int coincidence = 0;
    UINT8 simTime, ringdownTime;

    if ( vrbflg ) fprintf( stdout, 
        "checking for events that are coincident with injections\n" );

    /* Note: we are assuming that both the ringdown and */
    /* injection events are time sorted                 */
    thisSimEvent = simEventHead;
    thisEvent    = eventHead;

    simEventHead = NULL;
    eventHead    = NULL;
    prevSimEvent = NULL;
    prevEvent    = NULL;

    numSimFound      = 0;
    numSimDiscard    = 0;
    numEventsDiscard = 0;
    numEventsCoinc   = 0;

    if ( ! thisEvent )
    {
      /* no triggers in the input data, so all injections are missed */
      if ( vrbflg ) fprintf( stdout, "no triggers in input data\n" );

      thisMissedSim = missedSimHead = thisSimEvent;

      while ( thisMissedSim )
      {
        /* count the number of injections just stuck in the missed list */
        if ( vrbflg ) fprintf( stdout, "M" );
        ++numSimMissed;
        ++numSimProcessed;
        thisMissedSim = thisMissedSim->next;
      }
    }
    else
    {
      /* begin loop over the sim_ringdown events */
      while ( thisSimEvent )
      {
        /* compute the end time in nanosec for the injection */
        /* at the relevant detector                          */
        if ( ! strcmp( "L1", thisEvent->ifo ) )
        {
          simTime = XLALGPSToINT8NS ( &(thisSimEvent->l_start_time) );
        }
        else if ( ! strcmp( "H1", thisEvent->ifo ) || 
            ! strcmp( "H2", thisEvent->ifo ) )
        {
          simTime = XLALGPSToINT8NS ( &(thisSimEvent->h_start_time) );
        }
        else
        {
          fprintf( stderr, "unknown detector found in event list: %s\n", 
              thisEvent->ifo );
          fprintf( stderr, "Detector must be one of (G1|H1|H2|L1|T1|V1)\n");
          exit( 1 );
        }

        /* find the first ringdown event after the current sim event */
        while ( thisEvent )
        {
          coincidence = 0;

          /* compute the time in nanosec for the ringdown */
          ringdownTime = XLALGPSToINT8NS ( &(thisEvent->start_time) );

          if ( ringdownTime < (simTime - inject_dt) )
          {
            /* discard this event and move on to the next one */
            if ( prevEvent ) prevEvent->next = thisEvent->next;
            tmpEvent = thisEvent;
            thisEvent = thisEvent->next;
            LAL_CALL ( LALFreeSnglRingdown ( &status, &tmpEvent ), &status);
            ++numEventsProcessed;
            ++numEventsDiscard;
            if ( vrbflg ) fprintf( stdout, "-" );
          }
          else
          {
            /* we have reached the negative coincincidence window */
            break;
          }
        }

        while ( thisEvent )
        {
          /* compute the time in nanosec for the ringdown */
          ringdownTime = XLALGPSToINT8NS ( &(thisEvent->start_time) );

          if ( ringdownTime < (simTime + inject_dt) )
          {
            /* this event is within the coincidence window  */
            /* store this event and move on to the next one */
            if ( ! eventHead ) eventHead = thisEvent;
            prevEvent = thisEvent;
            thisEvent = thisEvent->next;
            coincidence = 1;
            ++numEventsProcessed;
            ++numEventsCoinc;
            if ( vrbflg ) fprintf( stdout, "+" );
          }
          else
          {
            /* we have reached the end of the positive coincincidence window */
            break;
          }
        }

        if ( coincidence )
        {
          /* keep this event in the list and move to the next sim event */
          if ( ! simEventHead ) simEventHead = thisSimEvent;
          prevSimEvent = thisSimEvent;
          ++numSimFound;
          ++numSimProcessed;
          thisSimEvent = thisSimEvent->next;
          if ( vrbflg ) fprintf( stdout, "F" );
        }
        else
        {
          /* save this sim event in the list of missed events... */
          if ( ! missedSimHead )
          {
            missedSimHead = thisMissedSim = thisSimEvent;
          }
          else
          {
            thisMissedSim = thisMissedSim->next = thisSimEvent;
          }

          /* ...and remove it from the list of found events */
          if ( prevSimEvent ) prevSimEvent->next = thisSimEvent->next;
          ++numSimMissed;
          if ( vrbflg ) fprintf( stdout, "M" );

          /* move to the next sim in the list */
          ++numSimProcessed;
          thisSimEvent = thisSimEvent->next;

          /* make sure the missed sim list is terminated */
          thisMissedSim->next = NULL;
        }

        if ( ! thisEvent )
        {
          /* these are no more events to process so all the rest of the */
          /* injections must be put in the missed injections list       */
          if ( ! missedSimHead )
          {
            /* this and any subsequent events are in the missed sim list */
            if ( thisSimEvent ) thisMissedSim = missedSimHead = thisSimEvent;
          }
          else
          {
            if ( thisSimEvent )
            {
              /* append the rest of the list to the list of missed injections */
              thisMissedSim = thisMissedSim->next = thisSimEvent;
            }
            else
            {
              /* there are no injections after this one */
              thisMissedSim = thisMissedSim->next = NULL;
            }
          }

          /* terminate the list of found injections correctly */
          if ( prevSimEvent ) prevSimEvent->next = NULL;

          while ( thisMissedSim )
          {
            /* count the number of injections just stuck in the missed list */
            if ( vrbflg ) fprintf( stdout, "M" );
            ++numSimMissed;
            ++numSimProcessed;
            thisMissedSim = thisMissedSim->next;
          }
          thisSimEvent = NULL;
          break;
        }
      }

      if ( thisEvent )
      {
        /* discard any remaining ringdown triggers -- including thisEvent */
        /* as we have run out of injections */
        tmpEvent = thisEvent;
        if ( prevEvent ) prevEvent->next = NULL;
        while ( tmpEvent )
        {
          thisEvent = tmpEvent;
          tmpEvent = tmpEvent->next;
          LAL_CALL ( LALFreeSnglRingdown ( &status, &thisEvent ), &status);
          ++numEventsDiscard;
          ++numEventsProcessed;
          if ( vrbflg ) fprintf( stdout, "-" );
        }
      }
    }

    if ( vrbflg )
    {
      fprintf( stdout, "\nfound %d injections, missed %d injections "
          "(%d injections processed)\n",
          numSimFound, numSimMissed, numSimProcessed );

      fprintf( stdout, "found %d coincident events, %d events discarded "
          "(%d events processed)\n",
          numEventsCoinc, numEventsDiscard, numEventsProcessed );
    }

  } /* end if ( injectFileName ) */


  /*
   *
   * cluster the remaining events
   *
   */


  if ( eventHead && clusterchoice )
  {
    if ( vrbflg ) fprintf( stdout, "clustering remaining triggers... " );
    LAL_CALL( LALClusterSnglRingdownTable( &status, eventHead,
          cluster_dt, clusterchoice ), &status );
    if ( vrbflg ) fprintf( stdout, "done\n" );

    /* count the number of triggers surviving the clustering */
    thisEvent = eventHead;
    numClusteredEvents = 0;
    while ( thisEvent )
    {
      ++numClusteredEvents;
      thisEvent = thisEvent->next;
    }
  }


  /*
   *
   * write output data
   *
   */


  /* write the main output file containing found injections */
  if ( vrbflg ) fprintf( stdout, "writing output xml files... " );
  memset( &xmlStream, 0, sizeof(LIGOLwXMLStream) );
  LAL_CALL( LALOpenLIGOLwXMLFile( &status, &xmlStream, outputFileName ), &status );

  /* write out the process and process params tables */
  if ( vrbflg ) fprintf( stdout, "process... " );
  XLALGPSTimeNow(&(proctable.processTable->start_time));
  LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, process_table ), 
      &status );
  LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, proctable, 
        process_table ), &status );
  LAL_CALL( LALEndLIGOLwXMLTable ( &status, &xmlStream ), &status );
  free( proctable.processTable );

  /* write the process params table */
  if ( vrbflg ) fprintf( stdout, "process_params... " );
  LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, 
        process_params_table ), &status );
  LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, procparams, 
        process_params_table ), &status );
  LAL_CALL( LALEndLIGOLwXMLTable ( &status, &xmlStream ), &status );

  /* Write the found injections to the sim table */
  if ( simEventHead )
  {
    if ( vrbflg ) fprintf( stdout, "sim_ringdown... " );
    outputTable.simRingdownTable = simEventHead;
    LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, 
          sim_ringdown_table ), &status );
    LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, outputTable, 
          sim_ringdown_table ), &status );
    LAL_CALL( LALEndLIGOLwXMLTable( &status, &xmlStream ), &status );
  }

  /* Write the results to the ringdown table */
  if ( eventHead )
  {
    if ( vrbflg ) fprintf( stdout, "sngl_ringdown... " );
    outputTable.snglRingdownTable = eventHead;
    LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, 
          sngl_ringdown_table ), &status );
    LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, outputTable, 
          sngl_ringdown_table ), &status );
    LAL_CALL( LALEndLIGOLwXMLTable( &status, &xmlStream ), &status);
  }

  /* close the output file */
  LAL_CALL( LALCloseLIGOLwXMLFile(&status, &xmlStream), &status);
  if ( vrbflg ) fprintf( stdout, "done\n" );

  /* write out the TAMA file if it is requested */
  if ( tamaFileName )
  {
    /* FIXME */
    REAL8 UNUSED trigtime;

    fp = fopen( tamaFileName, "w" );
    if ( ! fp )
    {
      perror( "TAMA file" );
      exit( 1 );
    }

    fprintf( fp, "IFO   trigger time       snr         chisq       "
        " total mass     eta       eff dist (kpc)\n" );

    for ( thisEvent = eventHead; thisEvent; thisEvent = thisEvent->next )
    {
      trigtime = XLALGPSGetREAL8(&(thisEvent->start_time));
    }

    fclose( fp );
  }

  if ( missedFileName )
  {
    /* open the missed injections file and write the missed injections to it */
    if ( vrbflg ) fprintf( stdout, "writing missed injections... " );
    memset( &xmlStream, 0, sizeof(LIGOLwXMLStream) );
    LAL_CALL( LALOpenLIGOLwXMLFile( &status, &xmlStream, missedFileName ), 
        &status );

    if ( missedSimHead )
    {
      outputTable.simRingdownTable = missedSimHead;
      LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, sim_ringdown_table ),
          &status );
      LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, outputTable, 
            sim_ringdown_table ), &status );
      LAL_CALL( LALEndLIGOLwXMLTable( &status, &xmlStream ), &status );
    }

    LAL_CALL( LALCloseLIGOLwXMLFile( &status, &xmlStream ), &status );
    if ( vrbflg ) fprintf( stdout, "done\n" );
  }

  if ( summFileName )
  {
    LIGOTimeGPS triggerTime;

    /* write out a summary file */
    fp = fopen( summFileName, "w" );

    switch ( dataType )
    {
      case playground_only:
        fprintf( fp, "using data from playground times only\n" );
        break;
      case exclude_play:
        fprintf( fp, "excluding all triggers in playground times\n" );
        break;
      case all_data:
        fprintf( fp, "using all input data\n" );
        break;
      default:
        fprintf( stderr, "data set not defined\n" );
        exit( 1 );
    }

    fprintf( fp, "read triggers from %d files\n", numInFiles );
    fprintf( fp, "number of triggers in input files: %d \n", numEvents );
    if ( snrStar >= 0 )
    {
      fprintf( fp, "number of triggers in input data with snr above %f: %d \n",
          snrStar, numEventsKept );
    }
    else
    {
      fprintf( fp, "number of triggers in input data %d \n", numEventsKept );
    }

    if ( ifoName )
    {
      fprintf( fp, "number of triggers from %s ifo %d \n", ifoName, 
          numEventsInIFO );
    }

    XLALINT8NSToGPS( &triggerTime, triggerInputTimeNS );
    fprintf( fp, "amount of time analysed for triggers %d sec %d ns\n", 
        triggerTime.gpsSeconds, triggerTime.gpsNanoSeconds );

    if ( injectFileName )
    {
      fprintf( fp, "read %d injections from file %s\n", 
          numSimEvents, injectFileName );

      fprintf( fp, "number of injections in input data: %d\n", numSimInData );
      fprintf( fp, "number of injections found in input data: %d\n", 
          numSimFound );
      fprintf( fp, 
          "number of triggers found within %" LAL_INT8_FORMAT "msec of injection: %d\n",
          (inject_dt / LAL_INT8_C(1000000) ), numEventsCoinc );

      fprintf( fp, "efficiency: %f \n", 
          (REAL4) numSimFound / (REAL4) numSimInData );
    }

    if ( clusterchoice )
    {
      fprintf( fp, "number of event clusters with %" LAL_INT8_FORMAT " msec window: %d\n",
          cluster_dt/ LAL_INT8_C(1000000), numClusteredEvents ); 
    }

    fclose( fp ); 
  }


  /*
   *
   * free memory and exit
   *
   */


  /* free the ringdown events we saved */
  while ( eventHead )
  {
    thisEvent = eventHead;
    eventHead = eventHead->next;
    LAL_CALL ( LALFreeSnglRingdown ( &status, &thisEvent ), &status);
  }

  /* free the process params */
  while( procparams.processParamsTable )
  {
    this_proc_param = procparams.processParamsTable;
    procparams.processParamsTable = this_proc_param->next;
    free( this_proc_param );
  }

  /* free the found injections */
  while ( simEventHead )
  {
    thisSimEvent = simEventHead;
    simEventHead = simEventHead->next;
    LALFree( thisSimEvent );
  }

  /* free the temporary memory containing the missed injections */
  while ( missedSimHead )
  {
    tmpSimEvent = missedSimHead;
    missedSimHead = missedSimHead->next;
    LALFree( tmpSimEvent );
  }

  /* free the input file name data */
  if ( inputGlob )
  {
    LALFree( inFileNameList ); 
    globfree( &globbedFiles );
  }
  else
  {
    for ( j = 0; j < numInFiles; ++j )
    {
      LALFree( inFileNameList[j] );
    }
    LALFree( inFileNameList );
  }

  if ( vrbflg ) fprintf( stdout, "checking memory leaks and exiting\n" );
  LALCheckMemoryLeaks();
  exit( 0 );
}