void LALForwardRealDFT(
    LALStatus      *status,
    COMPLEX8Vector *output,
    REAL4Vector    *input
    )
{
  COMPLEX8Vector *a = NULL;
  COMPLEX8Vector *b = NULL;
  UINT4 n;
  UINT4 j;
  UINT4 k;

  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );

  n = input->length;

  TRY( LALCCreateVector( status->statusPtr, &a, n ), status );
  TRY( LALCCreateVector( status->statusPtr, &b, n ), status );

  for ( j = 0; j < n; ++j )
    a->data[j] = input->data[j];

  TRY( LALDFT( status->statusPtr, b, a, -1 ), status );

  for ( k = 0; k <= n / 2; ++k )
    output->data[k] = b->data[k];

  TRY( LALCDestroyVector( status->statusPtr, &a ), status );
  TRY( LALCDestroyVector( status->statusPtr, &b ), status );

  DETATCHSTATUSPTR( status );
  RETURN( status );
}
int main( void )
{
  static LALStatus status;

  REAL4Sequence       *sSequenceIn;
  REAL4Sequence       *sSequenceOut;
  REAL8Sequence       *dSequenceIn;
  REAL8Sequence       *dSequenceOut;

  COMPLEX8Sequence    *cSequenceIn;
  COMPLEX8Sequence    *cSequenceOut;
  COMPLEX16Sequence   *zSequenceIn;
  COMPLEX16Sequence   *zSequenceOut;


  REAL4FrequencySeries      sFrequencySeries;
  REAL8FrequencySeries      dFrequencySeries;
  COMPLEX8FrequencySeries   cFrequencySeries;
  COMPLEX16FrequencySeries  zFrequencySeries;

  REAL4FrequencySeries      sFrequencySeries2;
  REAL8FrequencySeries      dFrequencySeries2;
  COMPLEX8FrequencySeries   cFrequencySeries2;
  COMPLEX16FrequencySeries  zFrequencySeries2;

  REAL4TimeSeries           sTimeSeries;
  REAL8TimeSeries           dTimeSeries;
  COMPLEX8TimeSeries        cTimeSeries;
  COMPLEX16TimeSeries       zTimeSeries;

  REAL4TimeSeries           sTimeSeries2;
  REAL8TimeSeries           dTimeSeries2;
  COMPLEX8TimeSeries        cTimeSeries2;
  COMPLEX16TimeSeries       zTimeSeries2;

  REAL4            *sData;
  REAL8            *dData;
  COMPLEX8         *cData;
  COMPLEX16        *zData;

  /* Boolean Vars */
  BOOLEAN     unitComp;

  /* variables for units */
  RAT4        raise;
  LALUnit     strainToMinus2;
  LALUnit     adcToMinus2;
  LALUnit     adcStrain;


  /* This routine should generate a file with data */
  /* to be read by ReadFTSeries.c*/
  LIGOTimeGPS  t;
  UINT4         i;


  /* Data Test Variable */
  UINT4   j;


  fprintf(stderr,"Testing value of LALUnitTextSize ... ");
  if ( (int)LALSupportUnitTextSize != (int)LALUnitTextSize )
  {
    fprintf(stderr,"UnitTextSize mismatch: [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  fprintf(stderr,"PASS\n");

  t.gpsSeconds = 0;
  t.gpsNanoSeconds = 0;

  fprintf(stderr,"Testing Print/Read COMPLEX8FrequencySeries ... ");

  cSequenceIn = NULL;
  LALCCreateVector(&status, &cSequenceIn, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }
  for ( i=1, cData=cSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, cData++ )
  {
    *(cData) = crectf( i, i+1 );
    }

  strncpy(cFrequencySeries.name,"Complex frequency series",LALNameLength);
  cFrequencySeries.sampleUnits = lalHertzUnit;
  cFrequencySeries.deltaF = 1;
  cFrequencySeries.epoch = t;
  cFrequencySeries.f0 = 5;

  cFrequencySeries.data = cSequenceIn;

  LALCPrintFrequencySeries(&cFrequencySeries, "cFSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  cSequenceOut = NULL;
  LALCCreateVector( &status, &cSequenceOut, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  cFrequencySeries2.data = cSequenceOut;

  LALCReadFrequencySeries(&status, &cFrequencySeries2, "./cFSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (fabs(cFrequencySeries.deltaF - cFrequencySeries.deltaF)/
      cFrequencySeries.deltaF > READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"DeltaF MisMatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if (strcmp(cFrequencySeries.name,cFrequencySeries2.name) != 0)
  {
    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((cFrequencySeries.epoch.gpsSeconds) !=
      (cFrequencySeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch Second Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((cFrequencySeries.epoch.gpsNanoSeconds) !=
      (cFrequencySeries2.epoch.gpsNanoSeconds))
  {
    fprintf(stderr,"Epoch NanosecondMismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((cFrequencySeries.f0) ?
      (fabs(cFrequencySeries.f0 - cFrequencySeries2.f0)/cFrequencySeries.f0) :
      (fabs(cFrequencySeries.f0 - cFrequencySeries2.f0)  >
      READFTSERIESTEST_TOL))
  {
    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  unitComp = XLALUnitCompare(&cFrequencySeries.sampleUnits,&cFrequencySeries2.sampleUnits);

  if (unitComp != 0)
  {
    fprintf(stderr,"Units Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  for (j = 0; j < cSequenceIn->length;j++)
  {
    if ((crealf(cSequenceIn->data[j]) ?
	 fabs((crealf(cSequenceIn->data[j]) - crealf(cSequenceOut->data[j]))
	      /crealf(cSequenceIn->data[j]))
	 :fabs(crealf(cSequenceIn->data[j]) - crealf(cSequenceOut->data[j]))) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
    if ((cimagf(cSequenceIn->data[j]) ?
	 fabs((cimagf(cSequenceIn->data[j]) - cimagf(cSequenceOut->data[j]))
	      /cimagf(cSequenceIn->data[j]))
	 :fabs(cimagf(cSequenceIn->data[j]) - cimagf(cSequenceOut->data[j]))) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
  }

  fprintf(stderr,"PASS\n");

  fprintf(stderr,"Testing Print/Read COMPLEX16FrequencySeries ... ");

  /* Test case 2 */

  t.gpsSeconds = 45678;
  t.gpsNanoSeconds = 89065834;

  zSequenceIn = NULL;
  LALZCreateVector( &status, &zSequenceIn, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  for ( i=1, zData=zSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, zData++ )
  {
    *(zData) = crect( i/4.0, (i+1)/5.0 );
  }
  zFrequencySeries.sampleUnits = lalDimensionlessUnit;
  strncpy(zFrequencySeries.name,"Complex frequency series",LALNameLength);
  zFrequencySeries.deltaF = 1.3;
  zFrequencySeries.epoch = t;
  zFrequencySeries.f0 = 0;
  zFrequencySeries.data = zSequenceIn;

  LALZPrintFrequencySeries(&zFrequencySeries, "zFSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  zSequenceOut = NULL;
  LALZCreateVector( &status, &zSequenceOut, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  zFrequencySeries2.data = zSequenceOut;

  LALZReadFrequencySeries(&status, &zFrequencySeries2, "./zFSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if ((zFrequencySeries.deltaF) != (zFrequencySeries2.deltaF))
  {
    fprintf(stderr,"DeltaF Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if (strcmp(zFrequencySeries.name,zFrequencySeries2.name) != 0)
  {
    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((zFrequencySeries.epoch.gpsSeconds) !=
      (zFrequencySeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((zFrequencySeries.epoch.gpsNanoSeconds) !=
      (zFrequencySeries2.epoch.gpsNanoSeconds))
  {
    fprintf(stderr,"Epoch NanoSeconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if (zFrequencySeries.f0 ?
       (fabs(zFrequencySeries.f0 - zFrequencySeries2.f0)/zFrequencySeries.f0)
       : (fabs(zFrequencySeries.f0 - zFrequencySeries2.f0)) >
       READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  unitComp = XLALUnitCompare(&zFrequencySeries.sampleUnits,&zFrequencySeries2.sampleUnits);

  if (unitComp != 0)
  {
    fprintf(stderr,"Units Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  for (j = 0; j < zSequenceIn->length;j++)
  {
    if ((creal(zSequenceIn->data[j]) ?
	fabs((creal(zSequenceIn->data[j]) - creal(zSequenceOut->data[j]))
	     /creal(zSequenceIn->data[j])) :
	fabs(creal(zSequenceIn->data[j]) - creal(zSequenceOut->data[j]))) >
	READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
   if ((cimag(zSequenceIn->data[j]) ?
	fabs((cimag(zSequenceIn->data[j]) - cimag(zSequenceOut->data[j]))
	     /cimag(zSequenceIn->data[j])) :
	fabs(cimag(zSequenceIn->data[j]) - cimag(zSequenceOut->data[j]))) >
	READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
  }

  fprintf(stderr,"PASS\n");

  fprintf(stderr,"Testing Print/Read REAL8FrequencySeries ... ");

  /* Test case 3 */
  t.gpsSeconds = 45678;
  t.gpsNanoSeconds = 89065834;

  dSequenceIn = NULL;
  LALDCreateVector( &status, &dSequenceIn, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  for ( i=1, dData=dSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, dData++ )
  {
    *(dData) = 0.005;
  }

  strncpy(dFrequencySeries.name,"Complex frequency series",LALNameLength);
  /* set units */
  raise.numerator = -2;
  raise.denominatorMinusOne = 0;
  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&dFrequencySeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  dFrequencySeries.deltaF = 1.3;
  dFrequencySeries.epoch = t;
  dFrequencySeries.f0 = 0;
  dFrequencySeries.data = dSequenceIn;
  LALDPrintFrequencySeries(&dFrequencySeries, "dFSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  dSequenceOut = NULL;
  LALDCreateVector( &status, &dSequenceOut, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  dFrequencySeries2.data = dSequenceOut;

  LALDReadFrequencySeries(&status, &dFrequencySeries2, "./dFSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if ((dFrequencySeries.deltaF) != (dFrequencySeries.deltaF))
  {
    fprintf(stderr,"DeltaF Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if (strcmp(dFrequencySeries.name,dFrequencySeries2.name) != 0)
  {
    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((dFrequencySeries.epoch.gpsSeconds)
      != (dFrequencySeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((dFrequencySeries.epoch.gpsSeconds)
      != (dFrequencySeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch NanoSeconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if (dFrequencySeries.f0 ?
       (fabs(dFrequencySeries.f0 - dFrequencySeries2.f0)/dFrequencySeries.f0)
       : (fabs(dFrequencySeries.f0 - dFrequencySeries2.f0)) >
       READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  unitComp = XLALUnitCompare(&dFrequencySeries.sampleUnits,&dFrequencySeries2.sampleUnits);

  if (unitComp != 0)
  {
    fprintf(stderr,"Unit Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }


  for (j = 0; j < dSequenceIn->length;j++)
  {
    if ((dSequenceIn->data[j] ?
	 fabs((dSequenceIn->data[j] - dSequenceOut->data[j])
	      /dSequenceIn->data[j])
	 :fabs(dSequenceIn->data[j] - dSequenceOut->data[j])) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }

  }


  fprintf(stderr,"PASS\n");

  fprintf(stderr,"Testing Print/Read REAL4FrequencySeries ... ");


 /* Test case 4 */
  t.gpsSeconds = 45678;
  t.gpsNanoSeconds = 89065834;

  sSequenceIn = NULL;
  LALSCreateVector( &status, &sSequenceIn, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  for ( i=1, sData=sSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, sData++ )
  {
    *(sData) = 0.005;
  }

  strncpy(sFrequencySeries.name,"Complex frequency series",LALNameLength);
  /* set units */
  raise.numerator = -2;
  raise.denominatorMinusOne = 0;
  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&sFrequencySeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  sFrequencySeries.deltaF = 1.3;
  sFrequencySeries.epoch = t;
  sFrequencySeries.f0 = 5;
  sFrequencySeries.data = sSequenceIn;

  sSequenceOut = NULL;
  LALSCreateVector( &status, &sSequenceOut, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  sFrequencySeries2.data = sSequenceOut;
  LALSPrintFrequencySeries(&sFrequencySeries, "sFSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALSReadFrequencySeries(&status, &sFrequencySeries2, "./sFSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (fabs(sFrequencySeries.deltaF - sFrequencySeries2.deltaF)
      /sFrequencySeries.deltaF > READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"Deltaf Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if (strcmp(sFrequencySeries.name,sFrequencySeries2.name)!=0)
  {
    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if ((sFrequencySeries.epoch.gpsSeconds) !=
      (sFrequencySeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((sFrequencySeries.epoch.gpsNanoSeconds) !=
      (sFrequencySeries2.epoch.gpsNanoSeconds))
  {
    fprintf(stderr,"Epoch NanoSeconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if (sFrequencySeries.f0 ?
       (fabs(sFrequencySeries.f0 - sFrequencySeries2.f0)/sFrequencySeries.f0)
       : (fabs(sFrequencySeries.f0 - sFrequencySeries2.f0)) >
       READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  unitComp = XLALUnitCompare(&sFrequencySeries.sampleUnits,&sFrequencySeries2.sampleUnits);

  if (unitComp != 0)
  {
    fprintf(stderr,"Unit Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  for (j = 0; j < sSequenceIn->length;j++)
  {
    if ((sSequenceIn->data[j] ?
	 fabs((sSequenceIn->data[j] - sSequenceOut->data[j])
	      /sSequenceIn->data[j])
	 :fabs(sSequenceIn->data[j] - sSequenceOut->data[j])) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
  }


  LALCDestroyVector(&status, &cSequenceIn);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALCDestroyVector(&status, &cSequenceOut);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALZDestroyVector(&status, &zSequenceIn);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }
  LALZDestroyVector(&status, &zSequenceOut);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALDDestroyVector(&status, &dSequenceIn);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALDDestroyVector(&status, &dSequenceOut);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALSDestroyVector(&status, &sSequenceIn);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALSDestroyVector(&status, &sSequenceOut);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  fprintf(stderr,"PASS\n");


  fprintf(stderr,"Testing Print/Read REAL4TimeSeries ... ");

  /* Here is where testing for ReadTimeSeries is done */
  /* S Case ReadTimeSeries */

  raise.numerator = -2;
  raise.denominatorMinusOne = 0;
  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&sTimeSeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  t.gpsSeconds = 45678;
  t.gpsNanoSeconds = 89065834;

  sSequenceIn = NULL;
  LALSCreateVector( &status, &sSequenceIn, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  for ( i=1, sData=sSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, sData++ )
  {
    *(sData) = 0.005;
  }
  strncpy(sTimeSeries.name,"Real4 Time series",LALNameLength);
  sTimeSeries.deltaT = 1.3;
  sTimeSeries.epoch = t;
  sTimeSeries.data = sSequenceIn;
  sTimeSeries.f0 = 5;
  LALSPrintTimeSeries(&sTimeSeries, "sTSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  sSequenceOut = NULL;
  LALSCreateVector( &status, &sSequenceOut, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  sTimeSeries2.data = sSequenceOut;

  LALSReadTimeSeries(&status, &sTimeSeries2, "./sTSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (fabs(sTimeSeries.deltaT-sTimeSeries2.deltaT) /
      sTimeSeries.deltaT > READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"DeltaT Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if (strcmp(sFrequencySeries.name,sFrequencySeries2.name) != 0)
  {
    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if ((sTimeSeries.epoch.gpsSeconds) != (sTimeSeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((sTimeSeries.epoch.gpsNanoSeconds) != (sTimeSeries2.epoch.gpsNanoSeconds))
  {
    fprintf(stderr,"Epoch NanoSeconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  /*  printf("%f ... %f  f0 value\n",sTimeSeries.f0,sTimeSeries2.f0);*/
  if (sTimeSeries.f0 ?
       (fabs(sTimeSeries.f0 - sTimeSeries2.f0)/sTimeSeries.f0)
       : (fabs(sTimeSeries.f0 - sTimeSeries2.f0)) >
       READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  unitComp = XLALUnitCompare(&sTimeSeries.sampleUnits,&sTimeSeries2.sampleUnits);

  if (unitComp != 0)
  {
    fprintf(stderr,"Units Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  for (j = 0; j < sSequenceIn->length;j++)
  {
    if ((sSequenceIn->data[j] ?
	 fabs((sSequenceIn->data[j] - sSequenceOut->data[j])
	      /sSequenceIn->data[j])
	 :fabs(sSequenceIn->data[j] - sSequenceOut->data[j])) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
  }

  fprintf(stderr,"PASS\n");

  fprintf(stderr,"Testing Print/Read COMPLEX16TimeSeries ... ");

  /* Z case ReadTimeSeries*/

  raise.numerator = -2;
  raise.denominatorMinusOne = 0;
  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&zTimeSeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  t.gpsSeconds = 45678;
  t.gpsNanoSeconds = 89065834;

  zSequenceIn = NULL;
  LALZCreateVector( &status, &zSequenceIn, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  for ( i=1, zData=zSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, zData++ )
  {
    *(zData) = crect( 0.005, 1 );
  }
  strncpy(zTimeSeries.name,"Complex16 Time series",LALNameLength);
  zTimeSeries.deltaT = 1.3;
  zTimeSeries.epoch = t;
  zTimeSeries.data = zSequenceIn;
  zTimeSeries.f0 = 0;
  LALZPrintTimeSeries(&zTimeSeries, "zTSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  zSequenceOut = NULL;
  LALZCreateVector( &status, &zSequenceOut, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  zTimeSeries2.data = zSequenceOut;

  LALZReadTimeSeries(&status, &zTimeSeries2, "./zTSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (fabs(zTimeSeries.deltaT) - (zTimeSeries2.deltaT)/zTimeSeries.deltaT >
      READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"Mismatch DeltaT [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }


  if (strcmp(zTimeSeries.name,zTimeSeries2.name) != 0)
  {
    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if ((zTimeSeries.epoch.gpsSeconds) != (zTimeSeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch Second Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ( (zTimeSeries.epoch.gpsNanoSeconds)
       != (zTimeSeries2.epoch.gpsNanoSeconds) )
  {
    fprintf(stderr,"Epoch Nanosecond Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if (zTimeSeries.f0 ?
       (fabs(zTimeSeries.f0 - zTimeSeries2.f0)/zTimeSeries.f0)
       : (fabs(zTimeSeries.f0 - zTimeSeries2.f0)) >
       READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  unitComp = XLALUnitCompare(&zTimeSeries.sampleUnits,&zTimeSeries2.sampleUnits);

  if (unitComp != 0)
  {
    fprintf(stderr,"Unit Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFUN;
  }

  for (j = 0; j < zSequenceIn->length;j++)
  {
    if ((creal(zSequenceIn->data[j]) ?
	 fabs((creal(zSequenceIn->data[j]) - creal(zSequenceOut->data[j]))
	      /creal(zSequenceIn->data[j]))
	 :fabs(creal(zSequenceIn->data[j]) - creal(zSequenceOut->data[j]))) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
    if ((cimag(zSequenceIn->data[j]) ?
	 fabs((cimag(zSequenceIn->data[j]) - cimag(zSequenceOut->data[j]))
	      /cimag(zSequenceIn->data[j]))
	 :fabs(cimag(zSequenceIn->data[j]) - cimag(zSequenceOut->data[j]))) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
  }

  fprintf(stderr,"PASS\n");

  fprintf(stderr,"Testing Print/Read REAL8TimeSeries ... ");

  /* D case  ReadTimeSeries*/

  raise.numerator = -2;
  raise.denominatorMinusOne = 0;
  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }
  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&sTimeSeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  strncpy(dTimeSeries.name,"REAL8 Time series",LALNameLength);
  dTimeSeries.sampleUnits = lalHertzUnit;
  t.gpsSeconds = 4578;
  t.gpsNanoSeconds = 890634;

  dSequenceIn = NULL;
  LALDCreateVector( &status, &dSequenceIn, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }


  for ( i=1, dData=dSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, dData++ )
  {
    *(dData) = 0.005;
  }

  dTimeSeries.deltaT = 1.3;
  dTimeSeries.epoch = t;
  dTimeSeries.data = dSequenceIn;
  dTimeSeries.f0 = 0;
  LALDPrintTimeSeries(&dTimeSeries, "dTSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  dSequenceOut = NULL;
  LALDCreateVector( &status, &dSequenceOut, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  dTimeSeries2.data = dSequenceOut;
  LALDReadTimeSeries(&status, &dTimeSeries2, "./dTSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (fabs(dTimeSeries.deltaT) - (dTimeSeries2.deltaT)/dTimeSeries.deltaT
      > READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"DeltaT Mismatch [ReadFTSeriesTest:%d,%s]\n",status.statusCode,
	    status.statusDescription );
    return READFTSERIESTESTC_EFLS;
  }
  if (strcmp(dTimeSeries.name,dTimeSeries2.name) != 0)
  {
    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%d,%s]\n",status.statusCode,
	    status.statusDescription );
    return READFTSERIESTESTC_EFLS;
  }

  if ((dTimeSeries.epoch.gpsSeconds) != (dTimeSeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if ((dTimeSeries.epoch.gpsNanoSeconds)
      != (dTimeSeries2.epoch.gpsNanoSeconds))
  {
    fprintf(stderr,"Epoch Nanoseconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if (dTimeSeries.f0 ?
       (fabs(dTimeSeries.f0 - dTimeSeries2.f0)/dTimeSeries.f0)
       : (fabs(dTimeSeries.f0 - dTimeSeries2.f0)) >
       READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  unitComp = XLALUnitCompare(&dTimeSeries.sampleUnits,&dTimeSeries2.sampleUnits);

  if (unitComp != 0)
  {
    fprintf(stderr,"Unit Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  for (j = 0; j < dSequenceIn->length;j++)
  {
    if ((dSequenceIn->data[j] ?
	 fabs((dSequenceIn->data[j] - dSequenceOut->data[j])
	      /dSequenceIn->data[j])
	 :fabs(dSequenceIn->data[j] - dSequenceOut->data[j])) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
  }

  fprintf(stderr,"PASS\n");

  fprintf(stderr,"Testing Print/Read COMPLEX8TimeSeries ... ");

  /* C case ReadTimeSeries*/

  raise.numerator = -2;
  raise.denominatorMinusOne = 0;
  if (XLALUnitRaiseRAT4(&strainToMinus2, &lalStrainUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitRaiseRAT4(&adcToMinus2, &lalADCCountUnit, &raise) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&(adcStrain), &strainToMinus2, &adcToMinus2) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (XLALUnitMultiply(&cTimeSeries.sampleUnits, &adcStrain, &lalHertzUnit) == NULL)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  t.gpsSeconds = 45678;
  t.gpsNanoSeconds = 89065834;

  cSequenceIn = NULL;
  LALCCreateVector( &status, &cSequenceIn, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  for ( i=1, cData=cSequenceIn->data; i<=READFTSERIESTEST_LEN ; i++, cData++ )
  {
    *(cData) = crectf( 0.005, 1 );
  }
  strncpy(cTimeSeries.name,"Complex8 Time series",LALNameLength);
  cTimeSeries.deltaT = 1.3;
  cTimeSeries.epoch = t;
  cTimeSeries.data = cSequenceIn;
  cTimeSeries.f0 = 0;
  cSequenceOut = NULL;
  LALCPrintTimeSeries(&cTimeSeries, "cTSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }
  LALCCreateVector( &status, &cSequenceOut, READFTSERIESTEST_LEN);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  cTimeSeries2.data = cSequenceOut;

  LALCReadTimeSeries(&status, &cTimeSeries2, "./cTSInput.dat");
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  if (fabs(cTimeSeries.deltaT - cTimeSeries2.deltaT)/cTimeSeries.deltaT
      > READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"DeltaT Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  if (strcmp(cTimeSeries.name,cTimeSeries2.name) != 0)
  {
    fprintf(stderr,"Name Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((cTimeSeries.epoch.gpsSeconds) != (cTimeSeries2.epoch.gpsSeconds))
  {
    fprintf(stderr,"Epoch Seconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if ((cTimeSeries.epoch.gpsNanoSeconds)!=(cTimeSeries2.epoch.gpsNanoSeconds))
  {
    fprintf(stderr,"Epoch Nanoseconds Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }
  if (cTimeSeries.f0 ?
       (fabs(cTimeSeries.f0 - cTimeSeries2.f0)/cTimeSeries.f0)
       : (fabs(cTimeSeries.f0 - cTimeSeries2.f0)) >
       READFTSERIESTEST_TOL)
  {
    fprintf(stderr,"f0 Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  unitComp = XLALUnitCompare(&cTimeSeries.sampleUnits,&cTimeSeries2.sampleUnits);

  if (unitComp != 0)
  {
    fprintf(stderr,"Units Mismatch [ReadFTSeriesTest:%s]\n",
	    READFTSERIESTESTC_MSGEFLS);
    return READFTSERIESTESTC_EFLS;
  }

  for (j = 0; j < cSequenceIn->length;j++)
  {
    if ((crealf(cSequenceIn->data[j]) ?
	 fabs((crealf(cSequenceIn->data[j]) - crealf(cSequenceOut->data[j]))
	      /crealf(cSequenceIn->data[j]))
	 :fabs(crealf(cSequenceIn->data[j]) - crealf(cSequenceOut->data[j]))) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
    if ((cimagf(cSequenceIn->data[j]) ?
	 fabs((cimagf(cSequenceIn->data[j]) - cimagf(cSequenceOut->data[j]))
	      /cimagf(cSequenceIn->data[j]))
	 :fabs(cimagf(cSequenceIn->data[j]) - cimagf(cSequenceOut->data[j]))) >
	 READFTSERIESTEST_TOL)
    {
      fprintf(stderr,"Data Tolerance Exceeded [ReadFTSeriesTest:%s]\n",
	      READFTSERIESTESTC_MSGEFLS);
      return READFTSERIESTESTC_EFLS;
    }
  }

  fprintf(stderr,"PASS\n");

  /* *******************Deallocate all memory****************** */
  LALCDestroyVector(&status, &cSequenceIn);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALCDestroyVector(&status, &cSequenceOut);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALZDestroyVector(&status, &zSequenceIn);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALZDestroyVector(&status, &zSequenceOut);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALDDestroyVector(&status, &dSequenceIn);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALDDestroyVector(&status, &dSequenceOut);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALSDestroyVector(&status, &sSequenceIn);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALSDestroyVector(&status, &sSequenceOut);
  if (status.statusCode != 0)
  {
    fprintf(stderr,"[%i]: %s [ReadFTSeriesTest:%s]\n",status.statusCode,
	    status.statusDescription, READFTSERIESTESTC_MSGEFUN);
    return READFTSERIESTESTC_EFUN;
  }

  LALCheckMemoryLeaks();

  fprintf(stderr,"ReadFTSeries passed all tests.\n");

  return READFTSERIESTESTC_ENOM;

}
/**
 * \brief Provides an interface between code build from \ref lalinspiral_findchirp and
 * various simulation packages for injecting chirps into data.
 * \author Brown, D. A. and Creighton, T. D
 *
 * Injects the signals described
 * in the linked list of \c SimInspiralTable structures \c events
 * into the data \c chan. The response function \c resp should
 * contain the response function to use when injecting the signals into the data.
 */
void
LALFindChirpInjectIMR (
    LALStatus                  *status,
    REAL4TimeSeries            *chan,
    SimInspiralTable           *events,
    SimRingdownTable           *ringdownevents,
    COMPLEX8FrequencySeries    *resp,
    INT4                        injectSignalType
    )

{
  UINT4                 k;
  DetectorResponse      detector;
  SimInspiralTable     *thisEvent = NULL;
  SimRingdownTable     *thisRingdownEvent = NULL;
  PPNParamStruc         ppnParams;
  CoherentGW            waveform, *wfm;
  INT8                  waveformStartTime;
  REAL4TimeSeries       signalvec;
  COMPLEX8Vector       *unity = NULL;
  CHAR                  warnMsg[512];
#if 0
  UINT4 n;
  UINT4 i;
#endif

  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );

  ASSERT( chan, status,
      FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT( chan->data, status,
      FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT( chan->data->data, status,
      FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );

  ASSERT( events, status,
      FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );

  ASSERT( resp, status,
      FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT( resp->data, status,
      FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT( resp->data->data, status,
      FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );


  /*
   *
   * set up structures and parameters needed
   *
   */

  /* fixed waveform injection parameters */
  memset( &ppnParams, 0, sizeof(PPNParamStruc) );
  ppnParams.deltaT   = chan->deltaT;
  ppnParams.lengthIn = 0;
  ppnParams.ppn      = NULL;


  /*
   *
   * compute the transfer function from the given response function
   *
   */


  /* allocate memory and copy the parameters describing the freq series */
  memset( &detector, 0, sizeof( DetectorResponse ) );
  detector.transfer = (COMPLEX8FrequencySeries *)
    LALCalloc( 1, sizeof(COMPLEX8FrequencySeries) );
  if ( ! detector.transfer )
  {
    ABORT( status, FINDCHIRPH_EALOC, FINDCHIRPH_MSGEALOC );
  }
  memcpy( &(detector.transfer->epoch), &(resp->epoch),
      sizeof(LIGOTimeGPS) );
  detector.transfer->f0 = resp->f0;
  detector.transfer->deltaF = resp->deltaF;

  detector.site = (LALDetector *) LALMalloc( sizeof(LALDetector) );
  /* set the detector site */
  switch ( chan->name[0] )
  {
    case 'H':
      *(detector.site) = lalCachedDetectors[LALDetectorIndexLHODIFF];
      LALWarning( status, "computing waveform for Hanford." );
      break;
    case 'L':
      *(detector.site) = lalCachedDetectors[LALDetectorIndexLLODIFF];
      LALWarning( status, "computing waveform for Livingston." );
      break;
    case 'G':
      *(detector.site) = lalCachedDetectors[LALDetectorIndexGEO600DIFF];
      LALWarning( status, "computing waveform for GEO600." );
      break;
    case 'T':
      *(detector.site) = lalCachedDetectors[LALDetectorIndexTAMA300DIFF];
      LALWarning( status, "computing waveform for TAMA300." );
      break;
    case 'V':
      *(detector.site) = lalCachedDetectors[LALDetectorIndexVIRGODIFF];
      LALWarning( status, "computing waveform for Virgo." );
      break;
    default:
      LALFree( detector.site );
      detector.site = NULL;
      LALWarning( status, "Unknown detector site, computing plus mode "
          "waveform with no time delay" );
      break;
  }

  /* set up units for the transfer function */
  if (XLALUnitDivide( &(detector.transfer->sampleUnits),
                      &lalADCCountUnit, &lalStrainUnit ) == NULL) {
    ABORTXLAL(status);
  }

  /* invert the response function to get the transfer function */
  LALCCreateVector( status->statusPtr, &( detector.transfer->data ),
      resp->data->length );
  CHECKSTATUSPTR( status );

  LALCCreateVector( status->statusPtr, &unity, resp->data->length );
  CHECKSTATUSPTR( status );
  for ( k = 0; k < resp->data->length; ++k )
  {
    unity->data[k] = 1.0;
  }

  LALCCVectorDivide( status->statusPtr, detector.transfer->data, unity,
      resp->data );
  CHECKSTATUSPTR( status );

  LALCDestroyVector( status->statusPtr, &unity );
  CHECKSTATUSPTR( status );

  thisRingdownEvent = ringdownevents;

  /*
   *
   * loop over the signals and inject them into the time series
   *
   */


  for ( thisEvent = events; thisEvent; thisEvent = thisEvent->next)
  {
    /*
     *
     * generate waveform and inject it into the data
     *
     */


    /* clear the waveform structure */
    memset( &waveform, 0, sizeof(CoherentGW) );

    LALGenerateInspiral(status->statusPtr, &waveform, thisEvent, &ppnParams);
    CHECKSTATUSPTR( status );

    /* add the ringdown */
    wfm = XLALGenerateInspRing( &waveform, thisEvent, thisRingdownEvent,
       injectSignalType );

    if ( !wfm )
    {
      fprintf( stderr, "Failed to generate the waveform \n" );
      if (xlalErrno == XLAL_EFAILED)
      {
        fprintf( stderr, "Too much merger\n");
        XLALDestroyREAL4TimeSeries( chan );
        xlalErrno = XLAL_SUCCESS;
        return;
      }
      else exit ( 1 );
    }


    waveform = *wfm;

    LALInfo( status, ppnParams.termDescription );

    if ( thisEvent->geocent_end_time.gpsSeconds )
    {
      /* get the gps start time of the signal to inject */
      waveformStartTime = XLALGPSToINT8NS( &(thisEvent->geocent_end_time) );
      waveformStartTime -= (INT8) ( 1000000000.0 * ppnParams.tc );
    }
    else
    {
      LALInfo( status, "Waveform start time is zero: injecting waveform "
          "into center of data segment" );

      /* center the waveform in the data segment */
      waveformStartTime = XLALGPSToINT8NS( &(chan->epoch) );

      waveformStartTime += (INT8) ( 1000000000.0 *
          ((REAL8) (chan->data->length - ppnParams.length) / 2.0) * chan->deltaT
          );
    }

    snprintf( warnMsg, sizeof(warnMsg)/sizeof(*warnMsg),
        "Injected waveform timing:\n"
        "thisEvent->geocent_end_time.gpsSeconds = %d\n"
        "thisEvent->geocent_end_time.gpsNanoSeconds = %d\n"
        "ppnParams.tc = %e\n"
        "waveformStartTime = %" LAL_INT8_FORMAT "\n",
        thisEvent->geocent_end_time.gpsSeconds,
        thisEvent->geocent_end_time.gpsNanoSeconds,
        ppnParams.tc,
        waveformStartTime );
    LALInfo( status, warnMsg );

    /* clear the signal structure */
    memset( &signalvec, 0, sizeof(REAL4TimeSeries) );

    /* set the start times for injection */
    XLALINT8NSToGPS( &(waveform.a->epoch), waveformStartTime );
    memcpy( &(waveform.f->epoch), &(waveform.a->epoch),
        sizeof(LIGOTimeGPS) );
    memcpy( &(waveform.phi->epoch), &(waveform.a->epoch),
        sizeof(LIGOTimeGPS) );

    /* set the start time of the signal vector to the start time of the chan */
    signalvec.epoch = chan->epoch;

    /* set the parameters for the signal time series */
    signalvec.deltaT = chan->deltaT;
    if ( ( signalvec.f0 = chan->f0 ) != 0 )
    {
      ABORT( status, FINDCHIRPH_EHETR, FINDCHIRPH_MSGEHETR );
    }
    signalvec.sampleUnits = lalADCCountUnit;

    /* simulate the detectors response to the inspiral */
    LALSCreateVector( status->statusPtr, &(signalvec.data), chan->data->length );
    CHECKSTATUSPTR( status );

    LALSimulateCoherentGW( status->statusPtr,
        &signalvec, &waveform, &detector );
    CHECKSTATUSPTR( status );

/* *****************************************************************************/
#if 0
    FILE *fp;
    char fname[512];
    UINT4 jj, kplus, kcross;
    snprintf( fname, sizeof(fname) / sizeof(*fname),
        "waveform-%d-%d-%s.txt",
        thisEvent->geocent_end_time.gpsSeconds,
        thisEvent->geocent_end_time.gpsNanoSeconds,
        thisEvent->waveform );
    fp = fopen( fname, "w" );
    for( jj = 0, kplus = 0, kcross = 1; jj < waveform.phi->data->length;
        ++jj, kplus += 2, kcross +=2 )
    {
      fprintf(fp, "%d %e %e %le %e\n", jj,
          waveform.a->data->data[kplus],
          waveform.a->data->data[kcross],
          waveform.phi->data->data[jj],
          waveform.f->data->data[jj]);
    }
    fclose( fp );
#endif

/* ********************************************************************************/
#if 0
    FILE *fp;
    char fname[512];
    UINT4 jj;
    snprintf( fname, sizeof(fname) / sizeof(*fname),
        "waveform-%d-%d-%s.txt",
        thisEvent->geocent_end_time.gpsSeconds,
        thisEvent->geocent_end_time.gpsNanoSeconds,
        thisEvent->waveform );
    fp = fopen( fname, "w" );
    for( jj = 0; jj < signalvec.data->length; ++jj )
    {
      fprintf(fp, "%d %e %e \n", jj, signalvec.data->data[jj]);
    }
    fclose( fp );
#endif

/* ********************************************************************************/


    /* inject the signal into the data channel */
    LALSSInjectTimeSeries( status->statusPtr, chan, &signalvec );
    CHECKSTATUSPTR( status );

    /* allocate and go to next SimRingdownTable */
    if( thisEvent->next )
      thisRingdownEvent = thisRingdownEvent->next = (SimRingdownTable *)
      calloc( 1, sizeof(SimRingdownTable) );
    else
      thisRingdownEvent->next = NULL;

    /* destroy the signal */
    LALSDestroyVector( status->statusPtr, &(signalvec.data) );
    CHECKSTATUSPTR( status );

    LALSDestroyVectorSequence( status->statusPtr, &(waveform.a->data) );
    CHECKSTATUSPTR( status );

    LALSDestroyVector( status->statusPtr, &(waveform.f->data) );
    CHECKSTATUSPTR( status );

    LALDDestroyVector( status->statusPtr, &(waveform.phi->data) );
    CHECKSTATUSPTR( status );

    if ( waveform.shift )
    {
      LALSDestroyVector( status->statusPtr, &(waveform.shift->data) );
      CHECKSTATUSPTR( status );
    }

    LALFree( waveform.a );
    LALFree( waveform.f );
    LALFree( waveform.phi );
    if ( waveform.shift )
    {
      LALFree( waveform.shift );
    }

  }

  LALCDestroyVector( status->statusPtr, &( detector.transfer->data ) );
  CHECKSTATUSPTR( status );

  if ( detector.site ) LALFree( detector.site );
  LALFree( detector.transfer );

  DETATCHSTATUSPTR( status );
  RETURN( status );
}
void
LALCOMPLEX8AverageSpectrum (
    LALStatus                   *status,
    COMPLEX8FrequencySeries     *fSeries,
    REAL4TimeSeries             *tSeries0,
    REAL4TimeSeries             *tSeries1,
    AverageSpectrumParams       *params
    )

{
  UINT4                 i, j, k, l;          /* seg, ts and freq counters       */
  UINT4                 numSeg;           /* number of segments in average   */
  UINT4                 fLength;          /* length of requested power spec  */
  UINT4                 tLength;          /* length of time series segments  */
  REAL4Vector          *tSegment[2] = {NULL,NULL};
  COMPLEX8Vector       *fSegment[2] = {NULL,NULL};
  REAL4                *tSeriesPtr0,*tSeriesPtr1 ;
  REAL4                 psdNorm = 0;      /* factor to multiply windows data */
  REAL4                 fftRe0, fftIm0, fftRe1, fftIm1;
  LALUnit               unit;
  /* RAT4                  negRootTwo = { -1, 1 }; */

  INITSTATUS(status);
  XLAL_PRINT_DEPRECATION_WARNING("XLALREAL8AverageSpectrumWelch");
  ATTATCHSTATUSPTR (status);

  /* check the input and output data pointers are non-null */
  ASSERT( fSeries, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( fSeries->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( fSeries->data->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( tSeries0, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( tSeries0->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( tSeries0->data->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
   ASSERT( tSeries1, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( tSeries1->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( tSeries1->data->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );

  /* check the contents of the parameter structure */
  ASSERT( params, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( params->window, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( params->window->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( params->window->data->length > 0, status,
      TIMEFREQFFTH_EZSEG, TIMEFREQFFTH_MSGEZSEG );
  ASSERT( params->plan, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  if ( !  ( params->method == useUnity || params->method == useMean ||
        params->method == useMedian ) )
  {
    ABORT( status, TIMEFREQFFTH_EUAVG, TIMEFREQFFTH_MSGEUAVG );
  }

  /* check that the window length and fft storage lengths agree */
  fLength = fSeries->data->length;
  tLength = params->window->data->length;
  if ( fLength != tLength / 2 + 1 )
  {
    ABORT( status, TIMEFREQFFTH_EMISM, TIMEFREQFFTH_MSGEMISM );
  }

  /* compute the number of segs, check that the length and overlap are valid */
  numSeg = (tSeries0->data->length - params->overlap) / (tLength - params->overlap);
  if ( (tSeries0->data->length - params->overlap) % (tLength - params->overlap) )
  {
    ABORT( status, TIMEFREQFFTH_EMISM, TIMEFREQFFTH_MSGEMISM );
  }

  /* clear the output spectrum and the workspace frequency series */
  memset( fSeries->data->data, 0, fLength * sizeof(COMPLEX8) );

  /* compute the parameters of the output frequency series data */
  fSeries->epoch = tSeries0->epoch;
  fSeries->f0 = tSeries0->f0;
  fSeries->deltaF = 1.0 / ( (REAL8) tLength * tSeries0->deltaT );
  if ( XLALUnitMultiply( &unit, &(tSeries0->sampleUnits), &(tSeries0->sampleUnits) ) == NULL ) {
    ABORTXLAL(status);
  }
  if ( XLALUnitMultiply( &(fSeries->sampleUnits), &unit, &lalSecondUnit ) == NULL ) {
    ABORTXLAL(status);
  }

  /* create temporary storage for the dummy time domain segment */
  for (l = 0; l < 2; l ++){
  LALCreateVector( status->statusPtr, &tSegment[l], tLength );
  CHECKSTATUSPTR( status );

  /* create temporary storage for the individual ffts */
  LALCCreateVector( status->statusPtr, &fSegment[l], fLength );
  CHECKSTATUSPTR( status );}


  /* compute each of the power spectra used in the average */
  for ( i = 0, tSeriesPtr0 = tSeries0->data->data, tSeriesPtr1 = tSeries1->data->data; i < (UINT4) numSeg; ++i )
  {
    /* copy the time series data to the dummy segment */
    memcpy( tSegment[0]->data, tSeriesPtr0, tLength * sizeof(REAL4) );
    memcpy( tSegment[1]->data, tSeriesPtr1, tLength * sizeof(REAL4) );
    /* window the time series segment */
    for ( j = 0; j < tLength; ++j )
    {
      tSegment[0]->data[j] *= params->window->data->data[j];
      tSegment[1]->data[j] *= params->window->data->data[j];
    }

    /* compute the fft of the data segment */
    LALForwardRealFFT( status->statusPtr, fSegment[0], tSegment[0], params->plan );
    CHECKSTATUSPTR (status);
    LALForwardRealFFT( status->statusPtr, fSegment[1], tSegment[1], params->plan );
    CHECKSTATUSPTR (status);

    /* advance the segment data pointer to the start of the next segment */
    tSeriesPtr0 += tLength - params->overlap;
    tSeriesPtr1 += tLength - params->overlap;

    /* compute the psd components */
    /*use mean method here*/
      /* we can get away with less storage */
      for ( k = 0; k < fLength; ++k )
      {
        fftRe0 = crealf(fSegment[0]->data[k]);
        fftIm0 = cimagf(fSegment[0]->data[k]);
        fftRe1 = crealf(fSegment[1]->data[k]);
        fftIm1 = cimagf(fSegment[1]->data[k]);
        fSeries->data->data[k] += fftRe0 * fftRe1 + fftIm0 * fftIm1;
        fSeries->data->data[k] += I * (- fftIm0 * fftRe1 + fftRe0 * fftIm1);

      }

      /* halve the DC and Nyquist components to be consistent with T010095 */
      fSeries->data->data[0] /= 2;
      fSeries->data->data[fLength - 1] /= 2;

      }

  /* destroy the dummy time series segment and the fft scratch space */
  for (l = 0; l < 2; l ++){
  LALDestroyVector( status->statusPtr, &tSegment[l] );
  CHECKSTATUSPTR( status );
  LALCDestroyVector( status->statusPtr, &fSegment[l] );
  CHECKSTATUSPTR( status );}

  /* compute the desired average of the spectra */

    /* normalization constant for the arithmentic mean */
    psdNorm = ( 2.0 * tSeries1->deltaT ) /
      ( (REAL4) numSeg * params->window->sumofsquares );

    /* normalize the psd to it matches the conventions document */
    for ( k = 0; k < fLength; ++k )
      fSeries->data->data[k] *= psdNorm;


  DETATCHSTATUSPTR( status );
  RETURN( status );
}
void
LALREAL4AverageSpectrum (
    LALStatus                   *status,
    REAL4FrequencySeries        *fSeries,
    REAL4TimeSeries             *tSeries,
    AverageSpectrumParams       *params
    )

{
  UINT4                 i, j, k;          /* seg, ts and freq counters       */
  UINT4                 numSeg;           /* number of segments in average   */
  UINT4                 fLength;          /* length of requested power spec  */
  UINT4                 tLength;          /* length of time series segments  */
  REAL4Vector          *tSegment = NULL;  /* dummy time series segment       */
  COMPLEX8Vector       *fSegment = NULL;  /* dummy freq series segment       */
  REAL4                *tSeriesPtr;       /* pointer to the segment data     */
  REAL4                 psdNorm = 0;      /* factor to multiply windows data */
  REAL4                 fftRe, fftIm;     /* real and imag parts of fft      */
  REAL4                *s;                /* work space for computing mean   */
  REAL4                *psdSeg = NULL;    /* storage for individual specta   */
  LALUnit               unit;
  /* RAT4                  negRootTwo = { -1, 1 }; */

  INITSTATUS(status);
  XLAL_PRINT_DEPRECATION_WARNING("XLALREAL4AverageSpectrumWelch");
  ATTATCHSTATUSPTR (status);

  /* check the input and output data pointers are non-null */
  ASSERT( fSeries, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( fSeries->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( fSeries->data->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( tSeries, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( tSeries->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( tSeries->data->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );

  /* check the contents of the parameter structure */
  ASSERT( params, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( params->window, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( params->window->data, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  ASSERT( params->window->data->length > 0, status,
      TIMEFREQFFTH_EZSEG, TIMEFREQFFTH_MSGEZSEG );
  ASSERT( params->plan, status,
      TIMEFREQFFTH_ENULL, TIMEFREQFFTH_MSGENULL );
  if ( !  ( params->method == useUnity || params->method == useMean ||
        params->method == useMedian ) )
  {
    ABORT( status, TIMEFREQFFTH_EUAVG, TIMEFREQFFTH_MSGEUAVG );
  }

  /* check that the window length and fft storage lengths agree */
  fLength = fSeries->data->length;
  tLength = params->window->data->length;
  if ( fLength != tLength / 2 + 1 )
  {
    ABORT( status, TIMEFREQFFTH_EMISM, TIMEFREQFFTH_MSGEMISM );
  }

  /* compute the number of segs, check that the length and overlap are valid */
  numSeg = (tSeries->data->length - params->overlap) / (tLength - params->overlap);
  if ( (tSeries->data->length - params->overlap) % (tLength - params->overlap) )
  {
    ABORT( status, TIMEFREQFFTH_EMISM, TIMEFREQFFTH_MSGEMISM );
  }

  /* clear the output spectrum and the workspace frequency series */
  memset( fSeries->data->data, 0, fLength * sizeof(REAL4) );

  /* compute the parameters of the output frequency series data */
  fSeries->epoch = tSeries->epoch;
  fSeries->f0 = tSeries->f0;
  fSeries->deltaF = 1.0 / ( (REAL8) tLength * tSeries->deltaT );
  if ( XLALUnitMultiply( &unit, &(tSeries->sampleUnits), &(tSeries->sampleUnits) ) == NULL ) {
    ABORTXLAL(status);
  }
  if ( XLALUnitMultiply( &(fSeries->sampleUnits), &unit, &lalSecondUnit ) == NULL ) {
    ABORTXLAL(status);
  }

  /* if this is a unit spectrum, just set the conents to unity and return */
  if ( params->method == useUnity )
  {
    for ( k = 0; k < fLength; ++k )
    {
      fSeries->data->data[k] = 1.0;
    }
    DETATCHSTATUSPTR( status );
    RETURN( status );
  }

  /* create temporary storage for the dummy time domain segment */
  LALCreateVector( status->statusPtr, &tSegment, tLength );
  CHECKSTATUSPTR( status );

  /* create temporary storage for the individual ffts */
  LALCCreateVector( status->statusPtr, &fSegment, fLength );
  CHECKSTATUSPTR( status );

  if ( params->method == useMedian )
  {
    /* create enough storage for the indivdiual power spectra */
    psdSeg = XLALCalloc( numSeg, fLength * sizeof(REAL4) );
  }

  /* compute each of the power spectra used in the average */
  for ( i = 0, tSeriesPtr = tSeries->data->data; i < (UINT4) numSeg; ++i )
  {
    /* copy the time series data to the dummy segment */
    memcpy( tSegment->data, tSeriesPtr, tLength * sizeof(REAL4) );

    /* window the time series segment */
    for ( j = 0; j < tLength; ++j )
    {
      tSegment->data[j] *= params->window->data->data[j];
    }

    /* compute the fft of the data segment */
    LALForwardRealFFT( status->statusPtr, fSegment, tSegment, params->plan );
    CHECKSTATUSPTR (status);

    /* advance the segment data pointer to the start of the next segment */
    tSeriesPtr += tLength - params->overlap;

    /* compute the psd components */
    if ( params->method == useMean )
    {
      /* we can get away with less storage */
      for ( k = 0; k < fLength; ++k )
      {
        fftRe = crealf(fSegment->data[k]);
        fftIm = cimagf(fSegment->data[k]);
        fSeries->data->data[k] += fftRe * fftRe + fftIm * fftIm;
      }

      /* halve the DC and Nyquist components to be consistent with T010095 */
      fSeries->data->data[0] /= 2;
      fSeries->data->data[fLength - 1] /= 2;
    }
    else if ( params->method == useMedian )
    {
      /* we must store all the spectra */
      for ( k = 0; k < fLength; ++k )
      {
        fftRe = crealf(fSegment->data[k]);
        fftIm = cimagf(fSegment->data[k]);
        psdSeg[i * fLength + k] = fftRe * fftRe + fftIm * fftIm;
      }

      /* halve the DC and Nyquist components to be consistent with T010095 */
      psdSeg[i * fLength] /= 2;
      psdSeg[i * fLength + fLength - 1] /= 2;
    }
  }

  /* destroy the dummy time series segment and the fft scratch space */
  LALDestroyVector( status->statusPtr, &tSegment );
  CHECKSTATUSPTR( status );
  LALCDestroyVector( status->statusPtr, &fSegment );
  CHECKSTATUSPTR( status );

  /* compute the desired average of the spectra */
  if ( params->method == useMean )
  {
    /* normalization constant for the arithmentic mean */
    psdNorm = ( 2.0 * tSeries->deltaT ) /
      ( (REAL4) numSeg * params->window->sumofsquares );

    /* normalize the psd to it matches the conventions document */
    for ( k = 0; k < fLength; ++k )
    {
      fSeries->data->data[k] *= psdNorm;
    }
  }
  else if ( params->method == useMedian )
  {
    REAL8 bias;

    /* determine the running median bias */
    /* note: this is not the correct bias if the segments are overlapped */
    if ( params->overlap )
    {
      LALWarning( status, "Overlapping segments with median method causes a biased spectrum." );
    }
    TRY( LALRngMedBias( status->statusPtr, &bias, numSeg ), status );

    /* normalization constant for the median */
    psdNorm = ( 2.0 * tSeries->deltaT ) /
      ( bias * params->window->sumofsquares );

    /* allocate memory array for insert sort */
    s = XLALMalloc( numSeg * sizeof(REAL4) );
    if ( ! s )
    {
      ABORT( status, TIMEFREQFFTH_EMALLOC, TIMEFREQFFTH_MSGEMALLOC );
    }

    /* compute the median spectra and normalize to the conventions doc */
    for ( k = 0; k < fLength; ++k )
    {
      fSeries->data->data[k] = psdNorm *
        MedianSpec( psdSeg, s, k, fLength, numSeg );
    }

    /* free memory used for sort array */
    XLALFree( s );

    /* destroy the storage for the individual spectra */
    XLALFree( psdSeg );
  }

  DETATCHSTATUSPTR( status );
  RETURN( status );
}
Exemple #6
0
int
main(int argc, char **argv)
{
  /* Command-line parsing variables. */
  int arg;                   /* command-line argument counter */
  static LALStatus stat;     /* status structure */
  CHAR *sourcefile = NULL;   /* name of sourcefile */
  CHAR *respfile = NULL;     /* name of respfile */
  CHAR *infile = NULL;       /* name of infile */
  CHAR *outfile = NULL;      /* name of outfile */
  INT4 seed = 0;             /* random number seed */
  INT4 sec = SEC;            /* ouput epoch.gpsSeconds */
  INT4 nsec = NSEC;          /* ouput epoch.gpsNanoSeconds */
  INT4 npt = NPT;            /* number of output points */
  REAL8 dt = DT;             /* output sampling interval */
  REAL4 sigma = SIGMA;       /* noise amplitude */

  /* File reading variables. */
  FILE *fp = NULL; /* generic file pointer */
  BOOLEAN ok = 1;  /* whether input format is correct */
  UINT4 i;         /* generic index over file lines */
  INT8 epoch;      /* epoch stored as an INT8 */

  /* Other global variables. */
  RandomParams *params = NULL; /* parameters of pseudorandom sequence */
  DetectorResponse detector;   /* the detector in question */
  INT2TimeSeries output;       /* detector ACD output */


  /*******************************************************************
   * PARSE ARGUMENTS (arg stores the current position)               *
   *******************************************************************/

  /* Exit gracefully if no arguments were given.
  if ( argc <= 1 ) {
    INFO( "No testing done." );
    return 0;
  } */

  arg = 1;
  while ( arg < argc ) {
    /* Parse source file option. */
    if ( !strcmp( argv[arg], "-s" ) ) {
      if ( argc > arg + 1 ) {
	arg++;
	sourcefile = argv[arg++];
      }else{
	ERROR( BASICINJECTTESTC_EARG, BASICINJECTTESTC_MSGEARG, 0 );
        LALPrintError( USAGE, *argv );
        return BASICINJECTTESTC_EARG;
      }
    }
    /* Parse response file option. */
    else if ( !strcmp( argv[arg], "-r" ) ) {
      if ( argc > arg + 1 ) {
	arg++;
	respfile = argv[arg++];
      }else{
	ERROR( BASICINJECTTESTC_EARG, BASICINJECTTESTC_MSGEARG, 0 );
        LALPrintError( USAGE, *argv );
        return BASICINJECTTESTC_EARG;
      }
    }
    /* Parse input file option. */
    else if ( !strcmp( argv[arg], "-i" ) ) {
      if ( argc > arg + 1 ) {
	arg++;
	infile = argv[arg++];
      }else{
	ERROR( BASICINJECTTESTC_EARG, BASICINJECTTESTC_MSGEARG, 0 );
        LALPrintError( USAGE, *argv );
        return BASICINJECTTESTC_EARG;
      }
    }
    /* Parse noise output option. */
    else if ( !strcmp( argv[arg], "-n" ) ) {
      if ( argc > arg + 5 ) {
	arg++;
	sec = atoi( argv[arg++] );
	nsec = atoi( argv[arg++] );
	npt = atoi( argv[arg++] );
	dt = atof( argv[arg++] );
	sigma = atof( argv[arg++] );
      }else{
	ERROR( BASICINJECTTESTC_EARG, BASICINJECTTESTC_MSGEARG, 0 );
        LALPrintError( USAGE, *argv );
        return BASICINJECTTESTC_EARG;
      }
    }
    /* Parse output file option. */
    else if ( !strcmp( argv[arg], "-o" ) ) {
      if ( argc > arg + 1 ) {
	arg++;
	outfile = argv[arg++];
      }else{
	ERROR( BASICINJECTTESTC_EARG, BASICINJECTTESTC_MSGEARG, 0 );
        LALPrintError( USAGE, *argv );
        return BASICINJECTTESTC_EARG;
      }
    }
    /* Parse debug level option. */
    else if ( !strcmp( argv[arg], "-d" ) ) {
      if ( argc > arg + 1 ) {
	arg++;
      }else{
	ERROR( BASICINJECTTESTC_EARG, BASICINJECTTESTC_MSGEARG, 0 );
        LALPrintError( USAGE, *argv );
        return BASICINJECTTESTC_EARG;
      }
    }
    /* Parse random seed option. */
    else if ( !strcmp( argv[arg], "-e" ) ) {
      if ( argc > arg + 1 ) {
	arg++;
	seed = atoi( argv[arg++] );
      }else{
	ERROR( BASICINJECTTESTC_EARG, BASICINJECTTESTC_MSGEARG, 0 );
        LALPrintError( USAGE, *argv );
        return BASICINJECTTESTC_EARG;
      }
    }
    /* Check for unrecognized options. */
    else if ( argv[arg][0] == '-' ) {
      ERROR( BASICINJECTTESTC_EARG, BASICINJECTTESTC_MSGEARG, 0 );
      LALPrintError( USAGE, *argv );
      return BASICINJECTTESTC_EARG;
    }
  } /* End of argument parsing loop. */

  /* Check for redundant or bad argument values. */
  CHECKVAL( npt, 0, 2147483647 );
  CHECKVAL( dt, 0, LAL_REAL4_MAX );


  /*******************************************************************
   * SETUP                                                           *
   *******************************************************************/

  /* Set up output, detector, and random parameter structures. */
  output.data = NULL;
  detector.transfer = (COMPLEX8FrequencySeries *)
    LALMalloc( sizeof(COMPLEX8FrequencySeries) );
  if ( !(detector.transfer) ) {
    ERROR( BASICINJECTTESTC_EMEM, BASICINJECTTESTC_MSGEMEM, 0 );
    return BASICINJECTTESTC_EMEM;
  }
  detector.transfer->data = NULL;
  detector.site = NULL;
  SUB( LALCreateRandomParams( &stat, &params, seed ), &stat );

  /* Set up units. */
  output.sampleUnits = lalADCCountUnit;
  if (XLALUnitDivide( &(detector.transfer->sampleUnits),
                      &lalADCCountUnit, &lalStrainUnit ) == NULL) {
    return LAL_EXLAL;
  }

  /* Read response function. */
  if ( respfile ) {
    REAL4VectorSequence *resp = NULL; /* response as vector sequence */
    COMPLEX8Vector *response = NULL;  /* response as complex vector */
    COMPLEX8Vector *unity = NULL;     /* vector of complex 1's */

    if ( ( fp = fopen( respfile, "r" ) ) == NULL ) {
      ERROR( BASICINJECTTESTC_EFILE, BASICINJECTTESTC_MSGEFILE,
	     respfile );
      return BASICINJECTTESTC_EFILE;
    }

    /* Read header. */
    ok &= ( fscanf( fp, "# epoch = %" LAL_INT8_FORMAT "\n", &epoch ) == 1 );
    I8ToLIGOTimeGPS( &( detector.transfer->epoch ), epoch );
    ok &= ( fscanf( fp, "# f0 = %lf\n", &( detector.transfer->f0 ) )
	    == 1 );
    ok &= ( fscanf( fp, "# deltaF = %lf\n",
		    &( detector.transfer->deltaF ) ) == 1 );
    if ( !ok ) {
      ERROR( BASICINJECTTESTC_EINPUT, BASICINJECTTESTC_MSGEINPUT,
	     respfile );
      return BASICINJECTTESTC_EINPUT;
    }

    /* Read and convert body to a COMPLEX8Vector. */
    SUB( LALSReadVectorSequence( &stat, &resp, fp ), &stat );
    fclose( fp );
    if ( resp->vectorLength != 2 ) {
      ERROR( BASICINJECTTESTC_EINPUT, BASICINJECTTESTC_MSGEINPUT,
	     respfile );
      return BASICINJECTTESTC_EINPUT;
    }
    SUB( LALCCreateVector( &stat, &response, resp->length ), &stat );
    memcpy( response->data, resp->data, 2*resp->length*sizeof(REAL4) );
    SUB( LALSDestroyVectorSequence( &stat, &resp ), &stat );

    /* Convert response function to a transfer function. */
    SUB( LALCCreateVector( &stat, &unity, response->length ), &stat );
    for ( i = 0; i < response->length; i++ ) {
      unity->data[i] = 1.0;
    }
    SUB( LALCCreateVector( &stat, &( detector.transfer->data ),
			   response->length ), &stat );
    SUB( LALCCVectorDivide( &stat, detector.transfer->data, unity,
			    response ), &stat );
    SUB( LALCDestroyVector( &stat, &response ), &stat );
    SUB( LALCDestroyVector( &stat, &unity ), &stat );
  }

  /* No response file, so generate a unit response. */
  else {
    I8ToLIGOTimeGPS( &( detector.transfer->epoch ), EPOCH );
    detector.transfer->f0 = 0.0;
    detector.transfer->deltaF = 1.5*FSTOP;
    SUB( LALCCreateVector( &stat, &( detector.transfer->data ), 2 ),
	 &stat );
    detector.transfer->data->data[0] = 1.0;
    detector.transfer->data->data[1] = 1.0;
  }


  /* Read input data. */
  if ( infile ) {
    REAL4VectorSequence *input = NULL; /* input as vector sequence */
    if ( ( fp = fopen( infile, "r" ) ) == NULL ) {
      ERROR( BASICINJECTTESTC_EFILE, BASICINJECTTESTC_MSGEFILE,
	     infile );
      return BASICINJECTTESTC_EFILE;
    }

    /* Read header. */
    ok &= ( fscanf( fp, "# epoch = %" LAL_INT8_FORMAT "\n", &epoch ) == 1 );
    I8ToLIGOTimeGPS( &( output.epoch ), epoch );
    ok &= ( fscanf( fp, "# deltaT = %lf\n", &( output.deltaT ) )
	    == 1 );
    if ( !ok ) {
      ERROR( BASICINJECTTESTC_EINPUT, BASICINJECTTESTC_MSGEINPUT,
	     infile );
      return BASICINJECTTESTC_EINPUT;
    }

    /* Read and convert body. */
    SUB( LALSReadVectorSequence( &stat, &input, fp ), &stat );
    fclose( fp );
    if ( input->vectorLength != 1 ) {
      ERROR( BASICINJECTTESTC_EINPUT, BASICINJECTTESTC_MSGEINPUT,
	     infile );
      return BASICINJECTTESTC_EINPUT;
    }
    SUB( LALI2CreateVector( &stat, &( output.data ), input->length ),
	 &stat );
    for ( i = 0; i < input->length; i++ )
      output.data->data[i] = (INT2)( input->data[i] );
    SUB( LALSDestroyVectorSequence( &stat, &input ), &stat );
  }

  /* No input file, so generate one randomly. */
  else {
    output.epoch.gpsSeconds = sec;
    output.epoch.gpsNanoSeconds = nsec;
    output.deltaT = dt;
    SUB( LALI2CreateVector( &stat, &( output.data ), npt ), &stat );
    if ( sigma == 0 ) {
      memset( output.data->data, 0, npt*sizeof(INT2) );
    } else {
      REAL4Vector *deviates = NULL; /* unit Gaussian deviates */
      SUB( LALSCreateVector( &stat, &deviates, npt ), &stat );
      SUB( LALNormalDeviates( &stat, deviates, params ), &stat );
      for ( i = 0; i < (UINT4)( npt ); i++ )
	output.data->data[i] = (INT2)
	  floor( sigma*deviates->data[i] + 0.5 );
      SUB( LALSDestroyVector( &stat, &deviates ), &stat );
    }
  }


  /*******************************************************************
   * INJECTION                                                       *
   *******************************************************************/

  /* Open sourcefile. */
  if ( sourcefile ) {
    if ( ( fp = fopen( sourcefile, "r" ) ) == NULL ) {
      ERROR( BASICINJECTTESTC_EFILE, BASICINJECTTESTC_MSGEFILE,
	     sourcefile );
      return BASICINJECTTESTC_EFILE;
    }
  }

  /* For each line in the sourcefile... */
  while ( ok ) {
    PPNParamStruc ppnParams;       /* wave generation parameters */
    REAL4 m1, m2, dist, inc, phic; /* unconverted parameters */
    CoherentGW waveform;           /* amplitude and phase structure */
    REAL4TimeSeries signalvec;     /* GW signal */
    REAL8 time;                    /* length of GW signal */
    CHAR timeCode;                 /* code for signal time alignment */
    CHAR message[MSGLEN];          /* warning/info messages */

    /* Read and convert input line. */
    if ( sourcefile ) {
      ok &= ( fscanf( fp, "%c %" LAL_INT8_FORMAT " %f %f %f %f %f\n", &timeCode,
		      &epoch, &m1, &m2, &dist, &inc, &phic ) == 7 );
      ppnParams.mTot = m1 + m2;
      ppnParams.eta = m1*m2/( ppnParams.mTot*ppnParams.mTot );
      ppnParams.d = dist*LAL_PC_SI*1000.0;
      ppnParams.inc = inc*LAL_PI/180.0;
      ppnParams.phi = phic*LAL_PI/180.0;
    } else {
      timeCode = 'i';
      ppnParams.mTot = M1 + M2;
      ppnParams.eta = M1*M2/( ppnParams.mTot*ppnParams.mTot );
      ppnParams.d = DIST;
      ppnParams.inc = INC;
      ppnParams.phi = PHIC;
      epoch = EPOCH;
    }

    if ( ok ) {
      /* Set up other parameter structures. */
      ppnParams.epoch.gpsSeconds = ppnParams.epoch.gpsNanoSeconds = 0;
      ppnParams.position.latitude = ppnParams.position.longitude = 0.0;
      ppnParams.position.system = COORDINATESYSTEM_EQUATORIAL;
      ppnParams.psi = 0.0;
      ppnParams.fStartIn = FSTART;
      ppnParams.fStopIn = FSTOP;
      ppnParams.lengthIn = 0;
      ppnParams.ppn = NULL;
      ppnParams.deltaT = DELTAT;
      memset( &waveform, 0, sizeof(CoherentGW) );

      /* Generate waveform at zero epoch. */
      SUB( LALGeneratePPNInspiral( &stat, &waveform, &ppnParams ),
	   &stat );
      snprintf( message, MSGLEN, "%d: %s", ppnParams.termCode,
		   ppnParams.termDescription );
      INFO( message );
      if ( ppnParams.dfdt > 2.0 ) {
	snprintf( message, MSGLEN,
		     "Waveform sampling interval is too large:\n"
		     "\tmaximum df*dt = %f", ppnParams.dfdt );
	WARNING( message );
      }

      /* Compute epoch for waveform. */
      time = waveform.a->data->length*DELTAT;
      if ( timeCode == 'f' )
	epoch -= (INT8)( 1000000000.0*time );
      else if ( timeCode == 'c' )
	epoch -= (INT8)( 1000000000.0*ppnParams.tc );
      I8ToLIGOTimeGPS( &( waveform.a->epoch ), epoch );
      waveform.f->epoch = waveform.phi->epoch = waveform.a->epoch;

      /* Generate and inject signal. */
      signalvec.epoch = waveform.a->epoch;
      signalvec.epoch.gpsSeconds -= 1;
      signalvec.deltaT = output.deltaT/4.0;
      signalvec.f0 = 0;
      signalvec.data = NULL;
      time = ( time + 2.0 )/signalvec.deltaT;
      SUB( LALSCreateVector( &stat, &( signalvec.data ), (UINT4)time ),
	   &stat );
      SUB( LALSimulateCoherentGW( &stat, &signalvec, &waveform,
				  &detector ), &stat );
      SUB( LALSI2InjectTimeSeries( &stat, &output, &signalvec, params ),
	   &stat );
      SUB( LALSDestroyVectorSequence( &stat, &( waveform.a->data ) ),
	   &stat );
      SUB( LALSDestroyVector( &stat, &( waveform.f->data ) ), &stat );
      SUB( LALDDestroyVector( &stat, &( waveform.phi->data ) ), &stat );
      LALFree( waveform.a );
      LALFree( waveform.f );
      LALFree( waveform.phi );
      SUB( LALSDestroyVector( &stat, &( signalvec.data ) ), &stat );
    }

    /* If there is no source file, inject only one source. */
    if ( !sourcefile )
      ok = 0;
  }

  /* Input file is exhausted (or has a badly-formatted line ). */
  if ( sourcefile )
    fclose( fp );


  /*******************************************************************
   * CLEANUP                                                         *
   *******************************************************************/

  /* Print output file. */
  if ( outfile ) {
    if ( ( fp = fopen( outfile, "w" ) ) == NULL ) {
      ERROR( BASICINJECTTESTC_EFILE, BASICINJECTTESTC_MSGEFILE,
	     outfile );
      return BASICINJECTTESTC_EFILE;
    }
    epoch = 1000000000LL*(INT8)( output.epoch.gpsSeconds );
    epoch += (INT8)( output.epoch.gpsNanoSeconds );
    fprintf( fp, "# epoch = %" LAL_INT8_FORMAT "\n", epoch );
    fprintf( fp, "# deltaT = %23.16e\n", output.deltaT );
    for ( i = 0; i < output.data->length; i++ )
      fprintf( fp, "%8.1f\n", (REAL4)( output.data->data[i] ) );
    fclose( fp );
  }

  /* Destroy remaining memory. */
  SUB( LALDestroyRandomParams( &stat, &params ), &stat );
  SUB( LALI2DestroyVector( &stat, &( output.data ) ), &stat );
  SUB( LALCDestroyVector( &stat, &( detector.transfer->data ) ),
       &stat );
  LALFree( detector.transfer );

  /* Done! */
  LALCheckMemoryLeaks();
  INFO( BASICINJECTTESTC_MSGENORM );
  return BASICINJECTTESTC_ENORM;
}
int
main ( int argc, char *argv[] )
{
  const int size = 8;
  COMPLEX8Vector *z1 = NULL;
  COMPLEX8Vector *z2 = NULL;
  COMPLEX8Vector *z3 = NULL;
  REAL4Vector    *x1 = NULL;
  REAL4Vector    *x2 = NULL;
  REAL4Vector    *x3 = NULL;
  REAL4Vector    *y_1 = NULL;
  REAL4Vector    *y2 = NULL;
  REAL4Vector    *y3 = NULL;
  static LALStatus   status;
  INT4            i;


  ParseOptions( argc, argv );

  LALCCreateVector(&status, &z1, size);
  TestStatus( &status, CODES(0), 1 );
  LALCCreateVector(&status, &z2, size);
  TestStatus( &status, CODES(0), 1 );
  LALCCreateVector(&status, &z3, size);
  TestStatus( &status, CODES(0), 1 );
  LALSCreateVector(&status, &x1, size);
  TestStatus( &status, CODES(0), 1 );
  LALSCreateVector(&status, &x2, size);
  TestStatus( &status, CODES(0), 1 );
  LALSCreateVector(&status, &x3, size);
  TestStatus( &status, CODES(0), 1 );
  LALSCreateVector(&status, &y_1, size/2);
  TestStatus( &status, CODES(0), 1 );
  y2         = (REAL4Vector *)LALMalloc(sizeof(REAL4Vector));
  y2->data   = NULL;
  y2->length = size;
  y3         = (REAL4Vector *)LALMalloc(sizeof(REAL4Vector));
  y3->data   = (REAL4 *)LALMalloc(size*sizeof(REAL4));
  y3->length = 0;

  for (i = 0; i < size; ++i)
  {
    z1->data[i] = 1 + i;
    z1->data[i] += I * (2 + i*i);
    z2->data[i] = 3 + i + i*i*i;
    z2->data[i] += I * (4 + i*i + i*i*i);
    x1->data[i]    = 5 + i + i*i;
    x2->data[i]    = 6 + i + i*i + i*i*i;
  }

  if (verbose) printf("\n");
  LALCCVectorMultiply(&status, z3, z1, z2);
  TestStatus( &status, CODES(0), 1 );
  for (i = 0; i < size; ++i)
    if (verbose) printf("(% 6.0f,% 6.0f) x (% 6.0f,% 6.0f) = (% 6.0f,% 6.0f)\n",
        crealf(z1->data[i]), cimagf(z1->data[i]),
        crealf(z2->data[i]), cimagf(z2->data[i]),
        crealf(z3->data[i]), cimagf(z3->data[i]));

  if (verbose) printf("\n");
  LALCCVectorMultiplyConjugate(&status, z3, z1, z2);
  TestStatus( &status, CODES(0), 1 );
  for (i = 0; i < size; ++i)
    if (verbose) printf("(% 6.0f,% 6.0f) x (% 6.0f,% 6.0f)* = (% 6.0f,% 6.0f)\n",
        crealf(z1->data[i]), cimagf(z1->data[i]),
        crealf(z2->data[i]), cimagf(z2->data[i]),
        crealf(z3->data[i]), cimagf(z3->data[i]));

  if (verbose) printf("\n");
  LALCCVectorDivide(&status, z3, z1, z2);
  TestStatus( &status, CODES(0), 1 );
  for (i = 0; i < size; ++i)
    if (verbose) printf("(% 6.0f,% 6.0f) / (% 6.0f,% 6.0f) = (% 9.6f,% 9.6f)\n",
        crealf(z1->data[i]), cimagf(z1->data[i]),
        crealf(z2->data[i]), cimagf(z2->data[i]),
        crealf(z3->data[i]), cimagf(z3->data[i]));

  if (verbose) printf("\n");
  LALSCVectorMultiply(&status, z3, x1, z1);
  TestStatus( &status, CODES(0), 1 );
  for (i = 0; i < size; ++i)
    if (verbose) printf("% 6.0f x (% 6.0f,% 6.0f) = (% 6.0f,% 6.0f)\n",
        crealf(x1->data[i]),
        crealf(z1->data[i]), cimagf(z1->data[i]),
        crealf(z3->data[i]), cimagf(z3->data[i]));

  if (verbose) printf("\n");
  LALSSVectorMultiply(&status, x3, x1, x2);
  TestStatus( &status, CODES(0), 1 );
  for (i = 0; i < size; ++i)
    if (verbose) printf("% 6.0f x % 6.0f = % 6.0f\n",
        x1->data[i], x2->data[i], x3->data[i]);

  if (verbose) printf("\n");
#ifndef LAL_NDEBUG
  if ( ! lalNoDebug )
  {
    LALSSVectorMultiply(&status, x3, x1, NULL);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALSSVectorMultiply(&status, x3, y2, x2);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALSSVectorMultiply(&status, y3, x1, x2);
    TestStatus( &status, CODES(VECTOROPSH_ESIZE), 1 );
    LALSSVectorMultiply(&status, x3, x1, y_1);
    TestStatus( &status, CODES(VECTOROPSH_ESZMM), 1 );
  }
#endif

  LALCDestroyVector(&status, &z1);
  TestStatus( &status, CODES(0), 1 );
  LALCDestroyVector(&status, &z2);
  TestStatus( &status, CODES(0), 1 );
  LALCDestroyVector(&status, &z3);
  TestStatus( &status, CODES(0), 1 );
  LALSDestroyVector(&status, &x1);
  TestStatus( &status, CODES(0), 1 );
  LALSDestroyVector(&status, &x2);
  TestStatus( &status, CODES(0), 1 );
  LALSDestroyVector(&status, &x3);
  TestStatus( &status, CODES(0), 1 );
  LALSDestroyVector(&status, &y_1);
  TestStatus( &status, CODES(0), 1 );
  LALFree(y2);
  LALFree(y3->data);
  LALFree(y3);

  x1 = x2 = x3 = y_1 = y2 = y3 = NULL;
  z1 = z2 = z3 = NULL;


  LALCCreateVector(&status, &z1, size);
  TestStatus( &status, CODES(0), 1 );

  LALSCreateVector(&status, &x1, size);
  TestStatus( &status, CODES(0), 1 );
  LALSCreateVector(&status, &x2, size);
  TestStatus( &status, CODES(0), 1 );
  LALSCreateVector(&status, &x3, size);
  TestStatus( &status, CODES(0), 1 );


  for (i = 0; i < size; ++i)
  {
    z1->data[i] = (12.0 + i) *cos(LAL_PI/3.0*i);
    z1->data[i] += I * (12.0 + i )*sin(LAL_PI/3.0*i);
  }

  if (verbose) printf("\n");
  LALCVectorAbs(&status, x1, z1);
  TestStatus( &status, CODES(0), 1 );
  for (i = 0; i < size; ++i)
    if (verbose) printf(" Abs(% f,%f)  = %f \n",
        crealf(z1->data[i]), cimagf(z1->data[i]),
        x1->data[i]);

  LALCVectorAngle(&status, x2, z1);
  TestStatus( &status, CODES(0), 1 );
  for (i = 0; i < size; ++i)
    if (verbose) printf(" Angle(%f,%f)  = %f \n",
        crealf(z1->data[i]), cimagf(z1->data[i]),
        x2->data[i]);

  LALUnwrapREAL4Angle(&status, x3, x2);
  TestStatus( &status, CODES(0), 1 );
  for (i = 0; i < size; ++i)
    if (verbose) printf(" Unwrap Phase Angle ( %f )  = %f \n",
        x2->data[i],
        x3->data[i]);


  LALSCreateVector(&status, &y_1, size/2);
  TestStatus( &status, CODES(0), 1 );

  y2         = (REAL4Vector *)LALMalloc(sizeof(REAL4Vector));
  y2->data   = NULL;
  y2->length = size;

  y3         = (REAL4Vector *)LALMalloc(sizeof(REAL4Vector));
  y3->data   = (REAL4 *)LALMalloc(size*sizeof(REAL4));
  y3->length = 0;

  if (verbose) printf("\n");

#ifndef LAL_NDEBUG
  if ( ! lalNoDebug )
  {
    LALCVectorAbs(&status, x1, NULL);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALCVectorAbs(&status, NULL, z1);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALCVectorAbs(&status, y_1, z1);
    TestStatus( &status, CODES(VECTOROPSH_ESZMM), 1 );
    LALCVectorAbs(&status, y2, z1);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALCVectorAbs(&status, y3, z1);
    TestStatus( &status, CODES(VECTOROPSH_ESIZE), 1 );


    LALCVectorAngle(&status, x2, NULL);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALCVectorAngle(&status, NULL, z1);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALCVectorAngle(&status, y_1, z1);
    TestStatus( &status, CODES(VECTOROPSH_ESZMM), 1 );
    LALCVectorAngle(&status, y2, z1);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALCVectorAngle(&status, y3, z1);
    TestStatus( &status, CODES(VECTOROPSH_ESIZE), 1 );

    LALUnwrapREAL4Angle(&status, x3, NULL);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALUnwrapREAL4Angle(&status, NULL, x2);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALUnwrapREAL4Angle(&status, y_1, x2);
    TestStatus( &status, CODES(VECTOROPSH_ESZMM), 1 );
    LALUnwrapREAL4Angle(&status, y2, x2);
    TestStatus( &status, CODES(VECTOROPSH_ENULL), 1 );
    LALUnwrapREAL4Angle(&status, y3, x2);
    TestStatus( &status, CODES(VECTOROPSH_ESIZE), 1 );
    LALUnwrapREAL4Angle(&status, x2, x2);
    TestStatus( &status, CODES(VECTOROPSH_ESAME), 1 );
  }
#endif


  LALCDestroyVector(&status, &z1);
  TestStatus( &status, CODES(0), 1 );

  LALSDestroyVector(&status, &x1);
  TestStatus( &status, CODES(0), 1 );
  LALSDestroyVector(&status, &x2);
  TestStatus( &status, CODES(0), 1 );
  LALSDestroyVector(&status, &x3);
  TestStatus( &status, CODES(0), 1 );

  LALSDestroyVector(&status, &y_1);
  TestStatus( &status, CODES(0), 1 );
  LALFree(y2);
  LALFree(y3->data);
  LALFree(y3);

  LALCheckMemoryLeaks();
  return 0;
}
Exemple #8
0
void
LALRingInjectSignals(
    LALStatus               *stat,
    REAL4TimeSeries         *series,
    SimRingdownTable        *injections,
    COMPLEX8FrequencySeries *resp,
    INT4                     calType
    )

{
  UINT4              k;
  INT4               injStartTime;
  INT4               injStopTime;
  DetectorResponse   detector;
  COMPLEX8Vector    *unity = NULL;
  CoherentGW         waveform;
  RingParamStruc     ringParam;
  REAL4TimeSeries    signalvec;
  SimRingdownTable  *simRingdown=NULL;
  LALDetector       *tmpDetector=NULL /*,*nullDetector=NULL*/;
  COMPLEX8FrequencySeries    *transfer = NULL;

  INITSTATUS(stat);
  ATTATCHSTATUSPTR( stat );

  /* set up start and end of injection zone TODO: fix this hardwired 10 */
  injStartTime = series->epoch.gpsSeconds - 10;
  injStopTime = series->epoch.gpsSeconds + 10 + (INT4)(series->data->length
      * series->deltaT);

  /*
   *compute the transfer function
   */

  /* allocate memory and copy the parameters describing the freq series */
  memset( &detector, 0, sizeof( DetectorResponse ) );
  transfer = (COMPLEX8FrequencySeries *)
    LALCalloc( 1, sizeof(COMPLEX8FrequencySeries) );
  if ( ! transfer )
  {
    ABORT( stat, GENERATERINGH_EMEM, GENERATERINGH_MSGEMEM );
  }
  memcpy( &(transfer->epoch), &(resp->epoch),
      sizeof(LIGOTimeGPS) );
  transfer->f0 = resp->f0;
  transfer->deltaF = resp->deltaF;

  tmpDetector = detector.site = (LALDetector *) LALMalloc( sizeof(LALDetector) );
  /* set the detector site */
  switch ( series->name[0] )
  {
    case 'H':
      *(detector.site) = lalCachedDetectors[LALDetectorIndexLHODIFF];
      LALWarning( stat, "computing waveform for Hanford." );
      break;
    case 'L':
      *(detector.site) = lalCachedDetectors[LALDetectorIndexLLODIFF];
      LALWarning( stat, "computing waveform for Livingston." );
      break;
    default:
      LALFree( detector.site );
      detector.site = NULL;
      tmpDetector = NULL;
      LALWarning( stat, "Unknown detector site, computing plus mode "
          "waveform with no time delay" );
      break;
  }

  /* set up units for the transfer function */
  if (XLALUnitDivide( &(detector.transfer->sampleUnits),
                      &lalADCCountUnit, &lalStrainUnit ) == NULL) {
    ABORTXLAL(stat);
  }

  /* invert the response function to get the transfer function */
  LALCCreateVector( stat->statusPtr, &( transfer->data ),
      resp->data->length );
  CHECKSTATUSPTR( stat );

  LALCCreateVector( stat->statusPtr, &unity, resp->data->length );
  CHECKSTATUSPTR( stat );
  for ( k = 0; k < resp->data->length; ++k )
  {
    unity->data[k] = 1.0;
  }

  LALCCVectorDivide( stat->statusPtr, transfer->data, unity,
      resp->data );
  CHECKSTATUSPTR( stat );

  LALCDestroyVector( stat->statusPtr, &unity );
  CHECKSTATUSPTR( stat );

  /* Set up a time series to hold signal in ADC counts */
  signalvec.deltaT = series->deltaT;
  if ( ( signalvec.f0 = series->f0 ) != 0 )
  {
    ABORT( stat, GENERATERINGH_EMEM, GENERATERINGH_MSGEMEM );
  }
  signalvec.sampleUnits = lalADCCountUnit;

  signalvec.data=NULL;
  LALSCreateVector( stat->statusPtr, &(signalvec.data),
      series->data->length );
  CHECKSTATUSPTR( stat );

  /* loop over list of waveforms and inject into data stream */
  simRingdown = injections;
  while ( simRingdown )
  {
    /* only do the work if the ring is in injection zone */
    if( (injStartTime - simRingdown->geocent_start_time.gpsSeconds) *
        (injStopTime - simRingdown->geocent_start_time.gpsSeconds) > 0 )
    {
      simRingdown = simRingdown->next;
      continue;
    }

    /* set the ring params */
    ringParam.deltaT = series->deltaT;
    if( !( strcmp( simRingdown->coordinates, "HORIZON" ) ) )
    {
      ringParam.system = COORDINATESYSTEM_HORIZON;
    }
    else if ( !( strcmp( simRingdown->coordinates, "ZENITH" ) ) )
    {
      /* set coordinate system for completeness */
      ringParam.system = COORDINATESYSTEM_EQUATORIAL;
      detector.site = NULL;
    }
    else if ( !( strcmp( simRingdown->coordinates, "GEOGRAPHIC" ) ) )
    {
     ringParam.system = COORDINATESYSTEM_GEOGRAPHIC;
    }
    else if ( !( strcmp( simRingdown->coordinates, "EQUATORIAL" ) ) )
    {
      ringParam.system = COORDINATESYSTEM_EQUATORIAL;
    }
    else if ( !( strcmp( simRingdown->coordinates, "ECLIPTIC" ) ) )
    {
      ringParam.system = COORDINATESYSTEM_ECLIPTIC;
    }
    else if ( !( strcmp( simRingdown->coordinates, "GALACTIC" ) ) )
    {
      ringParam.system = COORDINATESYSTEM_GALACTIC;
    }
    else
      ringParam.system = COORDINATESYSTEM_EQUATORIAL;

    /* generate the ring */
    memset( &waveform, 0, sizeof(CoherentGW) );
    LALGenerateRing( stat->statusPtr, &waveform, series, simRingdown, &ringParam );
    CHECKSTATUSPTR( stat );

    /* print the waveform to a file */
    if ( 0 )
      {
        FILE *fp;
        char fname[512];
        UINT4 jj, kplus, kcross;
        snprintf( fname, sizeof(fname) / sizeof(*fname),
            "waveform-%d-%d-%s.txt",
            simRingdown->geocent_start_time.gpsSeconds,
            simRingdown->geocent_start_time.gpsNanoSeconds,
            simRingdown->waveform );
        fp = fopen( fname, "w" );

        for( jj = 0, kplus = 0, kcross = 1; jj < waveform.phi->data->length;
            ++jj, kplus += 2, kcross +=2 )
          {
            fprintf(fp, "%d %e %e %le %e\n", jj,
                waveform.a->data->data[kplus],
                waveform.a->data->data[kcross],
                waveform.phi->data->data[jj],
                waveform.f->data->data[jj]);
            }
        fclose( fp );
        }
    /* end */
#if 0
    fprintf( stderr, "a->epoch->gpsSeconds = %d\na->epoch->gpsNanoSeconds = %d\n",
        waveform.a->epoch.gpsSeconds, waveform.a->epoch.gpsNanoSeconds );
    fprintf( stderr, "phi->epoch->gpsSeconds = %d\nphi->epoch->gpsNanoSeconds = %d\n",
        waveform.phi->epoch.gpsSeconds, waveform.phi->epoch.gpsNanoSeconds );
    fprintf( stderr, "f->epoch->gpsSeconds = %d\nf->epoch->gpsNanoSeconds = %d\n",
        waveform.f->epoch.gpsSeconds, waveform.f->epoch.gpsNanoSeconds );
#endif
    /* must set the epoch of signal since it's used by coherent GW */
    signalvec.epoch = series->epoch;
    memset( signalvec.data->data, 0, signalvec.data->length * sizeof(REAL4) );

    /* decide which way to calibrate the data; defaul to old way */
    if( calType )
      detector.transfer=NULL;
    else
      detector.transfer=transfer;

    /* convert this into an ADC signal */
    LALSimulateCoherentGW( stat->statusPtr,
        &signalvec, &waveform, &detector );
    CHECKSTATUSPTR( stat );


/* print the waveform to a file */
    if ( 0 )
      {
        FILE *fp;
        char fname[512];
        UINT4 jj;
        snprintf( fname, sizeof(fname) / sizeof(*fname),
            "signal-%d-%d-%s.txt",
            simRingdown->geocent_start_time.gpsSeconds,
            simRingdown->geocent_start_time.gpsNanoSeconds,
            simRingdown->waveform );
        fp = fopen( fname, "w" );

        for( jj = 0; jj < signalvec.data->length; ++jj )
          {
            fprintf( fp, "%d %le\n", jj, signalvec.data->data[jj] );
          }
        fclose( fp );
        }
    /* end */
#if 0
    fprintf( stderr, "series.epoch->gpsSeconds = %d\nseries.epoch->gpsNanoSeconds = %d\n",
        series->epoch.gpsSeconds, series->epoch.gpsNanoSeconds );
    fprintf( stderr, "signalvec->epoch->gpsSeconds = %d\nsignalvec->epoch->gpsNanoSeconds = %d\n",
        signalvec.epoch.gpsSeconds, signalvec.epoch.gpsNanoSeconds );
#endif
    /* if calibration using RespFilt */
    if( calType == 1 )
      XLALRespFilt(&signalvec, transfer);

    /* inject the signal into the data channel */
    LALSSInjectTimeSeries( stat->statusPtr, series, &signalvec );
    CHECKSTATUSPTR( stat );

/* free memory in coherent GW structure.  TODO:  fix this */
    LALSDestroyVectorSequence( stat->statusPtr, &( waveform.a->data ) );
    CHECKSTATUSPTR( stat );
    LALSDestroyVector( stat->statusPtr, &( waveform.f->data ) );
    CHECKSTATUSPTR( stat );
    LALDDestroyVector( stat->statusPtr, &( waveform.phi->data ) );
    CHECKSTATUSPTR( stat );
    LALFree( waveform.a );   waveform.a = NULL;
    LALFree( waveform.f );   waveform.f = NULL;
    LALFree( waveform.phi );  waveform.phi = NULL;

    /* reset the detector site information in case it changed */
    detector.site = tmpDetector;

    /* move on to next one */
    simRingdown = simRingdown->next;
  }

  /* destroy the signal */
  LALSDestroyVector( stat->statusPtr, &(signalvec.data) );
  CHECKSTATUSPTR( stat );

  LALCDestroyVector( stat->statusPtr, &( transfer->data ) );
  CHECKSTATUSPTR( stat );

  if ( detector.site ) LALFree( detector.site );
  LALFree( transfer );

  DETATCHSTATUSPTR( stat );
  RETURN( stat );
}
void
LALExtractFrameResponse(LALStatus * status,
    COMPLEX8FrequencySeries * output,
    LALCache * calCache, CalibrationUpdateParams * calfacts)
{
    const LALUnit strainPerCount =
        { 0, {0, 0, 0, 0, 0, 1, -1}, {0, 0, 0, 0, 0, 0, 0} };

    LALCache *refCache = NULL;
    LALCache *facCache = NULL;
    LALFrStream *refStream = NULL;
    LALFrStream *facStream = NULL;
    FrChanIn frameChan;
    LALFrStreamPos facPos;

    CHAR facDsc[LALNameLength];
    CHAR channelName[LALNameLength];

    COMPLEX8FrequencySeries R0;
    COMPLEX8FrequencySeries C0;
    COMPLEX8TimeSeries ab;
    COMPLEX8TimeSeries a;
    /*
     * COMPLEX8Vector                abVec;
     * COMPLEX8Vector                aVec;
     * COMPLEX8                      abData;
     * COMPLEX8                      aData;
     */
    CalibrationFunctions calfuncs;

    LIGOTimeGPS seekEpoch;
    UINT4 length;
    REAL8 duration_real;
    const REAL8 fuzz = 0.1 / 16384.0;

    INITSTATUS(status);
    ATTATCHSTATUSPTR(status);

    ASSERT(output, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(output->data, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(output->data->data, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(calCache, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(calfacts, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(calfacts->ifo, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(crealf(calfacts->alpha) == 0, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(cimagf(calfacts->alpha) == 0, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(crealf(calfacts->alphabeta) == 0, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);
    ASSERT(cimagf(calfacts->alphabeta) == 0, status,
        FRAMECALIBRATIONH_ENULL, FRAMECALIBRATIONH_MSGENULL);

    /*
     *
     * set up and clear the structures to hold the input data
     *
     */

    memset(&R0, 0, sizeof(COMPLEX8FrequencySeries));
    memset(&C0, 0, sizeof(COMPLEX8FrequencySeries));
    memset(&ab, 0, sizeof(COMPLEX8TimeSeries));
    memset(&a, 0, sizeof(COMPLEX8TimeSeries));
    memset(&calfuncs, 0, sizeof(CalibrationFunctions));

    calfuncs.responseFunction = &R0;
    calfuncs.sensingFunction = &C0;
    calfacts->openLoopFactor = &ab;
    calfacts->sensingFactor = &a;
    calfacts->epoch = output->epoch;
    frameChan.name = channelName;

    /*
     *
     * get the reference calibration and cavity gain frequency series
     *
     */

    /* sieve the calibration cache for the reference frame */
    refCache = XLALCacheDuplicate(calCache);
    XLALCacheSieve(refCache, 0, 0, NULL, REF_TYPE, NULL);
    if (!refCache->length) {
        /* if we don't have a reference calibration, we can't do anything */
        XLALDestroyCache(refCache);
        ABORT(status, FRAMECALIBRATIONH_ECREF, FRAMECALIBRATIONH_MSGECREF);
    }

    /* open the reference calibration frame */
    LALFrCacheOpen(status->statusPtr, &refStream, refCache);
    if (status->statusPtr->statusCode) {
        /* if we don't have a reference calibration, we can't do anything */
        XLALDestroyCache(refCache);
        ABORT(status, FRAMECALIBRATIONH_EOREF, FRAMECALIBRATIONH_MSGEOREF);
    }
    XLALDestroyCache(refCache);
    if (status->statusPtr->statusCode) {
        TRY(LALFrClose(status->statusPtr, &refStream), status);
        ABORT(status, FRAMECALIBRATIONH_EDCHE, FRAMECALIBRATIONH_MSGEDCHE);
    }

    /* read in the frequency series for the reference calbration */
    snprintf(channelName, LALNameLength * sizeof(CHAR),
        "%s:" RESPONSE_CHAN, calfacts->ifo);
    LALFrGetCOMPLEX8FrequencySeries(status->statusPtr,
        &R0, &frameChan, refStream);
    if (status->statusCode) {
        /* if we don't have a reference calibration, we can't do anything */
        XLALDestroyCache(refCache);
        ABORT(status, FRAMECALIBRATIONH_EREFR, FRAMECALIBRATIONH_MSGEREFR);
    }

    /* read in the reference cavity gain frequency series */
    snprintf(channelName, LALNameLength * sizeof(CHAR),
        "%s:" CAV_GAIN_CHAN, calfacts->ifo);
    LALFrGetCOMPLEX8FrequencySeries(status->statusPtr,
        &C0, &frameChan, refStream);
    BEGINFAIL(status) {
        /* no cavity gain response to update point cal */
        XLALDestroyCache(refCache);
        TRY(LALFrClose(status->statusPtr, &refStream), status);
        RETURN_POINT_CAL;
    }
    ENDFAIL(status);

    LALFrClose(status->statusPtr, &refStream);
    BEGINFAIL(status) {
        RETURN_POINT_CAL;
    }
    ENDFAIL(status);

    /*
     *
     * get the factors necessary to update the reference calibration
     *
     */

    /* try and get some update factors. first we try to get a cache  */
    /* containing sensemon frames. if that fails, try the S1 type    */
    /* calibration data, otherwise just return the point calibration */
    do {
        /* try and get sensemon frames */
        snprintf(facDsc, LALNameLength * sizeof(CHAR), SENSEMON_FAC_TYPE);
        facCache = XLALCacheDuplicate(calCache);
        XLALCacheSieve(facCache, 0, 0, NULL, facDsc, NULL);
        if (!facCache) {
            RETURN_POINT_CAL;
        }

        if (facCache->length) {
            /* sensemon stores fac times series as real_8 adc trend data */
            REAL8TimeSeries sensemonTS;
            REAL8 alphaDeltaT;
            UINT4 i;

            memset(&sensemonTS, 0, sizeof(REAL8TimeSeries));

            OPEN_FAC;

            snprintf(channelName, LALNameLength * sizeof(CHAR),
                "%s:" CAV_FAC_CHAN ".mean", calfacts->ifo);

            /* get the sample rate of the alpha channel */
            LALFrGetREAL8TimeSeries(status->statusPtr,
                &sensemonTS, &frameChan, facStream);
            BEGINFAIL(status) {
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* determine number of calibration points required */
            duration_real = XLALGPSGetREAL8(&(calfacts->duration));
            length = (UINT4) ceil(duration_real / sensemonTS.deltaT);
            ++length;

            /* make sure we get the first point before the requested cal time */
            alphaDeltaT = sensemonTS.deltaT;
            seekEpoch = output->epoch;
            XLALGPSAdd(&seekEpoch, fuzz - sensemonTS.deltaT);
            sensemonTS.epoch = seekEpoch;

            GET_POS;

            /* create memory for the alpha values */
            LALDCreateVector(status->statusPtr, &(sensemonTS.data), length);
            BEGINFAIL(status) {
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* get the alpha values */
            LALFrGetREAL8TimeSeries(status->statusPtr,
                &sensemonTS, &frameChan, facStream);
            BEGINFAIL(status) {
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            LALCCreateVector(status->statusPtr, &(a.data), length);
            BEGINFAIL(status) {
                TRY(LALDDestroyVector(status->statusPtr, &(sensemonTS.data)),
                    status);
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            for (i = 0; i < length; ++i) {
                a.data->data[i] = crectf( (REAL4) sensemonTS.data->data[i], 0 );
            }
            a.epoch = sensemonTS.epoch;
            a.deltaT = sensemonTS.deltaT;
            strncpy(a.name, sensemonTS.name, LALNameLength);

            LALFrSetPos(status->statusPtr, &facPos, facStream);
            BEGINFAIL(status) {
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* get the alpha*beta values */
            snprintf(channelName, LALNameLength * sizeof(CHAR),
                "%s:" OLOOP_FAC_CHAN ".mean", calfacts->ifo);
            LALFrGetREAL8TimeSeries(status->statusPtr,
                &sensemonTS, &frameChan, facStream);
            BEGINFAIL(status) {
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* check that alpha and alpha*beta have the same sample rate */
            if (fabs(alphaDeltaT - sensemonTS.deltaT) > LAL_REAL8_EPS) {
                TRY(LALCDestroyVector(status->statusPtr, &(a.data)), status);
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
                ABORT(status, FRAMECALIBRATIONH_EDTMM,
                    FRAMECALIBRATIONH_MSGEDTMM);
            }

            LALCCreateVector(status->statusPtr, &(ab.data), length);
            BEGINFAIL(status) {
                TRY(LALCDestroyVector(status->statusPtr, &(a.data)), status);
                TRY(LALDDestroyVector(status->statusPtr, &(sensemonTS.data)),
                    status);
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            for (i = 0; i < length; ++i) {
                ab.data->data[i] = crectf( (REAL4) sensemonTS.data->data[i], 0 );
            }
            ab.epoch = sensemonTS.epoch;
            ab.deltaT = sensemonTS.deltaT;
            strncpy(ab.name, sensemonTS.name, LALNameLength);

            /* destroy the sensemonTS.data */
            LALDDestroyVector(status->statusPtr, &(sensemonTS.data));
            CHECKSTATUSPTR(status);
            break;
        }

        /* destroy the empty frame cache and try again */
        XLALDestroyCache(facCache);

        /* try and get the the factors from lalapps_mkcalfac frames */
        facCache = XLALCacheDuplicate(calCache);
        XLALCacheSieve(facCache, 0, 0, NULL, FAC_TYPE, NULL);
        if (!facCache) {
            RETURN_POINT_CAL;
        }

        if (facCache->length) {
            /* the lalapps frames are complex_8 proc data */
            OPEN_FAC;

            snprintf(channelName, LALNameLength * sizeof(CHAR),
                "%s:" CAV_FAC_CHAN, calfacts->ifo);

            /* get the sample rate of the alpha channel */
            LALFrGetCOMPLEX8TimeSeries(status->statusPtr,
                &a, &frameChan, facStream);
            BEGINFAIL(status) {
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* determine number of calibration points required */
            duration_real = XLALGPSGetREAL8(&(calfacts->duration));
            length = (UINT4) ceil(duration_real / a.deltaT);
            ++length;

            /* make sure we get the first point before the requested cal time */
            seekEpoch = output->epoch;
            XLALGPSAdd(&seekEpoch, fuzz - a.deltaT);
            a.epoch = ab.epoch = seekEpoch;

            GET_POS;

            /* create storage for the alpha values */
            LALCCreateVector(status->statusPtr, &(a.data), length);
            BEGINFAIL(status) {
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* get the alpha values */
            LALFrGetCOMPLEX8TimeSeries(status->statusPtr,
                &a, &frameChan, facStream);
            BEGINFAIL(status) {
                TRY(LALCDestroyVector(status->statusPtr, &(a.data)), status);
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            LALFrSetPos(status->statusPtr, &facPos, facStream);
            BEGINFAIL(status) {
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* create storage for the alpha*beta values */
            LALCCreateVector(status->statusPtr, &(ab.data), length);
            BEGINFAIL(status) {
                TRY(LALCDestroyVector(status->statusPtr, &(a.data)), status);
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* get the alpha*beta values */
            snprintf(channelName, LALNameLength * sizeof(CHAR),
                "%s:" OLOOP_FAC_CHAN, calfacts->ifo);
            LALFrGetCOMPLEX8TimeSeries(status->statusPtr,
                &ab, &frameChan, facStream);
            BEGINFAIL(status) {
                TRY(LALCDestroyVector(status->statusPtr, &(a.data)), status);
                TRY(LALCDestroyVector(status->statusPtr, &(ab.data)), status);
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
            }
            ENDFAIL(status);

            /* check that alpha and alpha*beta have the same sample rate */
            if (fabs(a.deltaT - ab.deltaT) > LAL_REAL8_EPS) {
                TRY(LALCDestroyVector(status->statusPtr, &(a.data)), status);
                TRY(LALCDestroyVector(status->statusPtr, &(ab.data)), status);
                TRY(LALFrClose(status->statusPtr, &facStream), status);
                RETURN_POINT_CAL;
                ABORT(status, FRAMECALIBRATIONH_EDTMM,
                    FRAMECALIBRATIONH_MSGEDTMM);
            }

            break;
        }
/* Actually, we don't need it -- JTW
struct tagRealFFTPlan
{
  INT4  sign;
  UINT4 size;
  void* junk;
};
*/
int
main( int argc, char *argv[] )
{

   static LALStatus         status;

   UINT4      i;
   REAL8      f;


   const REAL4    testInputDataData[SZEROPADANDFFTTESTC_LENGTH]
                     = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};

   COMPLEX8 expectedOutputDataData[SZEROPADANDFFTTESTC_LENGTH]
                     = {crectf(+3.600000000000000e+01, 0.0),
                        crectf(-1.094039137097177e+01, -2.279368601990178e+01),
                        crectf(+3.693524635113721e-01, +9.326003289238411e+00),
                        crectf(-8.090169943749448e-01, -7.918722831227928e+00),
                        crectf(+3.502214272222959e-01, +5.268737078678177e+00),
                        crectf(+5.329070518200751e-15, -5.196152422706625e+00),
                        crectf(+3.090169943749475e-01, +4.306254604896173e+00),
                        crectf(+2.208174802380956e-01, -4.325962305777781e+00)};

   REAL4TimeSeries             goodInput;
   COMPLEX8FrequencySeries     goodOutput;

   int                    result;
   LALUnit                expectedUnit;
   CHAR                   unitString[LALUnitTextSize];

   SZeroPadAndFFTParameters   goodParams;


   goodParams.window = NULL;
   goodParams.fftPlan = NULL;
   goodParams.length = SZEROPADANDFFTTESTC_FULLLENGTH;

   /* build window */
   goodParams.window = XLALCreateRectangularREAL4Window(SZEROPADANDFFTTESTC_LENGTH);
#ifndef LAL_NDEBUG
   SZeroPadAndFFTParameters badParams = goodParams;
#endif

   /* Fill in expected output */

   for (i=0; i<SZEROPADANDFFTTESTC_LENGTH; ++i)
   {
     expectedOutputDataData[i] *= SZEROPADANDFFTTESTC_DELTAT;
   }

   ParseOptions( argc, argv );

   /* TEST INVALID DATA HERE ------------------------------------------- */

   /* define valid parameters */
   goodInput.f0                   = 0.0;
   goodInput.deltaT               = SZEROPADANDFFTTESTC_DELTAT;
   goodInput.epoch.gpsSeconds     = SZEROPADANDFFTTESTC_EPOCHSEC;
   goodInput.epoch.gpsNanoSeconds = SZEROPADANDFFTTESTC_EPOCHNS;
   goodInput.data                 = NULL;
   goodOutput.data                = NULL;

#ifndef LAL_NDEBUG
   REAL4TimeSeries badInput = goodInput;
   COMPLEX8FrequencySeries badOutput = goodOutput;
#endif

   /* construct plan */
   LALCreateForwardRealFFTPlan(&status, &(goodParams.fftPlan),
			       SZEROPADANDFFTTESTC_FULLLENGTH,
			       SZEROPADANDFFTTESTC_FALSE);
   if ( ( code = CheckStatus( &status, 0 , "",
			      SZEROPADANDFFTTESTC_EFLS,
			      SZEROPADANDFFTTESTC_MSGEFLS ) ) )
   {
     return code;
   }
   /* allocate input and output vectors */
   LALSCreateVector(&status, &(goodInput.data), SZEROPADANDFFTTESTC_LENGTH);
   if ( ( code = CheckStatus( &status, 0 , "",
			      SZEROPADANDFFTTESTC_EFLS,
			      SZEROPADANDFFTTESTC_MSGEFLS ) ) )
   {
     return code;
   }
   LALCCreateVector(&status, &(goodOutput.data), SZEROPADANDFFTTESTC_LENGTH);
   if ( ( code = CheckStatus( &status, 0 , "",
			      SZEROPADANDFFTTESTC_EFLS,
			      SZEROPADANDFFTTESTC_MSGEFLS ) ) )
   {
     return code;
   }

#ifndef LAL_NDEBUG
   if ( ! lalNoDebug )
   {
     /* test behavior for null pointer to output series */
     LALSZeroPadAndFFT(&status, NULL, &goodInput, &goodParams);
     if ( ( code = CheckStatus( &status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
				STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
				SZEROPADANDFFTTESTC_ECHK,
				SZEROPADANDFFTTESTC_MSGECHK ) ) )
     {
       return code;
     }
     printf("  PASS: null pointer to output series results in error:\n       \"%s\"\n", STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

     /* test behavior for null pointer to input series */
     LALSZeroPadAndFFT(&status, &goodOutput, NULL, &goodParams);
     if ( ( code = CheckStatus( &status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
				STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
				SZEROPADANDFFTTESTC_ECHK,
				SZEROPADANDFFTTESTC_MSGECHK ) ) )
     {
       return code;
     }
     printf("  PASS: null pointer to input series results in error:\n       \"%s\"\n", STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

     /* test behavior for null pointer to parameter structure */
     LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, NULL);
     if ( ( code = CheckStatus( &status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
				STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
				SZEROPADANDFFTTESTC_ECHK,
				SZEROPADANDFFTTESTC_MSGECHK ) ) )
     {
       return code;
     }
     printf("  PASS: null pointer to parameter structure results in error:\n       \"%s\"\n", STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

     /* test behavior for null pointer to FFT plan */
     badParams.fftPlan = NULL;
     LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &badParams);
     if ( ( code = CheckStatus( &status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
				STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
				SZEROPADANDFFTTESTC_ECHK,
				SZEROPADANDFFTTESTC_MSGECHK ) ) )
     {
       return code;
     }
     printf("  PASS: null pointer to FFT plan results in error:\n       \"%s\"\n", STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);
     badParams.fftPlan = goodParams.fftPlan;

     /* test behavior for null pointer to data member of output series */
     LALSZeroPadAndFFT(&status, &badOutput, &goodInput, &goodParams);
     if ( ( code = CheckStatus( &status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
				STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
				SZEROPADANDFFTTESTC_ECHK,
				SZEROPADANDFFTTESTC_MSGECHK ) ) )
     {
       return code;
     }
     printf("  PASS: null pointer to data member of output series results in error:\n       \"%s\"\n", STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

     /* test behavior for null pointer to data member of input series */
     LALSZeroPadAndFFT(&status, &goodOutput, &badInput, &goodParams);
     if ( ( code = CheckStatus( &status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
				STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
				SZEROPADANDFFTTESTC_ECHK,
				SZEROPADANDFFTTESTC_MSGECHK ) ) )
     {
       return code;
     }
     printf("  PASS: null pointer to data member of input series results in error:\n       \"%s\"\n", STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

     /* test behavior for null pointer to data member of data member of output series */
     LALCCreateVector(&status, &(badOutput.data), SZEROPADANDFFTTESTC_LENGTH);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }
     COMPLEX8                *cPtr;
     cPtr = badOutput.data->data;
     badOutput.data->data = NULL;
     LALSZeroPadAndFFT(&status, &badOutput, &goodInput, &goodParams);
     if ( ( code = CheckStatus( &status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
				STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
				SZEROPADANDFFTTESTC_ECHK,
				SZEROPADANDFFTTESTC_MSGECHK ) ) )
     {
       return code;
     }
     printf("  PASS: null pointer to data member of data member of output series results in error:\n       \"%s\"\n", STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);
     badOutput.data->data = cPtr;
     LALCDestroyVector(&status, &(badOutput.data));
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }

     /* test behavior for null pointer to data member of data member of output series */
     LALSCreateVector(&status, &(badInput.data), SZEROPADANDFFTTESTC_LENGTH);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }
     REAL4                   *sPtr;
     sPtr = badInput.data->data;
     badInput.data->data = NULL;
     LALSZeroPadAndFFT(&status, &goodOutput, &badInput, &goodParams);
     if ( ( code = CheckStatus( &status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
				STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
				SZEROPADANDFFTTESTC_ECHK,
				SZEROPADANDFFTTESTC_MSGECHK ) ) )
     {
       return code;
     }
     printf("  PASS: null pointer to data member of data member of input series results in error:\n       \"%s\"\n", STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);
     badInput.data->data = sPtr;
     LALSDestroyVector(&status, &(badInput.data));
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }

     /* test behavior for zero length */
     goodInput.data->length = goodOutput.data->length = 0;
     /* plan->size = -1; */
     LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &goodParams);
     if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EZEROLEN,
			       STOCHASTICCROSSCORRELATIONH_MSGEZEROLEN,
			       SZEROPADANDFFTTESTC_ECHK,
			       SZEROPADANDFFTTESTC_MSGECHK) ) )
     {
       return code;
     }
     printf("  PASS: zero length results in error:\n       \"%s\"\n",
            STOCHASTICCROSSCORRELATIONH_MSGEZEROLEN);
     /* reassign valid length */
     goodInput.data->length = goodOutput.data->length
       = SZEROPADANDFFTTESTC_LENGTH;
     /* plan->size = SZEROPADANDFFTTESTC_FULLLENGTH; */

     /* test behavior for negative time spacing */
     goodInput.deltaT = -SZEROPADANDFFTTESTC_DELTAT;
     LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &goodParams);
     if ( ( code = CheckStatus(&status,
			       STOCHASTICCROSSCORRELATIONH_ENONPOSDELTAT,
			       STOCHASTICCROSSCORRELATIONH_MSGENONPOSDELTAT,
			       SZEROPADANDFFTTESTC_ECHK,
			       SZEROPADANDFFTTESTC_MSGECHK) ) )
     {
       return code;
     }
     printf("  PASS: negative time spacing results in error:\n       \"%s\"\n",
            STOCHASTICCROSSCORRELATIONH_MSGENONPOSDELTAT);

     /* test behavior for zero time spacing */
     goodInput.deltaT = 0;
     LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &goodParams);
     if ( ( code = CheckStatus(&status,
			       STOCHASTICCROSSCORRELATIONH_ENONPOSDELTAT,
			       STOCHASTICCROSSCORRELATIONH_MSGENONPOSDELTAT,
			       SZEROPADANDFFTTESTC_ECHK,
			       SZEROPADANDFFTTESTC_MSGECHK) ) )
     {
       return code;
     }
     printf("  PASS: zero time spacing results in error:\n       \"%s\"\n",
            STOCHASTICCROSSCORRELATIONH_MSGENONPOSDELTAT);
     /* reassign valid time spacing */
     goodInput.deltaT = SZEROPADANDFFTTESTC_DELTAT;

   } /* if ( ! lalNoDebug ) */
#endif /* NDEBUG */

   /* test behavior for negative heterodyning frequency */
   goodInput.f0 = -100.0;
   LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &goodParams);
   if ( ( code = CheckStatus(&status,
			     STOCHASTICCROSSCORRELATIONH_ENONZEROHETERO,
			     STOCHASTICCROSSCORRELATIONH_MSGENONZEROHETERO,
			     SZEROPADANDFFTTESTC_ECHK,
			     SZEROPADANDFFTTESTC_MSGECHK) ) )
   {
     return code;
   }
   printf("  PASS: negative heterodyning frequency results in error:\n       \"%s\"\n",
            STOCHASTICCROSSCORRELATIONH_MSGENONZEROHETERO);
   /* test behavior for positive heterodyning frequency */
   goodInput.f0 = 100.0;
   LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &goodParams);
   if ( ( code = CheckStatus(&status,
			     STOCHASTICCROSSCORRELATIONH_ENONZEROHETERO,
			     STOCHASTICCROSSCORRELATIONH_MSGENONZEROHETERO,
			     SZEROPADANDFFTTESTC_ECHK,
			     SZEROPADANDFFTTESTC_MSGECHK) ) )
   {
     return code;
   }
   printf("  PASS: positive heterodyning frequency results in error:\n       \"%s\"\n",
          STOCHASTICCROSSCORRELATIONH_MSGENONZEROHETERO);
   goodInput.f0 = 0.0;

   /* test behavior for length mismatch between input series and output series */
   goodOutput.data->length = SZEROPADANDFFTTESTC_LENGTH + 1;
   LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &goodParams);
   if ( ( code = CheckStatus(&status,
			     STOCHASTICCROSSCORRELATIONH_EMMLEN,
			     STOCHASTICCROSSCORRELATIONH_MSGEMMLEN,
			     SZEROPADANDFFTTESTC_ECHK,
			     SZEROPADANDFFTTESTC_MSGECHK) ) )
   {
     return code;
   }
   printf("  PASS: length mismatch between input series and output series results in error:\n       \"%s\"\n",
          STOCHASTICCROSSCORRELATIONH_MSGEMMLEN);
   goodOutput.data->length = SZEROPADANDFFTTESTC_LENGTH;

   /* TEST VALID DATA HERE --------------------------------------------- */

   /* fill input time-series parameters */
   strncpy(goodInput.name,"Dummy test data",LALNameLength);
   goodInput.sampleUnits  = lalDimensionlessUnit;
   goodInput.sampleUnits.unitNumerator[LALUnitIndexADCCount] = 1;

     /* fill input time-series data */
   for (i=0; i<SZEROPADANDFFTTESTC_LENGTH; ++i)
   {
     goodInput.data->data[i] = testInputDataData[i];
   }

   /* zero-pad and FFT */
   LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &goodParams);
   if ( ( code = CheckStatus( &status, 0 , "",
			      SZEROPADANDFFTTESTC_EFLS,
			      SZEROPADANDFFTTESTC_MSGEFLS) ) )
   {
     return code;
   }

   /* check output f0 */
   if (optVerbose)
   {
     printf("f0=%g, should be 0\n", goodOutput.f0);
   }
   if (goodOutput.f0)
   {
     printf("  FAIL: Valid data test\n");
     if (optVerbose)
     {
       printf("Exiting with error: %s\n", SZEROPADANDFFTTESTC_MSGEFLS);
     }
     return SZEROPADANDFFTTESTC_EFLS;
   }

   /* check output deltaF */
   if (optVerbose)
   {
     printf("deltaF=%g, should be %g\n", goodOutput.deltaF,
            SZEROPADANDFFTTESTC_DELTAF);
   }
   if ( fabs(goodOutput.deltaF-SZEROPADANDFFTTESTC_DELTAF)
        / SZEROPADANDFFTTESTC_DELTAF > SZEROPADANDFFTTESTC_TOL )
   {
     printf("  FAIL: Valid data test\n");
     if (optVerbose)
     {
       printf("Exiting with error: %s\n", SZEROPADANDFFTTESTC_MSGEFLS);
     }
     return SZEROPADANDFFTTESTC_EFLS;
   }

   /* check output epoch */
   if (optVerbose)
   {
     printf("epoch=%d seconds, %d nanoseconds; should be %d seconds, %d nanoseconds\n",
            goodOutput.epoch.gpsSeconds, goodOutput.epoch.gpsNanoSeconds,
            SZEROPADANDFFTTESTC_EPOCHSEC, SZEROPADANDFFTTESTC_EPOCHNS);
   }
   if ( goodOutput.epoch.gpsSeconds != SZEROPADANDFFTTESTC_EPOCHSEC
        || goodOutput.epoch.gpsNanoSeconds != SZEROPADANDFFTTESTC_EPOCHNS )
   {
     printf("  FAIL: Valid data test\n");
     if (optVerbose)
     {
       printf("Exiting with error: %s\n", SZEROPADANDFFTTESTC_MSGEFLS);
     }
     return SZEROPADANDFFTTESTC_EFLS;
   }

   /* check output units */
   expectedUnit = lalDimensionlessUnit;
   expectedUnit.unitNumerator[LALUnitIndexADCCount] = 1;
   expectedUnit.unitNumerator[LALUnitIndexSecond] = 1;
   result = XLALUnitCompare(&expectedUnit, &(goodOutput.sampleUnits));
   if (optVerbose)
   {
     if ( XLALUnitAsString( unitString, LALUnitTextSize, &(goodOutput.sampleUnits)) == NULL ) {
       return SZEROPADANDFFTTESTC_EFLS;
     }
     printf( "Units are \"%s\", ", unitString );
     if ( XLALUnitAsString( unitString, LALUnitTextSize, &expectedUnit) == NULL ) {
       return SZEROPADANDFFTTESTC_EFLS;
     }
     printf( "should be \"%s\"\n", unitString );
   }

   if (result != 0)
   {
     printf("  FAIL: Valid data test #1\n");
     if (optVerbose)
     {
       printf("Exiting with error: %s\n",
              SZEROPADANDFFTTESTC_MSGEFLS);
     }
     return SZEROPADANDFFTTESTC_EFLS;
   }

   /* check output values */
   if (optVerbose)
   {
     printf("hBarTilde(0)=%g + %g i, should be %g\n",
            crealf(goodOutput.data->data[0]), cimagf(goodOutput.data->data[0]),
            crealf(expectedOutputDataData[0]));
   }
   if ( fabsf(crealf(goodOutput.data->data[0]) - crealf(expectedOutputDataData[0]))
        /* / expectedOutputDataData[0].re */> SZEROPADANDFFTTESTC_TOL
        || fabsf(cimagf(goodOutput.data->data[0])) > SZEROPADANDFFTTESTC_TOL )
   {
     printf("  FAIL: Valid data test\n");
     if (optVerbose)
       {
         printf("Exiting with error: %s\n", SZEROPADANDFFTTESTC_MSGEFLS);
       }
     return SZEROPADANDFFTTESTC_EFLS;
   }

   for (i=1; i<SZEROPADANDFFTTESTC_LENGTH; ++i)
   {
     f = i * SZEROPADANDFFTTESTC_DELTAF;
     if (optVerbose)
     {
       printf("hBarTilde(%f Hz)=%g + %g i, should be %g + %g i\n",
              f, crealf(goodOutput.data->data[i]), cimagf(goodOutput.data->data[i]),
              crealf(expectedOutputDataData[i]), cimagf(expectedOutputDataData[i]));
     }
     if (fabsf(crealf(goodOutput.data->data[i]) - crealf(expectedOutputDataData[i]))
         /* / expectedOutputDataData[0].re */> SZEROPADANDFFTTESTC_TOL
         || fabsf(cimagf(goodOutput.data->data[i]) - cimagf(expectedOutputDataData[i]))
         /* / expectedOutputDataData[0].re */> SZEROPADANDFFTTESTC_TOL)
     {
       printf("  FAIL: Valid data test\n");
       if (optVerbose)
       {
         printf("Exiting with error: %s\n", SZEROPADANDFFTTESTC_MSGEFLS);
       }
       return SZEROPADANDFFTTESTC_EFLS;
     }
   }

    /* write results to output file
   LALSPrintTimeSeries(&input, "zeropadgoodInput.dat");
   LALCPrintFrequencySeries(&output, "zeropadgoodOutput.dat");*/

   /* clean up valid data */
   LALSDestroyVector(&status, &goodInput.data);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
   {
     return code;
   }
   LALCDestroyVector(&status, &goodOutput.data);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
   {
     return code;
   }
   LALDestroyRealFFTPlan(&status, &(goodParams.fftPlan));
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
   {
     return code;
   }
   XLALDestroyREAL4Window(goodParams.window);

   LALCheckMemoryLeaks();

   printf("PASS: all tests\n");

   /**************** Process User-Entered Data, If Any **************/

   /* ::TODO:: Fix this with length and window type to be specified */

   if (optInputFile[0] && optOutputFile[0]){
     /* construct plan*/
     LALCreateForwardRealFFTPlan(&status, &(goodParams.fftPlan), 2*optLength - 1,
				   optMeasurePlan);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }

     goodInput.data  = NULL;
     goodOutput.data = NULL;

     LALSCreateVector(&status, &goodInput.data, optLength);
     if ( ( code = CheckStatus( &status, 0 , "",
				SZEROPADANDFFTTESTC_EUSE,
				SZEROPADANDFFTTESTC_MSGEUSE) ) )
     {
       return code;
     }
     LALCCreateVector(&status, &goodOutput.data, optLength);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }

     /* Read input file */
     LALSReadTimeSeries(&status, &goodInput, optInputFile);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }

     /* calculate zero-pad and FFT */
     LALSZeroPadAndFFT(&status, &goodOutput, &goodInput, &goodParams);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }

     LALCPrintFrequencySeries(&goodOutput, optOutputFile);

     printf("===== FFT of Zero-Padded User-Specified Data Written to File %s =====\n", optOutputFile);

     /* clean up valid data */
     LALSDestroyVector(&status, &goodInput.data);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }
     LALCDestroyVector(&status, &goodOutput.data);
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }
     LALDestroyRealFFTPlan(&status, &(goodParams.fftPlan));
     if ( ( code = CheckStatus(&status, 0 , "",
			       SZEROPADANDFFTTESTC_EFLS,
			       SZEROPADANDFFTTESTC_MSGEFLS) ) )
     {
       return code;
     }
     LALCheckMemoryLeaks();
   }
   return SZEROPADANDFFTTESTC_ENOM;
}
Exemple #11
0
void LALTfrWv (LALStatus *stat, REAL4Vector* sig, TimeFreqRep *tfr, TimeFreqParam *param)
{

  INT4    nf;
  INT4    time;
  INT4    column, row;
  INT4    taumax, tau;
  REAL4Vector  *lacf = NULL;      /* local autocorrelation function */
  COMPLEX8Vector  *vtmp = NULL;
  RealFFTPlan  *plan = NULL;

  INITSTATUS(stat);
  ATTATCHSTATUSPTR (stat);

  /* Make sure the arguments are not NULL: */
  ASSERT (sig, stat, TFR_ENULL, TFR_MSGENULL);
  ASSERT (tfr, stat, TFR_ENULL, TFR_MSGENULL);
  ASSERT (param, stat, TFR_ENULL, TFR_MSGENULL);

  /* Make sure the data pointers are not NULL: */
  ASSERT (sig->data, stat, TFR_ENULL, TFR_MSGENULL);
  ASSERT (tfr->timeInstant, stat, TFR_ENULL, TFR_MSGENULL);
  ASSERT (tfr->freqBin, stat, TFR_ENULL, TFR_MSGENULL);
  ASSERT (tfr->map, stat, TFR_ENULL, TFR_MSGENULL);

  /* Make sure the requested TFR type corresponds to what will be done */
  ASSERT (tfr->type == WignerVille , stat, TFR_ENAME, TFR_MSGENAME);
  ASSERT (param->type == WignerVille , stat, TFR_ENAME, TFR_MSGENAME);

  /* Make sure the number of freq bins is a positive number: */
  nf = tfr->fRow;
  ASSERT (nf > 0 , stat, TFR_EFROW, TFR_MSGEFROW);

  /* Make sure the number of freq bins is a power of 2: */
  while(!(nf & 1))
      nf = nf>>1;

  ASSERT (nf == 1, stat, TFR_EFROW, TFR_MSGEFROW);

  /* Make sure the timeInstant indicates existing time instants */
  for (column=0 ; column<tfr->tCol ; column++)
    {
      if ((tfr->timeInstant[column] < 0) || (tfr->timeInstant[column] > (INT4)(sig->length-1)))
	{
	  ASSERT (tfr->timeInstant[column] > 0, stat, TFR_EBADT, TFR_MSGEBADT);
	  ASSERT (tfr->timeInstant[column] < (INT4)sig->length, stat, TFR_EBADT, TFR_MSGEBADT);
	}
    }
    TRY(LALCreateForwardRealFFTPlan(stat->statusPtr, &plan,(UINT4)tfr->fRow,0),stat);

  TRY(LALSCreateVector(stat->statusPtr, &lacf, tfr->fRow), stat);
  TRY(LALCCreateVector(stat->statusPtr, &vtmp, tfr->fRow/2+1), stat);

  for (column = 0; column < tfr->tCol; column++)
    {

      for (row = 0; row < tfr->fRow; row++)
	lacf->data[row] = 0.0;

      time = tfr->timeInstant[column];
      taumax = MIN (time, (INT4)(sig->length -1 - time));
      taumax = MIN (taumax, (tfr->fRow / 2 - 1));

      for (tau = -taumax; tau <= taumax; tau++)
	{
	  row = (tfr->fRow+tau)%tfr->fRow;
	  lacf->data[row] =   sig->data[time + tau]*sig->data[time - tau];
        }

      tau=tfr->fRow/2;
      if ((time<=(INT4)sig->length-tau-1)&(time>=tau))
	lacf->data[tau] =  sig->data[time+tau]*sig->data[time-tau];

      LALForwardRealFFT(stat->statusPtr, vtmp, lacf, plan);

      for (row = 0; row < (tfr->fRow/2+1); row++)
	tfr->map[column][row] = crealf(vtmp->data[row]);

    }
  /* Reflecting frequency halfing in WV distrob so multiply by 1/2 */
  for (row = 0; row < (tfr->fRow/2+1) ; row++)
    tfr->freqBin[row] = (REAL4) row / (2 *tfr->fRow);

  TRY(LALSDestroyVector(stat->statusPtr, &lacf), stat);
  TRY(LALCDestroyVector(stat->statusPtr, &vtmp), stat);

  TRY(LALDestroyRealFFTPlan(stat->statusPtr, &plan), stat);

  DETATCHSTATUSPTR (stat);

  (void)param;

  /* normal exit */
  RETURN (stat);
}
Exemple #12
0
int main(int argc, char *argv[])
{
long i;
double window_sum;
LALStatus status={level:0, statusPtr: NULL};
PassBandParamStruc filterpar;
REAL4TimeSeries chan; /* must zero the f0 field */

fprintf(stderr,"make_sft_op version %s\n", MAKE_SFT_VERSION);
fprintf(stderr,"Using frame library %s\n", FrLibVersionF());
fprintf(stderr,"Using LAL version %s\n", LAL_VERSION);


yylex();

if(freq_start<0)freq_start=0;
if(freq_stop<0)freq_stop=total_samples;

/* post_init various subsystems */

post_init_response_files();
post_init_alpha_beta();

/* print settings */
print_settings(stderr);

/* start processing data */
print_data_stats();
print_data(file_debug1, "debug 1");

verify_loaded_data();

generate_fake_data();

linear_interpolate_gaps();
print_data(file_debug2, "debug 2");

/* this is a hack, but it significantly reduces memory footprint */
td_data=do_alloc(1,sizeof(*td_data));
td_data->length=total_samples;
td_data->data=data;

/* setup structure to hold input for Butterworth filter */
chan.data=NULL;
strncpy(chan.name,channel,LALNameLength);
chan.f0=0;
chan.name[LALNameLength-1]=0; /* make sure it is null-terminated */
chan.deltaT=1.0/samples_per_second;
chan.epoch.gpsSeconds=gps_start; /* no need */
chan.epoch.gpsNanoSeconds=0;

if(trace_power){
	fprintf(stderr, "Input data total power=%.*g\n",
		precision, sum_r4_squares(data, total_samples)/samples_per_second);
	}

if(!bypass_highpass_filter && (highpass_filter_f>0) && (highpass_filter_a>0)){
	fprintf(stderr,"Applying high pass filter, f=%g a=%g order=%d\n",
		highpass_filter_f, highpass_filter_a, highpass_filter_order);
	/* Setup Butterworth filter */
	filterpar.name="Butterworth High Pass";
	filterpar.nMax=highpass_filter_order;
	filterpar.f2=highpass_filter_f;
	filterpar.a2=highpass_filter_a;
	/* values that are 'not given' = out of range */
	filterpar.f1=-1.0;
	filterpar.a1=-1.0;
	
	/* REAL4Sequence is the same as REAL4Vector - according to lal/Datatypes.h */
	chan.data=(REAL4Sequence *)td_data;
	LALDButterworthREAL4TimeSeries(&status, &chan, &filterpar);
	TESTSTATUS(&status);

	if(trace_power){
		fprintf(stderr, "After highpass filter total power=%.*g\n",
			precision, sum_r4_squares(data, total_samples)/samples_per_second);
		}
	}
	
if(!bypass_lowpass_filter && (lowpass_filter_f>0) && (lowpass_filter_a > 0)){
	fprintf(stderr,"Applying low pass filter, f=%g a=%g order=%d\n",
		lowpass_filter_f, lowpass_filter_a, lowpass_filter_order);
	/* Setup Butterworth filter */
	filterpar.name="Butterworth Low Pass";
	filterpar.nMax=lowpass_filter_order;
	filterpar.f1=lowpass_filter_f;
	filterpar.a1=lowpass_filter_a;
	/* values that are 'not given' = out of range */
	/* why 2*nsamples ? LAL used to have a bug in it where
	   the pairs were sorted before deciding whether the filter 
	   is lowpass or highpass. Therefore, we need to specify a 
	   large, out of range, frequency f so that we get a low-pass filter.
	   The maximum frequency is Nyquist, hence 2*nsamples is definitely out of range */
	filterpar.f2=2*total_samples;
	filterpar.a2=-1.0;
		/* REAL4Sequence is the same as REAL4Vector - according to lal/Datatypes.h */
	chan.data=(REAL4Sequence *)td_data;
	LALDButterworthREAL4TimeSeries(&status, &chan, &filterpar);
	TESTSTATUS(&status);

	if(trace_power){
		fprintf(stderr, "After lowpass filter total power=%.*g\n",
			precision, sum_r4_squares(data, total_samples)/samples_per_second);
		}
	}

if(!bypass_first_window){
	fprintf(stderr,"Applying Hann window to input data\n");
	for(i=0;i<total_samples;i++)data[i]*=0.5*(1.0-cos((2.0*M_PI*i)/total_samples));
	window_sum=0.5;
	} else {
	window_sum=1.0;
	}

if(trace_power){
	fprintf(stderr, "After windowing total power=%.*g\n",
		precision, sum_r4_squares(data, total_samples)/samples_per_second);
	}

for(i=0;i<3;i++){
	fprintf(stderr,"Allocating phi[%ld]\n", i);
	LALCCreateVector(&status, &(phi[i]), freq_stop-freq_start);
	TESTSTATUS(&status);
	}

compute_test_fft(td_data, phi, 3, freq_start, freq_stop);

/* now free td_data to conserve space */
free(td_data->data);
data=NULL;
free(td_data);
td_data=NULL;

LALCCreateVector(&status, &pgram, freq_stop-freq_start);
TESTSTATUS(&status);

compute_calibrated_periodogram3(phi, freq_start, freq_stop, pgram, window_sum);

print_COMPLEX8Vector(pgram, output_sft, "CALIBRATED FREQUENCY DOMAIN DATA", output_mode, 0, freq_stop-freq_start);

if(output_power!=NULL){
	/* we need more space */
	for(i=0;i<3;i++){
		LALCDestroyVector(&status, &(phi[i]));
		TESTSTATUS(&status);
		}
	LALSCreateVector(&status, &power, freq_stop-freq_start);
	TESTSTATUS(&status);
	for(i=0;i<freq_stop-freq_start;i++)
		power->data[i]=(pgram->data[i].re*pgram->data[i].re+pgram->data[i].im*pgram->data[i].im);
	print_REAL4Vector(power, output_power, "CALIBRATED POWER", output_mode, 0, freq_stop-freq_start);
	}

/* we do not destroy large vectors when we are done unless we need
  to allocate a lot of space again. This reduces run time 
  of the program */
return 0;
}
Exemple #13
0
int main( int argc, char *argv[] )
{
  const UINT4 n  = 65536;
  const REAL4 dt = 1.0 / 16384.0;
  static LALStatus status;

  static REAL4TimeSeries         x;
  static COMPLEX8FrequencySeries X;

  static REAL4TimeSeries         y;
  static REAL4FrequencySeries    Y;

  static COMPLEX8TimeSeries      z;
  static COMPLEX8FrequencySeries Z;

  RealFFTPlan    *fwdRealPlan    = NULL;
  RealFFTPlan    *revRealPlan    = NULL;
  ComplexFFTPlan *fwdComplexPlan = NULL;
  ComplexFFTPlan *revComplexPlan = NULL;
  RandomParams   *randpar        = NULL;

  AverageSpectrumParams avgSpecParams;

  UINT4 srate[] = { 4096, 9000 };
  UINT4 npts[] = { 262144, 1048576 };
  REAL4 var[] = { 5, 16 };

  UINT4 j, sr, np, vr;


  /*CHAR fname[2048];*/

  ParseOptions( argc, argv );

  LALSCreateVector( &status, &x.data, n );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCCreateVector( &status, &X.data, n / 2 + 1 );
  TestStatus( &status, CODES( 0 ), 1 );

  LALCCreateVector( &status, &z.data, n );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCCreateVector( &status, &Z.data, n );
  TestStatus( &status, CODES( 0 ), 1 );

  LALCreateForwardRealFFTPlan( &status, &fwdRealPlan, n, 0 );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCreateReverseRealFFTPlan( &status, &revRealPlan, n, 0 );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCreateForwardComplexFFTPlan( &status, &fwdComplexPlan, n, 0 );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCreateReverseComplexFFTPlan( &status, &revComplexPlan, n, 0 );
  TestStatus( &status, CODES( 0 ), 1 );

  randpar = XLALCreateRandomParams( 100 );


  /*
   *
   * Try the real transform.
   *
   */


  x.f0 = 0;
  x.deltaT = dt;
  x.sampleUnits = lalMeterUnit;
  snprintf( x.name, sizeof( x.name ), "x" );
  XLALNormalDeviates( x.data, randpar );
  for ( j = 0; j < n; ++j ) /* add a 60 Hz line */
  {
    REAL4 t = j * dt;
    x.data->data[j] += 0.1 * cos( LAL_TWOPI * 60.0 * t );
  }
  LALSPrintTimeSeries( &x, "x.out" );

  snprintf( X.name, sizeof( X.name ), "X" );
  LALTimeFreqRealFFT( &status, &X, &x, fwdRealPlan );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCPrintFrequencySeries( &X, "X.out" );

  LALFreqTimeRealFFT( &status, &x, &X, revRealPlan );
  TestStatus( &status, CODES( 0 ), 1 );
  LALSPrintTimeSeries( &x, "xx.out" );


  /*
   *
   * Try the average power spectum.
   *
   */


  avgSpecParams.method = useMean;

  for ( np = 0; np < XLAL_NUM_ELEM(npts) ; ++np )
  {
    /* length of time series for 7 segments, overlapped by 1/2 segment */
    UINT4 tsLength = npts[np] * 7 - 6 * npts[np] / 2;
    LALCreateVector( &status, &y.data, tsLength );
    TestStatus( &status, CODES( 0 ), 1 );
    LALCreateVector( &status, &Y.data, npts[np] / 2 + 1  );
    TestStatus( &status, CODES( 0 ), 1 );
    avgSpecParams.overlap = npts[np] / 2;

    /* create the window */
    avgSpecParams.window = XLALCreateHannREAL4Window(npts[np]);
    avgSpecParams.plan = NULL;
    LALCreateForwardRealFFTPlan( &status, &avgSpecParams.plan, npts[np], 0 );
    TestStatus( &status, CODES( 0 ), 1 );

    for ( sr = 0; sr < XLAL_NUM_ELEM(srate) ; ++sr )
    {
      /* set the sample rate of the time series */
      y.deltaT = 1.0 / (REAL8) srate[sr];
      for ( vr = 0; vr < XLAL_NUM_ELEM(var) ; ++vr )
      {
        REAL4 eps = 1e-6; /* very conservative fp precision */
        REAL4 Sfk = 2.0 * var[vr] * var[vr] * y.deltaT;
        REAL4 sfk = 0;
        REAL4 lbn;
        REAL4 sig;
        REAL4 ssq;
        REAL4 tol;

        /* create the data */
        XLALNormalDeviates( y.data, randpar );
        ssq = 0;
        for ( j = 0; j < y.data->length; ++j )
        {
          y.data->data[j] *= var[vr];
          ssq += y.data->data[j] * y.data->data[j];
        }

        /* compute tolerance for comparison */
        lbn = log( y.data->length ) / log( 2 );
        sig = sqrt( 2.5 * lbn * eps * eps * ssq / y.data->length );
        tol = 5 * sig;

        /* compute the psd and find the average */
        LALREAL4AverageSpectrum( &status, &Y, &y, &avgSpecParams );
        TestStatus( &status, CODES( 0 ), 1 );
        LALSMoment( &status, &sfk, Y.data, 1 );
        TestStatus( &status, CODES( 0 ), 1 );

        /* check the result */
        if ( fabs(Sfk-sfk) > tol )
        {
          fprintf( stderr, "FAIL: PSD estimate appears incorrect\n");
          fprintf( stderr, "expected %e, got %e ", Sfk, sfk );
          fprintf( stderr, "(difference = %e, tolerance = %e)\n",
              fabs(Sfk-sfk), tol );
          exit(2);
        }

      }
    }

    /* destroy structures that need to be resized */
    LALDestroyRealFFTPlan( &status, &avgSpecParams.plan );
    TestStatus( &status, CODES( 0 ), 1 );
    XLALDestroyREAL4Window( avgSpecParams.window );
    LALDestroyVector( &status, &y.data );
    TestStatus( &status, CODES( 0 ), 1 );
    LALDestroyVector( &status, &Y.data );
    TestStatus( &status, CODES( 0 ), 1 );
  }


  /*
   *
   * Try the complex transform.
   *
   */


  z.f0 = 0;
  z.deltaT = dt;
  z.sampleUnits = lalVoltUnit;
  snprintf( z.name, sizeof( z.name ), "z" );
  { /* dirty hack */
    REAL4Vector tmp;
    tmp.length = 2 * z.data->length;
    tmp.data   = (REAL4 *)z.data->data;
    XLALNormalDeviates( &tmp, randpar );
  }
  for ( j = 0; j < n; ++j ) /* add a 50 Hz line and a 500 Hz ringdown */
  {
    REAL4 t = j * dt;
    z.data->data[j] += 0.2 * cos( LAL_TWOPI * 50.0 * t );
    z.data->data[j] += I * exp( -t ) * sin( LAL_TWOPI * 500.0 * t );
  }
  LALCPrintTimeSeries( &z, "z.out" );
  TestStatus( &status, CODES( 0 ), 1 );

  snprintf( Z.name, sizeof( Z.name ), "Z" );
  LALTimeFreqComplexFFT( &status, &Z, &z, fwdComplexPlan );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCPrintFrequencySeries( &Z, "Z.out" );

  LALFreqTimeComplexFFT( &status, &z, &Z, revComplexPlan );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCPrintTimeSeries( &z, "zz.out" );

  XLALDestroyRandomParams( randpar );

  LALDestroyRealFFTPlan( &status, &fwdRealPlan );
  TestStatus( &status, CODES( 0 ), 1 );
  LALDestroyRealFFTPlan( &status, &revRealPlan );
  TestStatus( &status, CODES( 0 ), 1 );
  LALDestroyComplexFFTPlan( &status, &fwdComplexPlan );
  TestStatus( &status, CODES( 0 ), 1 );
  LALDestroyComplexFFTPlan( &status, &revComplexPlan );
  TestStatus( &status, CODES( 0 ), 1 );

  LALCDestroyVector( &status, &Z.data );
  TestStatus( &status, CODES( 0 ), 1 );
  LALCDestroyVector( &status, &z.data );
  TestStatus( &status, CODES( 0 ), 1 );

  LALCDestroyVector( &status, &X.data );
  TestStatus( &status, CODES( 0 ), 1 );
  LALSDestroyVector( &status, &x.data );
  TestStatus( &status, CODES( 0 ), 1 );

  LALCheckMemoryLeaks();
  return 0;
}
int main( int argc, char *argv[] )
{
  static LALStatus                status;

  StochasticCrossCorrelationInput           input;
  REAL4WithUnits           output;

  COMPLEX8FrequencySeries  goodData1;
  COMPLEX8FrequencySeries  goodData2;
  COMPLEX8FrequencySeries  goodFilter;

  LIGOTimeGPS              epoch0 = {0,0};
  LIGOTimeGPS              epoch1 = {630720000,123456789};
  LIGOTimeGPS              epoch2 = {630720000,987654321};
  LIGOTimeGPS              epoch3 = {630722222,123456789};

  int                      result;

  CHAR                     unitString[LALUnitTextSize];
  
  UINT4 i;
  REAL4 f, x;
  INT4 code;


  ParseOptions( argc, argv );

  /* define valid parameters */

  goodFilter.f0     = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_F0;
  goodFilter.deltaF = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF;
  goodFilter.epoch  = epoch0;
  goodFilter.data   = NULL;

#ifndef LAL_NDEBUG
  COMPLEX8FrequencySeries  badFilter = goodFilter;
#endif

  goodData1 = goodFilter;

  goodData1.epoch = epoch1;
  goodData2 = goodData1;
#ifndef LAL_NDEBUG
  COMPLEX8FrequencySeries  badData1 = goodData2;
  COMPLEX8FrequencySeries  badData2 = badData1;
#endif

  LALCCreateVector(&status, &(goodData1.data),
                          STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH);
  if ( ( code = CheckStatus(&status, 0 , "",
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
  {
    return code;
  }

  LALCCreateVector(&status, &(goodData2.data),
                          STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH);
  if ( ( code = CheckStatus(&status, 0 , "",
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
  {
    return code;
  }

  LALCCreateVector(&status, &(goodFilter.data),
                          STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH);
  if ( ( code = CheckStatus(&status, 0 , "",
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
  {
    return code;
  }

  input.hBarTildeOne  = &goodData1;
  input.hBarTildeTwo  = &goodData2;
  input.optimalFilter = &goodFilter;

#ifndef LAL_NDEBUG
  if ( ! lalNoDebug )
  {
    /* test behavior for null pointer to output structure */
    LALStochasticCrossCorrelationStatistic(&status, NULL, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
      {
        return code;
      }
    printf("  PASS: null pointer to output structure results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* test behavior for null pointer to input structure */
    LALStochasticCrossCorrelationStatistic(&status, &output, NULL, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to input structure results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* test behavior for null pointer to first data stream */
    input.hBarTildeOne = NULL;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to first data stream results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to second data stream */
    input.hBarTildeOne = &goodData1;

    /* test behavior for null pointer to second data stream */
    input.hBarTildeTwo = NULL;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to second data stream results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to second data stream */
    input.hBarTildeTwo = &goodData2;

    /* test behavior for null pointer to optimal filter */
    input.optimalFilter = NULL;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to optimal filter results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to optimal filter */
    input.optimalFilter = &goodFilter;

    /* test behavior for null pointer to data member of first data stream */
    input.hBarTildeOne = &badData1;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to data member of first data stream results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to data member of first data stream */
    input.hBarTildeOne = &goodData1;

    /* test behavior for null pointer to data member of second data stream */
    input.hBarTildeTwo = &badData2;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to data member of second data stream results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to data member of second data stream */
    input.hBarTildeTwo = &goodData2;

    /* test behavior for null pointer to data member of optimal filter */
    input.optimalFilter = &badFilter;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to data member of optimal filter results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to data member of optimal filter */
    input.optimalFilter = &goodFilter;

    /* Create a vector for testing null data-data pointers */
    LALCCreateVector(&status, &(badFilter.data),
                          STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH);
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
    {
      return code;
    }
    COMPLEX8                *tempPtr;
    tempPtr = badFilter.data->data;
    badFilter.data->data = NULL;
    badData1.data = badData2.data = badFilter.data;

    /* test behavior for null pointer to data member of data member of first data stream */
    input.hBarTildeOne = &badData1;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to data member of data member of first data stream results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to data member of data member of first data stream */
    input.hBarTildeOne = &goodData1;

    /* test behavior for null pointer to data member of data member of second data stream */
    input.hBarTildeTwo = &badData2;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to data member of data member of second data stream results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to data member of data member of second data stream */
    input.hBarTildeTwo = &goodData2;

    /* test behavior for null pointer to data member of data member of optimal filter */
    input.optimalFilter = &badFilter;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENULLPTR,
			      STOCHASTICCROSSCORRELATIONH_MSGENULLPTR,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
     {
      return code;
    }
    printf("  PASS: null pointer to data member of data member of optimal filter results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENULLPTR);

    /* assign valid pointer to data member of data member of optimal filter */
    input.optimalFilter = &goodFilter;

    /* clean up */

    badFilter.data->data = tempPtr;
    LALCDestroyVector(&status, &(badFilter.data));
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
    {
      return code;
    }
    badData1.data = badData2.data = badFilter.data;

    /* test behavior for zero length */
    goodData1.data->length = goodData2.data->length
      = goodFilter.data->length = 0;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EZEROLEN,
			      STOCHASTICCROSSCORRELATIONH_MSGEZEROLEN,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
    {
      return code;
    }
    printf("  PASS: zero length results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGEZEROLEN);
    /* reassign valid length */
    goodData1.data->length = goodData2.data->length
      = goodFilter.data->length = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH;

    /* test behavior for negative frequency spacing */
    goodData1.deltaF = goodData2.deltaF
      = goodFilter.deltaF = -STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENONPOSDELTAF,
			      STOCHASTICCROSSCORRELATIONH_MSGENONPOSDELTAF,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
    {
      return code;
    }
    printf("  PASS: negative frequency spacing results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENONPOSDELTAF);

    /* test behavior for zero frequency spacing */
    goodData1.deltaF = goodData2.deltaF
      = goodFilter.deltaF = 0;
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
    if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENONPOSDELTAF,
			      STOCHASTICCROSSCORRELATIONH_MSGENONPOSDELTAF,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
    {
      return code;
    }
    printf("  PASS: zero frequency spacing results in error:\n       \"%s\"\n",
           STOCHASTICCROSSCORRELATIONH_MSGENONPOSDELTAF);
    /* reassign valid frequency spacing */
    goodData1.deltaF = goodData2.deltaF
      = goodFilter.deltaF = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF;
   } /* if ( ! lalNoDebug ) */
#endif /* LAL_NDEBUG */

  /* test behavior for negative start frequency */
  goodData1.f0 = goodData2.f0
    = goodFilter.f0 = -20.0;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_ENEGFMIN,
			    STOCHASTICCROSSCORRELATIONH_MSGENEGFMIN,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  printf("  PASS: negative start frequency results in error:\n       \"%s\"\n",
         STOCHASTICCROSSCORRELATIONH_MSGENEGFMIN);

  /* reassign valid start frequency */
  goodData1.f0 = goodData2.f0
    = goodFilter.f0 = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_F0;

  /* test behavior for length mismatch
     between optimal filter and first data stream */
  goodData1.data->length = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH - 1;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EMMLEN,
			    STOCHASTICCROSSCORRELATIONH_MSGEMMLEN,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  printf("  PASS: length mismatch between optimal filter and first data stream results in error:\n       \"%s\"\n",
         STOCHASTICCROSSCORRELATIONH_MSGEMMLEN);

  /* reassign correct length */
  goodData1.data->length = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH;

  /* test behavior for length mismatch
     between optimal filter and first data stream */
  goodData2.data->length = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH - 1;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EMMLEN,
			    STOCHASTICCROSSCORRELATIONH_MSGEMMLEN,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  printf("  PASS: length mismatch between optimal filter and second data stream results in error:\n       \"%s\"\n",
         STOCHASTICCROSSCORRELATIONH_MSGEMMLEN);

  /* reassign correct length */
  goodData2.data->length = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH;

  /* test behavior for frequency spacing mismatch
     between optimal filter and first data stream */
  goodData1.deltaF = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF * 2.0;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EMMDELTAF,
			    STOCHASTICCROSSCORRELATIONH_MSGEMMDELTAF,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  printf("  PASS: frequency spacing mismatch between optimal filter and first data stream results in error:\n       \"%s\"\n",
         STOCHASTICCROSSCORRELATIONH_MSGEMMDELTAF);

  /* reassign correct frequency spacing */
  goodData1.deltaF = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF;

  /* test behavior for frequency spacing mismatch
     between optimal filter and second data stream */
  goodData2.deltaF = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF * 2.0;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EMMDELTAF,
			    STOCHASTICCROSSCORRELATIONH_MSGEMMDELTAF,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  printf("  PASS: frequency spacing mismatch between optimal filter and second data stream results in error:\n       \"%s\"\n",
         STOCHASTICCROSSCORRELATIONH_MSGEMMDELTAF);

  /* reassign correct frequency spacing */
  goodData2.deltaF = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF;

  /* test behavior for start frequency mismatch
     between optimal filter and first data stream */
  goodData1.f0 = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_F0 + 2.0;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EMMFMIN,
			    STOCHASTICCROSSCORRELATIONH_MSGEMMFMIN,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  printf("  PASS: start frequency mismatch between optimal filter and first data stream results in error:\n       \"%s\"\n",
         STOCHASTICCROSSCORRELATIONH_MSGEMMFMIN);

  /* reassign correct start frequency */
  goodData1.f0 = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_F0;

  /* test behavior for start frequency mismatch
     between optimal filter and second data stream */
  goodData2.f0 = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_F0 + 2.0;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EMMFMIN,
			    STOCHASTICCROSSCORRELATIONH_MSGEMMFMIN,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  printf("  PASS: start frequency mismatch between optimal filter and second data stream results in error:\n       \"%s\"\n",
         STOCHASTICCROSSCORRELATIONH_MSGEMMFMIN);

  /* reassign correct start frequency */
  goodData2.f0 = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_F0;

  /* test behavior for mismatch between epochs of data streams */
  goodData2.epoch = epoch2;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EMMTIME,
			    STOCHASTICCROSSCORRELATIONH_MSGEMMTIME,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  goodData2.epoch = epoch3;
  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, STOCHASTICCROSSCORRELATIONH_EMMTIME,
			    STOCHASTICCROSSCORRELATIONH_MSGEMMTIME,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ECHK,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGECHK) ) )
  {
    return code;
  }
  printf("  PASS: mismatch between epochs of data streams results in error:\n       \"%s\"\n",
         STOCHASTICCROSSCORRELATIONH_MSGEMMTIME);

  /* reassign correct epoch */
  goodData2.epoch = epoch1;

  /******************** Test Valid Data Case #1 ***********************/
  goodData1.sampleUnits = lalDimensionlessUnit;
  goodData1.sampleUnits.unitNumerator[LALUnitIndexStrain] = 1;
  goodData1.sampleUnits.unitNumerator[LALUnitIndexSecond] = 1;
  goodData2.sampleUnits = goodData1.sampleUnits;
  goodFilter.sampleUnits = lalDimensionlessUnit;
  goodFilter.sampleUnits.unitNumerator[LALUnitIndexStrain] = -1;

  goodData1.f0 = goodData2.f0 = goodFilter.f0 = 0.0;

  goodData1.data->data[0] = goodData2.data->data[0] = goodFilter.data->data[0] = 0.0;

  for (i=1; i<STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH; ++i)
  {
    f = i * STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF;
    x = f / (STOCHASTICCROSSCORRELATIONSTATISTICTESTC_FLIM / 2.0);
    goodData1.data->data[i] = crectf( x*x, x );
    goodData2.data->data[i] = crectf( 1.0/crealf(goodData1.data->data[i]), -1.0/cimagf(goodData1.data->data[i]) );
    goodFilter.data->data[i] = crectf( x * (2-x), 0.0 );
  }

  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, 0 , "",
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
  {
    return code;
  }

  if (optVerbose) printf("Y=%g, should be 0\n",output.value);
  if (fabsf(output.value)/STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF
      > STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TOL)
  {
    printf("  FAIL: Valid data test #1\n");
    if (optVerbose)
    {
      printf("Exiting with error: %s\n",
             STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS);
    }
    return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
  }

  result = XLALUnitCompare(&(goodData1.sampleUnits), &(output.units));
  if (optVerbose)
  {
    if ( XLALUnitAsString( unitString, LALUnitTextSize, &(output.units)) == NULL ) {
      return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
    }
    printf( "Units are \"%s\", ", unitString );
    if ( XLALUnitAsString( unitString, LALUnitTextSize, &(goodData1.sampleUnits)) == NULL ) {
      return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
    }
    printf( "should be \"%s\"\n", unitString );
  }

  if (result != 0)
  {
    printf("  FAIL: Valid data test #1\n");
    if (optVerbose)
    {
      printf("Exiting with error: %s\n",
             STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS);
    }
    return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
  }

  printf("  PASS: Valid data test #1\n");


  /********************** Test Valid Data Case #2 *****************/
  goodData1.sampleUnits = lalDimensionlessUnit;
  goodData1.sampleUnits.unitNumerator[LALUnitIndexStrain] = 1;
  goodData1.sampleUnits.unitNumerator[LALUnitIndexSecond] = 1;
  goodData2.sampleUnits = lalDimensionlessUnit;
  goodData2.sampleUnits.unitNumerator[LALUnitIndexADCCount] = 1;
  goodData2.sampleUnits.unitNumerator[LALUnitIndexSecond] = 1;
  goodFilter.sampleUnits = lalDimensionlessUnit;
  goodFilter.sampleUnits.unitNumerator[LALUnitIndexStrain] = -1;
  goodFilter.sampleUnits.unitNumerator[LALUnitIndexADCCount] = -1;

  goodData1.f0 = goodData2.f0 = goodFilter.f0
    = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_F0;

  for (i=0; i<STOCHASTICCROSSCORRELATIONSTATISTICTESTC_LENGTH; ++i)
  {
    f = STOCHASTICCROSSCORRELATIONSTATISTICTESTC_F0
      + i * STOCHASTICCROSSCORRELATIONSTATISTICTESTC_DELTAF;
    goodData1.data->data[i] = crectf( f/STOCHASTICCROSSCORRELATIONSTATISTICTESTC_FLIM, 0.0 );
    goodData2.data->data[i] = crectf( 1 - crealf(goodData1.data->data[i]), 0.0 );
    if ( f > STOCHASTICCROSSCORRELATIONSTATISTICTESTC_WINMIN
         && f < STOCHASTICCROSSCORRELATIONSTATISTICTESTC_WINMAX )
    {
      goodFilter.data->data[i] = 1.0;
    }
    else
    {
      goodFilter.data->data[i] = 0.0;
    }
  }

  LALStochasticCrossCorrelationStatistic(&status, &output, &input, STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TRUE);
  if ( ( code = CheckStatus(&status, 0 , "",
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
  {
    return code;
  }

  if (optVerbose)
  {
    printf("Y=%g, should be %g\n",output.value,
           STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EXP2);
  }
  if ( fabs(output.value-STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EXP2)
       / STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EXP2
       > STOCHASTICCROSSCORRELATIONSTATISTICTESTC_TOL)
  {
    printf("  FAIL: Valid data test #2\n");
    if (optVerbose)
    {
      printf("Exiting with error: %s\n",
             STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS);
    }
    return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
  }

  result = XLALUnitCompare(&lalSecondUnit, &(output.units));
  if (optVerbose)
  {
    if ( XLALUnitAsString( unitString, LALUnitTextSize, &(output.units)) == NULL ) {
      return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
    }
    printf( "Units are \"%s\", ", unitString );
    if ( XLALUnitAsString( unitString, LALUnitTextSize, &lalSecondUnit) == NULL ) {
      return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
    }
    printf( "should be \"%s\"\n", unitString );
  }

  if (result != 0)
  {
    printf("  FAIL: Valid data test #2\n");
    if (optVerbose)
    {
      printf("Exiting with error: %s\n",
             STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS);
    }
    return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
  }

  printf("  PASS: Valid data test #2\n");


  /* clean up */
  LALCDestroyVector(&status, &(goodFilter.data));
  if ( ( code = CheckStatus(&status, 0 , "",
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
  {
    return code;
  }

  LALCDestroyVector(&status, &(goodData1.data));
  if ( ( code = CheckStatus(&status, 0 , "",
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
  {
    return code;
  }

  LALCDestroyVector(&status, &(goodData2.data));
  if ( ( code = CheckStatus(&status, 0 , "",
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			    STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
  {
    return code;
  }

  printf("PASS: all tests\n");
  LALCheckMemoryLeaks();

  if (optData1File[0] && optData2File[0] && optFilterFile[0])
  {

    /* Allocate Memory */
    LALCCreateVector(&status, &(goodFilter.data), optLength);
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EUSE,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEUSE) ) )
    {
      return code;
    }
    LALCCreateVector(&status, &(goodData1.data), optLength);
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EUSE,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEUSE) ) )
    {
      return code;
    }
    LALCCreateVector(&status, &(goodData2.data), optLength);
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EUSE,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEUSE) ) )
    {
      return code;
    }
    /* Read Data From Files */
    LALCReadFrequencySeries(&status, &(goodFilter), optFilterFile);
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EUSE,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEUSE) ) )
    {
      return code;
    }
    LALCReadFrequencySeries(&status, &(goodData1), optData1File);
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EUSE,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEUSE) ) )
    {
      return code;
    }
    LALCReadFrequencySeries(&status, &(goodData2), optData2File);
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EUSE,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEUSE) ) )
    {
      return code;
    }
    /* Calculate CC Statistic */
    LALStochasticCrossCorrelationStatistic(&status, &output, &input, optMatch);
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EUSE,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEUSE) ) )
    {
      return code;
    }

    /* Convert Unit Structure to String */
    if ( XLALUnitAsString( unitString, LALUnitTextSize, &(output.units)) == NULL ) {
      return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS;
    }

    printf("=========== Cross-Correlation Statistic for User-Specified Data Is =======\n");
    printf("     %g %s\n", output.value, unitString);

    /* Deallocate Memory */
    LALCDestroyVector(&status, &(goodFilter.data));
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
    {
      return code;
    }
    LALCDestroyVector(&status, &(goodData1.data));
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
    {
      return code;
    }
    LALCDestroyVector(&status, &(goodData2.data));
    if ( ( code = CheckStatus(&status, 0 , "",
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_EFLS,
			      STOCHASTICCROSSCORRELATIONSTATISTICTESTC_MSGEFLS) ) )
    {
      return code;
    }
  }


  /* normal exit */
  LALCheckMemoryLeaks();
  return STOCHASTICCROSSCORRELATIONSTATISTICTESTC_ENOM;
}
int main( int argc, char *argv[] )
{
  UINT4 i, j, k;
  const REAL4 tiny = 1e-6;

  CHAR  ifoCode[][3] = { "H1", "L1" };
  INT4  calTime[] = { 729331981, 729332039, 729332040, 729332041, 729332099,
    800000000 };
  CHAR  cacheTime[][21] = { "729273600-734367600", "729273600-734367600" };
  COMPLEX8 H1AlphaBeta[] = { {0.9883124570783, 0}, {0.9883124570783, 0},
    {1.123396433694, 0}, {1.123396433694, 0}, {1.123396433694, 0}, {0, 0} };
  COMPLEX8 L1AlphaBeta[] = { {0, 0}, {0, 0}, {0.6041572088741, 0},
    {0.6041572088741, 0}, {0.6041572088741, 0}, {0, 0} };

  static LALStatus      status;
  const CHAR            calCacheName[LALNameLength];
  LALCache             *calCache = NULL;
  UINT4                 numPoints = 262144;
  UINT4                 sampleRate = 4096;
  CHAR                  outFile[LALNameLength];
  LIGOTimeGPS           duration = {0,0};

  COMPLEX8FrequencySeries       response;
  const LALUnit strainPerCount = {0,{0,0,0,0,0,1,-1},{0,0,0,0,0,0,0}};

  ParseOptions (argc, argv);

  /* clear the response function and create storage for the frequency series */
  memset( &response, 0, sizeof(COMPLEX8FrequencySeries) );
  LALCCreateVector( &status, &(response.data), numPoints / 2 + 1 );
  TESTSTATUS( &status );

  /* set the parameters of the response function to generate */
  response.deltaF = (REAL8) sampleRate / (REAL8) numPoints;
  response.sampleUnits = strainPerCount;

  /* loop over the three interferometers */
  for ( j = 0; j < sizeof(ifoCode) / sizeof(*ifoCode); ++j )
  {
    snprintf( response.name, LALNameLength * sizeof(CHAR),
        CHANNEL, ifoCode[j] );

    for ( i = 0; i < sizeof(calTime) / sizeof(*calTime); ++i )
    {
      /* set the time of the calibration and the frame cahche file to use */
      snprintf( calCacheName, LALNameLength * sizeof(CHAR), CAL_CATALOG,
          ifoCode[j], cacheTime[i % 2] );
      response.epoch.gpsSeconds = calTime[i];
      if ( verbose )
      {
        fprintf( stdout, "Calibration for GPS time %d from %s\n",
            response.epoch.gpsSeconds, calCacheName );
        fflush( stdout );
      }

      /* create the response function */
      LALExtractFrameResponse( &status, &response, calCacheName, ifoCode[j],
          &duration );
      if ( status.statusCode == -1 && status.statusPtr )
      {
        if ( status.statusPtr->statusCode == FRAMESTREAMH_EDONE &&
            calTime[i] == 800000000 )
        {
          /* no calibration for this time */
          if ( verbose )
          {
            fprintf( stderr, "OK: No calibration for 800000000\n" );
            LALPrintError( "OK: %s\n", status.statusPtr->statusDescription );
          }
          CLEARSTATUS( status );
        }
        else if ( status.statusPtr->statusCode == CALIBRATIONH_EZERO &&
            ! strncmp( ifoCode[j], "L1", 2 * sizeof(CHAR) ) &&
            (calTime[i] == 729331981 || calTime[i] == 729332039) )
        {
          /* alpha is zero at this time */
          if ( verbose )
          {
            fprintf( stderr, "OK: Cal is zero for L1 at 729332039\n" );
            LALPrintError( "OK: %s\n", status.statusPtr->statusDescription );
          }
          CLEARSTATUS( status );
        }
        else
        {
          /* some other error */
          TESTSTATUS( &status );
        }
      }
      else
      {
        TESTSTATUS( &status );

        /* FIXME check that the values match the expected ones          */
        /* H1AlphaBeta[i] and L1AlphaBeta[i] give the correct values    */
        /* for this i, so we need to check that the returned values     */
        /* match the expected ones up to tiny. Need to if on j to get   */
        /* the correct ifo                                              */

        /* test that the response does not contain NaN or Inf */
        for ( k = 0; k < response.data->length; ++k )
        {
          if ( (! finite( response.data->data[k].re )) ||
              (! finite( response.data->data[k].im )) )
          {
            fprintf( stderr, "ERROR: non-finite value found in response "
                "at k = %d (%e,%e)\n",
                k, response.data->data[k].re, response.data->data[k].im );
            exit( 1 );
          }
        }

        /* print out the response function */
        if ( verbose )
        {
          fprintf( stdout, "Calibration updated\n" );
          fflush( stdout );
        }
        if ( output )
        {
          snprintf( outFile, LALNameLength * sizeof(CHAR),
              "Response-%s-%d.txt", ifoCode[j], response.epoch.gpsSeconds );
          LALCPrintFrequencySeries( &response, outFile );
        }
      }
    }
  }

  /* free memory */
  LALCDestroyVector( &status, &(response.data) );
  TESTSTATUS( &status );

  LALCheckMemoryLeaks();
  return 0;
}
int main( int argc, char *argv[] )
{
  static LALStatus status;

  RealFFTPlan    *fwd = NULL;
  RealFFTPlan    *rev = NULL;
  REAL4Vector    *dat = NULL;
  REAL4Vector    *rfft = NULL;
  REAL4Vector    *ans = NULL;
  COMPLEX8Vector *dft = NULL;
  COMPLEX8Vector *fft = NULL;
#if LAL_CUDA_ENABLED
  /* The test itself should pass at 1e-4, but it might fail at
   * some rare cases where accuracy is bad for some numbers. */
  REAL8           eps = 3e-4;
#else
  /* very conservative floating point precision */
  REAL8           eps = 1e-6;
#endif
  REAL8           lbn;
  REAL8           ssq;
  REAL8           var;
  REAL8           tol;

  UINT4 nmax;
  UINT4 m;
  UINT4 n;
  UINT4 i;
  UINT4 j;
  UINT4 k;
  UINT4 s = 0;

  FILE *fp;


  ParseOptions( argc, argv );
  m = m_;
  n = n_;

  fp = verbose ? stdout : NULL ;

  if ( n == 0 )
  {
    nmax = 65536;
  }
  else
  {
    nmax = n--;
  }

  while ( n < nmax )
  {
    if ( n < 128 )
    {
      ++n;
    }
    else
    {
      n *= 2;
    }

    LALSCreateVector( &status, &dat, n );
    TestStatus( &status, CODES( 0 ), 1 );
    LALSCreateVector( &status, &rfft, n );
    TestStatus( &status, CODES( 0 ), 1 );
    LALSCreateVector( &status, &ans, n );
    TestStatus( &status, CODES( 0 ), 1 );
    LALCCreateVector( &status, &dft, n / 2 + 1 );
    TestStatus( &status, CODES( 0 ), 1 );
    LALCCreateVector( &status, &fft, n / 2 + 1 );
    TestStatus( &status, CODES( 0 ), 1 );
    LALCreateForwardRealFFTPlan( &status, &fwd, n, 0 );
    TestStatus( &status, CODES( 0 ), 1 );
    LALCreateReverseRealFFTPlan( &status, &rev, n, 0 );
    TestStatus( &status, CODES( 0 ), 1 );

    /*
     *
     * Do m trials of random data.
     *
     */
    for ( i = 0; i < m; ++i )
    {
      srand( s++ ); /* seed the random number generator */

      /*
       *
       * Create data and compute error tolerance.
       *
       * Reference: Kaneko and Liu,
       * "Accumulation of round-off error in fast fourier tranforms"
       * J. Asssoc. Comp. Mach, Vol 17 (No 4) 637-654, October 1970.
       *
       */
      srand( i ); /* seed the random number generator */
      ssq = 0;
      for ( j = 0; j < n; ++j )
      {
        dat->data[j] = 20.0 * rand() / (REAL4)( RAND_MAX + 1.0 ) - 10.0;
        ssq += dat->data[j] * dat->data[j];
        fp ? fprintf( fp, "%e\n", dat->data[j] ) : 0;
      }
      lbn = log( n ) / log( 2 );
      var = 2.5 * lbn * eps * eps * ssq / n;
      tol = 5 * sqrt( var ); /* up to 5 sigma excursions */
      fp ? fprintf( fp, "\neps = %e \ntol = %e\n", eps, tol ) : 0;

      /*
       *
       * Perform forward FFT and DFT (only if n < 100).
       *
       */
      LALForwardRealFFT( &status, fft, dat, fwd );
      TestStatus( &status, CODES( 0 ), 1 );
      LALREAL4VectorFFT( &status, rfft, dat, fwd );
      TestStatus( &status, CODES( 0 ), 1 );
      LALREAL4VectorFFT( &status, ans, rfft, rev );
      TestStatus( &status, CODES( 0 ), 1 );
      fp ?  fprintf( fp, "rfft()\t\trfft(rfft())\trfft(rfft())\n\n"  ) : 0;
      for ( j = 0; j < n; ++j )
      {
        fp ? fprintf( fp, "%e\t%e\t%e\n",
            rfft->data[j], ans->data[j], ans->data[j] / n ) : 0;
      }
      if ( n < 128 )
      {
        LALForwardRealDFT( &status, dft, dat );
        TestStatus( &status, CODES( 0 ), 1 );

        /*
         *
         * Check accuracy of FFT vs DFT.
         *
         */
        fp ? fprintf( fp, "\nfftre\t\tfftim\t\t" ) : 0;
        fp ? fprintf( fp, "dtfre\t\tdftim\n" ) : 0;
        for ( k = 0; k <= n / 2; ++k )
        {
          REAL8 fftre = creal(fft->data[k]);
          REAL8 fftim = cimag(fft->data[k]);
          REAL8 dftre = creal(dft->data[k]);
          REAL8 dftim = cimag(dft->data[k]);
          REAL8 errre = fabs( dftre - fftre );
          REAL8 errim = fabs( dftim - fftim );
          REAL8 avere = fabs( dftre + fftre ) / 2 + eps;
          REAL8 aveim = fabs( dftim + fftim ) / 2 + eps;
          REAL8 ferre = errre / avere;
          REAL8 ferim = errim / aveim;
          fp ? fprintf( fp, "%e\t%e\t", fftre, fftim ) : 0;
          fp ? fprintf( fp, "%e\t%e\n", dftre, dftim ) : 0;
          /* fp ? fprintf( fp, "%e\t%e\t", errre, errim ) : 0; */
          /* fp ? fprintf( fp, "%e\t%e\n", ferre, ferim ) : 0; */
          if ( ferre > eps && errre > tol )
          {
            fputs( "FAIL: Incorrect result from forward transform\n", stderr );
            fprintf( stderr, "\tdifference = %e\n", errre );
            fprintf( stderr, "\ttolerance  = %e\n", tol );
            fprintf( stderr, "\tfrac error = %e\n", ferre );
            fprintf( stderr, "\tprecision  = %e\n", eps );
            return 1;
          }
          if ( ferim > eps && errim > tol )
          {
            fputs( "FAIL: Incorrect result from forward transform\n", stderr );
            fprintf( stderr, "\tdifference = %e\n", errim );
            fprintf( stderr, "\ttolerance  = %e\n", tol );
            fprintf( stderr, "\tfrac error = %e\n", ferim );
            fprintf( stderr, "\tprecision  = %e\n", eps );
            return 1;
          }
        }
      }

      /*
       *
       * Perform reverse FFT and check accuracy vs original data.
       *
       */
      LALReverseRealFFT( &status, ans, fft, rev );
      TestStatus( &status, CODES( 0 ), 1 );
      fp ? fprintf( fp, "\ndat->data[j]\tans->data[j] / n\n" ) : 0;
      for ( j = 0; j < n; ++j )
      {
        REAL8 err = fabs( dat->data[j] - ans->data[j] / n );
        REAL8 ave = fabs( dat->data[j] + ans->data[j] / n ) / 2 + eps;
        REAL8 fer = err / ave;
        fp ? fprintf( fp, "%e\t%e\n", dat->data[j], ans->data[j] / n ) : 0;
        /* fp ? fprintf( fp, "%e\t%e\n", err, fer ) : 0; */
        if ( fer > eps && err > tol )
        {
          fputs( "FAIL: Incorrect result after reverse transform\n", stderr );
          fprintf( stderr, "\tdifference = %e\n", err );
          fprintf( stderr, "\ttolerance  = %e\n", tol );
          fprintf( stderr, "\tfrac error = %e\n", fer );
          fprintf( stderr, "\tprecision  = %e\n", eps );
          return 1;
        }
      }
    }

    LALSDestroyVector( &status, &dat );
    TestStatus( &status, CODES( 0 ), 1 );
    LALSDestroyVector( &status, &rfft );
    TestStatus( &status, CODES( 0 ), 1 );
    LALSDestroyVector( &status, &ans );
    TestStatus( &status, CODES( 0 ), 1 );
    LALCDestroyVector( &status, &dft );
    TestStatus( &status, CODES( 0 ), 1 );
    LALCDestroyVector( &status, &fft );
    TestStatus( &status, CODES( 0 ), 1 );
    LALDestroyRealFFTPlan( &status, &fwd );
    TestStatus( &status, CODES( 0 ), 1 );
    LALDestroyRealFFTPlan( &status, &rev );
    TestStatus( &status, CODES( 0 ), 1 );
  }

  LALCheckMemoryLeaks();
  return 0;
}