Ejemplo n.º 1
0
/** Initialize Fstat-code: handle user-input and set everything up. */
int
XLALInitCode ( ConfigVariables *cfg, const UserInput_t *uvar )
{
  /* generate log-string for file-output, containing cmdline-options + code VCS version info */
  char *vcs;
  if ( (vcs = XLALGetVersionString(0)) == NULL ) {	  /* short VCS version string */
    XLALPrintError ( "%s: XLALGetVersionString(0) failed with errno=%d.\n", __func__, xlalErrno );
    XLAL_ERROR ( XLAL_EFUNC );
  }
  char *cmdline;
  if ( (cmdline = XLALUserVarGetLog ( UVAR_LOGFMT_CMDLINE )) == NULL ) {
    XLALPrintError ( "%s: XLALUserVarGetLog ( UVAR_LOGFMT_CMDLINE ) failed with errno=%d.\n", __func__, xlalErrno );
    XLAL_ERROR ( XLAL_EFUNC );
  }
  const char fmt[] = "%%%% cmdline: %s\n%%%%\n%s%%%%\n";
  UINT4 len = strlen(vcs) + strlen(cmdline) + strlen(fmt) + 1;
  if ( ( cfg->logString = XLALMalloc ( len  )) == NULL ) {
    XLALPrintError ("%s: XLALMalloc ( %d ) failed.\n", __func__, len );
    XLAL_ERROR ( XLAL_ENOMEM );
  }
  sprintf ( cfg->logString, fmt, cmdline, vcs );
  XLALFree ( cmdline );
  XLALFree ( vcs );

  /* trivial settings from user-input */
  cfg->SignalOnly = uvar->SignalOnly;

  /* ----- parse user-input on signal amplitude-paramters + ranges ----- */
  /* skypos */
  cfg->skypos.longitude = uvar->Alpha;	/* Alpha < 0 indicates 'allsky' */
  cfg->skypos.latitude  = uvar->Delta;
  cfg->skypos.system = COORDINATESYSTEM_EQUATORIAL;

  /* ----- amplitude-params: create prior pdfs reflecting the user-input */
  if ( XLALInitAmplitudePrior ( &cfg->AmpPrior, uvar ) != XLAL_SUCCESS )
    XLAL_ERROR ( XLAL_EFUNC );

  /* ----- initialize random-number generator ----- */
  /* read out environment variables GSL_RNG_xxx
   * GSL_RNG_SEED: use to set random seed: default = 0, override by using --randSeed on cmdline
   * GSL_RNG_TYPE: type of random-number generator to use: default = 'mt19937'
   */
  gsl_rng_env_setup ();
  /* allow overriding the random-seed per command-line */
  if ( XLALUserVarWasSet ( &uvar->randSeed ) )
    gsl_rng_default_seed = uvar->randSeed;
  cfg->rng = gsl_rng_alloc (gsl_rng_default);

  LogPrintf ( LOG_DEBUG, "random-number generator type: %s\n", gsl_rng_name (cfg->rng));
  LogPrintf ( LOG_DEBUG, "seed = %lu\n", gsl_rng_default_seed );

  /* init ephemeris-data */
  EphemerisData *edat = XLALInitBarycenter( uvar->ephemEarth, uvar->ephemSun );
  if ( !edat ) {
    LogPrintf ( LOG_CRITICAL, "%s: XLALInitBarycenter failed: could not load Earth ephemeris '%s' and Sun ephemeris '%s'\n", __func__, uvar->ephemEarth, uvar->ephemSun);
    XLAL_ERROR ( XLAL_EFUNC );
  }

  UINT4 numDetectors = uvar->IFOs->length;
  MultiLALDetector multiDet;
  XLAL_CHECK ( XLALParseMultiLALDetector ( &multiDet, uvar->IFOs ) == XLAL_SUCCESS, XLAL_EFUNC );

  /* init timestamps vector covering observation time */
  UINT4 numSteps = (UINT4) ceil ( uvar->dataDuration / uvar->TAtom );
  MultiLIGOTimeGPSVector * multiTS;
  if ( (multiTS = XLALCreateMultiLIGOTimeGPSVector (numDetectors)) == NULL ) {
     XLALPrintError ("%s: XLALCreateMultiLIGOTimeGPSVector(%d) failed.\n", __func__, numDetectors );
  }

  for ( UINT4 X=0; X < numDetectors; X++ )    {
    if ( (multiTS->data[X] = XLALCreateTimestampVector (numSteps)) == NULL ) {
      XLALPrintError ("%s: XLALCreateTimestampVector(%d) failed.\n", __func__, numSteps );
    }
    multiTS->data[X]->deltaT = uvar->TAtom;
    UINT4 i;
    for ( i=0; i < numSteps; i ++ )
      {
	UINT4 ti = uvar->dataStartGPS + i * uvar->TAtom;
	multiTS->data[X]->data[i].gpsSeconds = ti;
	multiTS->data[X]->data[i].gpsNanoSeconds = 0;
      }
  }

  /* get detector states */
  if ( (cfg->multiDetStates = XLALGetMultiDetectorStates ( multiTS, &multiDet, edat, 0.5 * uvar->TAtom )) == NULL ) {
    XLALPrintError ( "%s: XLALGetMultiDetectorStates() failed.\n", __func__ );
    XLAL_ERROR ( XLAL_EFUNC );
  }

  if ( uvar->sqrtSX ) { /* translate user-input PSD sqrt(SX) to noise-weights (this actually does not care whether they were normalized or not) */

    /* parse input comma-separated list */
    MultiNoiseFloor multiNoiseFloor;
    XLAL_CHECK ( XLALParseMultiNoiseFloor ( &multiNoiseFloor, uvar->sqrtSX, numDetectors ) == XLAL_SUCCESS, XLAL_EFUNC );

    /* translate to noise weights */
    XLAL_CHECK ( ( cfg->multiNoiseWeights = XLALComputeConstantMultiNoiseWeightsFromNoiseFloor ( &multiNoiseFloor, multiTS, uvar->TAtom ) ) != NULL, XLAL_EFUNC );

  } /* if ( uvar->sqrtSX ) */

  /* get rid of all temporary memory allocated for this step */
  XLALDestroyEphemerisData ( edat );
  XLALDestroyMultiTimestamps ( multiTS );
  multiTS = NULL;

  /* ---------- initialize transient window ranges, for injection ... ---------- */
  cfg->transientInjectRange.type = TRANSIENT_NONE;			/* default: no transient signal window */
  /* apply correct defaults if unset: t0=dataStart, t0Band=dataDuration-3*tauMax */
//   cfg->transientInjectRange.t0 = uvar->dataStartGPS + uvar->injectWindow_t0Days * DAY24;

  cfg->transientSearchRange = cfg->transientInjectRange;
  return XLAL_SUCCESS;

} /* XLALInitCode() */
Ejemplo n.º 2
0
/**
 * basic initializations: set-up 'ConfigVariables'
 */
int
XLALInitCode ( ConfigVariables *cfg, const UserVariables_t *uvar, const char *app_name)
{
  if ( !cfg || !uvar || !app_name ) {
    LogPrintf (LOG_CRITICAL, "%s: illegal NULL pointer input.\n\n", __func__ );
    XLAL_ERROR (XLAL_EINVAL );
  }

  /* Init ephemerides */
  XLAL_CHECK ( (cfg->edat = XLALInitBarycenter ( uvar->ephemEarth, uvar->ephemSun )) != NULL, XLAL_EFUNC );

  // ----- figure out which segments to use
  BOOLEAN manualSegments = XLALUserVarWasSet(&uvar->duration) || XLALUserVarWasSet(&uvar->startTime) || XLALUserVarWasSet(&uvar->Nseg);
  if ( manualSegments && uvar->segmentList ) {
    XLAL_ERROR ( XLAL_EDOM, "Can specify EITHER {--startTime, --duration, --Nseg} OR --segmentList\n");
  }
  LIGOTimeGPS startTimeGPS;
  REAL8 duration;
  if ( uvar->segmentList == NULL )
    {
      XLAL_CHECK ( uvar->Nseg >= 1, XLAL_EDOM, "Invalid input --Nseg=%d: number of segments must be >= 1\n", uvar->Nseg );
      XLAL_CHECK ( uvar->duration >= 1, XLAL_EDOM, "Invalid input --duration=%f: duration must be >= 1 s\n", uvar->duration );
      startTimeGPS = uvar->startTime;
      int ret = XLALSegListInitSimpleSegments ( &cfg->segmentList, startTimeGPS, uvar->Nseg, uvar->duration / uvar->Nseg );
      XLAL_CHECK ( ret == XLAL_SUCCESS, XLAL_EFUNC, "XLALSegListInitSimpleSegments() failed with xlalErrno = %d\n", xlalErrno );
      duration = uvar->duration;
    }
  else
    {
      LALSegList *segList = XLALReadSegmentsFromFile ( uvar->segmentList );
      XLAL_CHECK ( segList != NULL, XLAL_EIO, "XLALReadSegmentsFromFile() failed to load segment list from file '%s', xlalErrno = %d\n", uvar->segmentList, xlalErrno );
      cfg->segmentList = (*segList);	// copy *contents*
      XLALFree ( segList );
      startTimeGPS = cfg->segmentList.segs[0].start;
      UINT4 Nseg = cfg->segmentList.length;
      LIGOTimeGPS endTimeGPS = cfg->segmentList.segs[Nseg-1].end;
      duration = XLALGPSDiff( &endTimeGPS, &startTimeGPS );
    }

  /* ----- figure out reference time */
  LIGOTimeGPS refTimeGPS;

  /* treat special values first */
  if ( uvar->refTime.gpsSeconds == 0 )		/* 0 = use startTime */
    {
      refTimeGPS = uvar->startTime;
    }
  else if ( !XLALUserVarWasSet ( &uvar->refTime ) )	/* default = use mid-time of observation */
    {
      refTimeGPS = startTimeGPS;
      XLALGPSAdd( &refTimeGPS, duration / 2.0 );
    }
  else
    {
      refTimeGPS = uvar->refTime;
    }

  /* ----- get parameter-space point from user-input) */
  cfg->signalParams.Amp.h0 = uvar->h0;
  cfg->signalParams.Amp.cosi = uvar->cosi;
  cfg->signalParams.Amp.psi = uvar->psi;
  cfg->signalParams.Amp.phi0 = uvar->phi0;

  {
    PulsarDopplerParams *dop = &(cfg->signalParams.Doppler);
    XLAL_INIT_MEM((*dop));
    dop->refTime = refTimeGPS;
    dop->Alpha    = uvar->Alpha;
    dop->Delta    = uvar->Delta;
    dop->fkdot[0] = uvar->Freq;
    dop->fkdot[1] = uvar->f1dot;
    dop->fkdot[2] = uvar->f2dot;
    dop->fkdot[3] = uvar->f3dot;
    dop->asini    = uvar->orbitasini;
    dop->period   = uvar->orbitPeriod;
    dop->tp       = uvar->orbitTp;
    dop->ecc      = uvar->orbitEcc;
    dop->argp     = uvar->orbitArgp;
  }

  /* ----- initialize IFOs and (Multi-)DetectorStateSeries  ----- */
  XLAL_CHECK ( XLALParseMultiLALDetector ( &cfg->multiIFO, uvar->IFOs ) == XLAL_SUCCESS, XLAL_EFUNC );
  UINT4 numDet = cfg->multiIFO.length;
  XLAL_CHECK ( numDet >= 1, XLAL_EINVAL );

  if ( uvar->sqrtSX ) {
    XLAL_CHECK ( XLALParseMultiNoiseFloor ( &cfg->multiNoiseFloor, uvar->sqrtSX, numDet ) == XLAL_SUCCESS, XLAL_EFUNC );
  }

  /* ---------- translate coordinate system into internal representation ---------- */
  if ( XLALDopplerCoordinateNames2System ( &cfg->coordSys, uvar->coords ) ) {
    LogPrintf (LOG_CRITICAL, "%s: Call to XLALDopplerCoordinateNames2System() failed. errno = %d\n\n", __func__, xlalErrno );
    XLAL_ERROR ( XLAL_EFUNC );
  }

  /* ---------- record full 'history' up to and including this application ---------- */
  {
    CHAR *cmdline = NULL;
    CHAR *tmp;
    size_t len = strlen ( app_name ) + 1;

    if ( (cfg->history = XLALCalloc ( 1, sizeof(*cfg->history))) == NULL ) {
      LogPrintf (LOG_CRITICAL, "%s: XLALCalloc(1,%zu) failed.\n\n", __func__, sizeof(*cfg->history));
      XLAL_ERROR ( XLAL_ENOMEM );
    }

    if ( (tmp = XLALMalloc ( len )) == NULL ) {
      LogPrintf (LOG_CRITICAL, "%s: XLALMalloc (%zu) failed.\n\n", __func__, len );
      XLAL_ERROR ( XLAL_ENOMEM );
    }
    strcpy ( tmp, app_name );
    cfg->history->app_name = tmp;

    /* get commandline describing search*/
    if ( (cmdline = XLALUserVarGetLog ( UVAR_LOGFMT_CMDLINE )) == NULL ) {
      LogPrintf (LOG_CRITICAL, "%s: XLALUserVarGetLog() failed with xlalErrno = %d.\n\n", __func__, xlalErrno );
      XLAL_ERROR ( XLAL_EFUNC );
    }
    cfg->history->cmdline = cmdline;
  } /* record history */


  return XLAL_SUCCESS;

} /* XLALInitCode() */
Ejemplo n.º 3
0
/**
 * basic initializations: deal with user input and return standardized 'ConfigVariables'
 */
int
XLALInitCode ( ConfigVariables *cfg, const UserVariables_t *uvar, const char *app_name)
{
  XLAL_CHECK ( cfg && uvar && app_name, XLAL_EINVAL, "Illegal NULL pointer input." );

  /* init ephemeris data */
  XLAL_CHECK ( ( cfg->edat = XLALInitBarycenter( uvar->ephemEarth, uvar->ephemSun ) ) != NULL, XLAL_EFUNC, "XLALInitBarycenter failed: could not load Earth ephemeris '%s' and Sun ephemeris '%s.", uvar->ephemEarth, uvar->ephemSun);

  cfg->numDetectors = uvar->IFOs->length;

  cfg->numTimeStamps = 0;
  XLAL_CHECK ( (cfg->numTimeStampsX = XLALCreateUINT4Vector ( cfg->numDetectors )) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector(%d) failed.", cfg->numDetectors );

  BOOLEAN haveTimeGPS = XLALUserVarWasSet( &uvar->timeGPS );
  BOOLEAN haveTimeStampsFile = XLALUserVarWasSet( &uvar->timeStampsFile );
  BOOLEAN haveTimeStampsFiles = XLALUserVarWasSet( &uvar->timeStampsFiles );

  XLAL_CHECK ( !(haveTimeStampsFiles && haveTimeStampsFile), XLAL_EINVAL, "Can't handle both timeStampsFiles and (deprecated) haveTimeStampsFiles input options." );
  XLAL_CHECK ( !(haveTimeGPS && haveTimeStampsFile), XLAL_EINVAL, "Can't handle both (deprecated) timeStampsFile and timeGPS input options." );
  XLAL_CHECK ( !(haveTimeGPS && haveTimeStampsFiles), XLAL_EINVAL, "Can't handle both timeStampsFiles and timeGPS input options." );
  XLAL_CHECK ( haveTimeGPS || haveTimeStampsFiles || haveTimeStampsFile, XLAL_EINVAL, "Need either timeStampsFiles or timeGPS input option." );
  if ( haveTimeStampsFiles ) {
    XLAL_CHECK ( (uvar->timeStampsFiles->length == 1 ) || ( uvar->timeStampsFiles->length == cfg->numDetectors ), XLAL_EINVAL, "Length of timeStampsFiles list is neither 1 (one file for all detectors) nor does it match the number of detectors. (%d != %d)", uvar->timeStampsFiles->length, cfg->numDetectors );
    XLAL_CHECK ( (uvar->timeStampsFiles->length == 1 ) || !uvar->outab, XLAL_EINVAL, "At the moment, can't produce a(t), b(t) output (--outab) when given per-IFO --timeStampsFiles.");
  }

  if ( haveTimeStampsFiles && ( uvar->timeStampsFiles->length == cfg->numDetectors ) ) {

    XLAL_CHECK ( ( cfg->multiTimestamps = XLALReadMultiTimestampsFiles ( uvar->timeStampsFiles ) ) != NULL, XLAL_EFUNC );

    XLAL_CHECK ( (cfg->multiTimestamps->length > 0) && (cfg->multiTimestamps->data != NULL), XLAL_EINVAL, "Got empty timestamps-list from '%s'.", uvar->timeStampsFiles );

  }

  else {

    /* prepare multiTimestamps structure */
    UINT4 nTS = 0;
    XLAL_CHECK ( ( cfg->multiTimestamps = XLALCalloc ( 1, sizeof(*cfg->multiTimestamps))) != NULL, XLAL_ENOMEM, "Allocating multiTimestamps failed." );
    XLAL_CHECK ( ( cfg->multiTimestamps->data = XLALCalloc ( cfg->numDetectors, sizeof(cfg->multiTimestamps->data) )) != NULL, XLAL_ENOMEM, "Allocating multiTimestamps->data failed." );
    cfg->multiTimestamps->length = cfg->numDetectors;

    if ( haveTimeGPS ) { /* set up timestamps vector from timeGPS, use same for all IFOs */

      nTS = uvar->timeGPS->length;
      XLAL_CHECK ( (cfg->multiTimestamps->data[0] = XLALCreateTimestampVector ( nTS ) ) != NULL, XLAL_EFUNC, "XLALCreateTimestampVector( %d ) failed.",  nTS );

      /* convert input REAL8 times into LIGOTimeGPS for first detector */
      for (UINT4 t = 0; t < nTS; t++) {
        REAL8 temp_real8_timestamp = 0;
        XLAL_CHECK ( 1 == sscanf ( uvar->timeGPS->data[t], "%" LAL_REAL8_FORMAT, &temp_real8_timestamp ), XLAL_EINVAL, "Illegal REAL8 commandline argument to --timeGPS[%d]: '%s'", t, uvar->timeGPS->data[t] );
        XLAL_CHECK ( XLALGPSSetREAL8( &cfg->multiTimestamps->data[0]->data[t], temp_real8_timestamp ) != NULL, XLAL_EFUNC, "Failed to convert input GPS %g into LIGOTimeGPS", temp_real8_timestamp );
       } // for (UINT4 t = 0; t < nTS; t++)

    } // if ( haveTimeGPS )

    else { // haveTimeStampsFiles || haveTimeStampsFile

     CHAR *singleTimeStampsFile = NULL;
     if ( haveTimeStampsFiles ) {
      singleTimeStampsFile = uvar->timeStampsFiles->data[0];
     }
     else if ( haveTimeStampsFile ) {
      singleTimeStampsFile = uvar->timeStampsFile;
     }

     XLAL_CHECK ( ( cfg->multiTimestamps->data[0] = XLALReadTimestampsFile ( singleTimeStampsFile ) ) != NULL, XLAL_EFUNC );
     nTS = cfg->multiTimestamps->data[0]->length;

    } // else: haveTimeStampsFiles || haveTimeStampsFile

    /* copy timestamps from first detector to all others */
    if ( cfg->numDetectors > 1 ) {
      for ( UINT4 X=1; X < cfg->numDetectors; X++ ) {
        XLAL_CHECK ( (cfg->multiTimestamps->data[X] = XLALCreateTimestampVector ( nTS ) ) != NULL, XLAL_EFUNC, "XLALCreateTimestampVector( %d ) failed.", nTS );
        for (UINT4 t = 0; t < nTS; t++) {
          cfg->multiTimestamps->data[X]->data[t].gpsSeconds = cfg->multiTimestamps->data[0]->data[t].gpsSeconds;
          cfg->multiTimestamps->data[X]->data[t].gpsNanoSeconds = cfg->multiTimestamps->data[0]->data[t].gpsNanoSeconds;
        } // for (UINT4 t = 0; t < nTS; t++)
      } // for ( UINT4 X=1; X < cfg->numDetectors X++ )
    } // if ( cfg->numDetectors > 1 )

  } // if !( haveTimeStampsFiles && ( uvar->timeStampsFiles->length == cfg->numDetectors ) )

  for ( UINT4 X=0; X < cfg->numDetectors; X++ ) {
    cfg->numTimeStampsX->data[X] = cfg->multiTimestamps->data[X]->length;
    cfg->numTimeStamps += cfg->numTimeStampsX->data[X];
  }

  /* convert detector names into site-info */
  MultiLALDetector multiDet;
  XLAL_CHECK ( XLALParseMultiLALDetector ( &multiDet, uvar->IFOs ) == XLAL_SUCCESS, XLAL_EFUNC );

  /* get detector states */
  XLAL_CHECK ( (cfg->multiDetStates = XLALGetMultiDetectorStates ( cfg->multiTimestamps, &multiDet, cfg->edat, 0.5 * uvar->Tsft )) != NULL, XLAL_EFUNC, "XLALGetDetectorStates() failed." );

  BOOLEAN haveAlphaDelta = ( XLALUserVarWasSet(&uvar->Alpha) && XLALUserVarWasSet(&uvar->Delta) );
  BOOLEAN haveSkyGrid = XLALUserVarWasSet( &uvar->skyGridFile );

  XLAL_CHECK ( !(haveAlphaDelta && haveSkyGrid), XLAL_EINVAL, "Can't handle both Alpha/Delta and skyGridFile input options." );
  XLAL_CHECK ( haveAlphaDelta || haveSkyGrid, XLAL_EINVAL, "Need either Alpha/Delta or skyGridFile input option." );

  if (haveAlphaDelta) { /* parse this into one-element Alpha, Delta vectors */
    XLAL_CHECK ( (cfg->Alpha = XLALCreateREAL8Vector ( 1 )) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector(1) failed." );
    cfg->Alpha->data[0] = uvar->Alpha;
    XLAL_CHECK ( (cfg->Delta = XLALCreateREAL8Vector ( 1 )) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector(1) failed." );
    cfg->Delta->data[0] = uvar->Delta;
    cfg->numSkyPoints = 1;
  } // if (haveAlphaDelta)

  else if ( haveSkyGrid ) {
    LALParsedDataFile *data = NULL;
    XLAL_CHECK ( XLALParseDataFile (&data, uvar->skyGridFile) == XLAL_SUCCESS, XLAL_EFUNC, "Failed to parse data file '%s'.", uvar->skyGridFile );
    cfg->numSkyPoints = data->lines->nTokens;
    XLAL_CHECK ( (cfg->Alpha = XLALCreateREAL8Vector ( cfg->numSkyPoints )) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector( %d ) failed.", cfg->numSkyPoints  );
    XLAL_CHECK ( (cfg->Delta = XLALCreateREAL8Vector ( cfg->numSkyPoints )) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector( %d ) failed.", cfg->numSkyPoints  );
    for (UINT4 n=0; n < cfg->numSkyPoints; n++) {
      XLAL_CHECK ( 2 == sscanf( data->lines->tokens[n], "%" LAL_REAL8_FORMAT "%" LAL_REAL8_FORMAT, &cfg->Alpha->data[n], &cfg->Delta->data[n] ), XLAL_EDATA, "Could not parse 2 numbers from line %d in candidate-file '%s':\n'%s'", n, uvar->skyGridFile, data->lines->tokens[n] );
    } // for (UINT4 n=0; n < cfg->numSkyPoints; n++)
    XLALDestroyParsedDataFile ( data );
  } // else if ( haveSkyGrid )

  if ( uvar->noiseSqrtShX ) { /* translate user-input PSD sqrt(SX) to noise-weights (this actually does not care whether they were normalized or not) */

    if (  uvar->noiseSqrtShX->length != cfg->numDetectors ) {
      fprintf(stderr, "Length of noiseSqrtShX vector does not match number of detectors! (%d != %d)\n", uvar->noiseSqrtShX->length, cfg->numDetectors);
      XLAL_ERROR ( XLAL_EINVAL );
    }
    REAL8Vector *noiseSqrtShX = NULL;
    if ( (noiseSqrtShX = XLALCreateREAL8Vector ( cfg->numDetectors )) == NULL ) {
      fprintf(stderr, "Failed call to XLALCreateREAL8Vector( %d )\n", cfg->numDetectors );
      XLAL_ERROR ( XLAL_EFUNC );
    }

    REAL8 psd_normalization = 0;

    for (UINT4 X = 0; X < cfg->numDetectors; X++) {

      if ( 1 != sscanf ( uvar->noiseSqrtShX->data[X], "%" LAL_REAL8_FORMAT, &noiseSqrtShX->data[X] ) ) {
        fprintf(stderr, "Illegal REAL8 commandline argument to --noiseSqrtShX[%d]: '%s'\n", X, uvar->noiseSqrtShX->data[X]);
        XLAL_ERROR ( XLAL_EINVAL );
      }

      if ( noiseSqrtShX->data[X] <= 0.0 ) {
        fprintf(stderr, "Non-positive input PSD ratio for detector X=%d: noiseSqrtShX[X]=%f\n", X, noiseSqrtShX->data[X] );
        XLAL_ERROR ( XLAL_EINVAL );
      }

      psd_normalization += 1.0/SQ(noiseSqrtShX->data[X]);

    } /* for X < cfg->numDetectors */

    psd_normalization = (REAL8)cfg->numDetectors/psd_normalization; /* S = NSFT / sum S_Xalpha^-1, no per-SFT variation here -> S = Ndet / sum S_X^-1 */

    /* create multi noise weights */
    if ( (cfg->multiNoiseWeights = XLALCalloc(1, sizeof(*cfg->multiNoiseWeights))) == NULL ) {
     XLALPrintError ("%s: failed to XLALCalloc ( 1, %d )\n", __func__, sizeof(*cfg->multiNoiseWeights) );
     XLAL_ERROR ( XLAL_ENOMEM );
    }
    if ( (cfg->multiNoiseWeights->data = XLALCalloc(cfg->numDetectors, sizeof(*cfg->multiNoiseWeights->data))) == NULL ) {
     XLALPrintError ("%s: failed to XLALCalloc ( %d, %d )\n", __func__, cfg->numDetectors, sizeof(*cfg->multiNoiseWeights->data) );
     XLAL_ERROR ( XLAL_ENOMEM );
    }
    cfg->multiNoiseWeights->length = cfg->numDetectors;

    for (UINT4 X = 0; X < cfg->numDetectors; X++) {

      REAL8 noise_weight_X = psd_normalization/SQ(noiseSqrtShX->data[X]); /* w_Xalpha = S_Xalpha^-1/S^-1 = S / S_Xalpha */

      /* create k^th weights vector */
      if( ( cfg->multiNoiseWeights->data[X] = XLALCreateREAL8Vector ( cfg->numTimeStampsX->data[X] ) ) == NULL )
        {
          /* free weights vectors created previously in loop */
          XLALDestroyMultiNoiseWeights ( cfg->multiNoiseWeights );
          XLAL_ERROR ( XLAL_EFUNC, "Failed to allocate noiseweights for IFO X = %d\n", X );
        } /* if XLALCreateREAL8Vector() failed */

      /* loop over rngmeds and calculate weights -- one for each sft */
      for ( UINT4 alpha = 0; alpha < cfg->numTimeStampsX->data[X]; alpha++) {
        cfg->multiNoiseWeights->data[X]->data[alpha] = noise_weight_X;
      }

    } /* for X < cfg->numDetectors */

    XLALDestroyREAL8Vector ( noiseSqrtShX );

  } /* if ( uvar->noiseSqrtShX ) */

  else {
    cfg->multiNoiseWeights =  NULL;
  }

  return XLAL_SUCCESS;

} /* XLALInitCode() */
Ejemplo n.º 4
0
/**
 * Handle user-input and set up shop accordingly, and do all
 * consistency-checks on user-input.
 */
int
XLALInitMakefakedata ( ConfigVars_t *cfg, UserVariables_t *uvar )
{
  XLAL_CHECK ( cfg != NULL, XLAL_EINVAL, "Invalid NULL input 'cfg'\n" );
  XLAL_CHECK ( uvar != NULL, XLAL_EINVAL, "Invalid NULL input 'uvar'\n");

  cfg->VCSInfoString = XLALGetVersionString(0);
  XLAL_CHECK ( cfg->VCSInfoString != NULL, XLAL_EFUNC, "XLALGetVersionString(0) failed.\n" );

  // version info was requested: output then exit
  if ( uvar->version )
    {
      printf ("%s\n", cfg->VCSInfoString );
      exit (0);
    }

  /* if requested, log all user-input and code-versions */
  if ( uvar->logfile ) {
    XLAL_CHECK ( XLALWriteMFDlog ( uvar->logfile, cfg ) == XLAL_SUCCESS, XLAL_EFUNC, "XLALWriteMFDlog() failed with xlalErrno = %d\n", xlalErrno );
  }

  /* Init ephemerides */
  XLAL_CHECK ( (cfg->edat = XLALInitBarycenter ( uvar->ephemEarth, uvar->ephemSun )) != NULL, XLAL_EFUNC );

  /* check for negative fMin and Band, which would break the fMin_eff, fBand_eff calculation below */
  XLAL_CHECK ( uvar->fmin >= 0, XLAL_EDOM, "Invalid negative frequency fMin=%f!\n\n", uvar->fmin );
  XLAL_CHECK ( uvar->Band > 0, XLAL_EDOM, "Invalid non-positive frequency band Band=%f!\n\n", uvar->Band );

  // ---------- check user-input consistency ----------

  // ----- check if frames + frame channels given
  BOOLEAN have_frames  = (uvar->inFrames != NULL);
  BOOLEAN have_channels= (uvar->inFrChannels != NULL);
  XLAL_CHECK ( !(have_frames || have_channels) || (have_frames && have_channels), XLAL_EINVAL, "Need both --inFrames and --inFrChannels, or NONE\n");

  // ----- IFOs : only from one of {--IFOs, --noiseSFTs, --inFrChannels}: mutually exclusive
  BOOLEAN have_IFOs      = (uvar->IFOs != NULL);
  BOOLEAN have_noiseSFTs = (uvar->noiseSFTs != NULL);
  XLAL_CHECK ( have_frames || have_IFOs || have_noiseSFTs, XLAL_EINVAL, "Need one of --IFOs, --noiseSFTs or --inFrChannels to determine detectors\n");

  if ( have_frames ) {
    XLAL_CHECK ( !have_IFOs && !have_noiseSFTs, XLAL_EINVAL, "If --inFrames given, cannot handle --IFOs or --noiseSFTs input\n");
    XLAL_CHECK ( XLALParseMultiLALDetector ( &(cfg->multiIFO), uvar->inFrChannels ) == XLAL_SUCCESS, XLAL_EFUNC );
  } else { // !have_frames
    XLAL_CHECK ( !(have_IFOs && have_noiseSFTs), XLAL_EINVAL, "Cannot handle both --IFOs and --noiseSFTs input\n");
  }
  if ( have_IFOs ) {
    XLAL_CHECK ( XLALParseMultiLALDetector ( &(cfg->multiIFO), uvar->IFOs ) == XLAL_SUCCESS, XLAL_EFUNC );
  }

  // ----- TIMESTAMPS: either from --timestampsFiles, --startTime+duration, or --noiseSFTs
  BOOLEAN have_startTime = XLALUserVarWasSet ( &uvar->startTime );
  BOOLEAN have_duration = XLALUserVarWasSet ( &uvar->duration );
  BOOLEAN have_timestampsFiles = ( uvar->timestampsFiles != NULL );
  // need BOTH startTime+duration or none
  XLAL_CHECK ( ( have_duration && have_startTime) || !( have_duration || have_startTime ), XLAL_EINVAL, "Need BOTH {--startTime,--duration} or NONE\n");
  // at least one of {startTime,timestamps,noiseSFTs,inFrames} required
  XLAL_CHECK ( have_timestampsFiles || have_startTime || have_noiseSFTs || have_frames, XLAL_EINVAL, "Need at least one of {--timestampsFiles, --startTime+duration, --noiseSFTs, --inFrames}\n" );
  // don't allow timestamps + {startTime+duration OR noiseSFTs}
  XLAL_CHECK ( !have_timestampsFiles || !(have_startTime||have_noiseSFTs), XLAL_EINVAL, "--timestampsFiles incompatible with {--noiseSFTs or --startTime+duration}\n");
  // note, however, that we DO allow --noiseSFTs and --startTime+duration, which will act as a constraint
  // on the noise-SFTs to load in

  // don't allow --SFToverlap with either --noiseSFTs OR --timestampsFiles
  XLAL_CHECK ( uvar->SFToverlap >= 0, XLAL_EDOM );
  BOOLEAN haveOverlap = ( uvar->SFToverlap > 0 );
  XLAL_CHECK ( !haveOverlap || !( have_noiseSFTs || have_timestampsFiles ), XLAL_EINVAL, "--SFToverlap incompatible with {--noiseSFTs or --timestampsFiles}\n" );

  // now handle the 3 mutually-exclusive cases: have_noiseSFTs || have_timestampsFiles || have_startTime (only)
  if ( have_noiseSFTs )
    {
      SFTConstraints XLAL_INIT_DECL(constraints);
      if ( have_startTime && have_duration )	 // use optional (startTime+duration) as constraints,
        {
          LIGOTimeGPS minStartTime, maxStartTime;
          minStartTime = uvar->startTime;
          maxStartTime = uvar->startTime;
          XLALGPSAdd ( &maxStartTime, uvar->duration );
          constraints.minStartTime = &minStartTime;
          constraints.maxStartTime = &maxStartTime;
          char bufGPS1[32], bufGPS2[32];
          XLALPrintWarning ( "Only noise-SFTs between GPS [%s, %s] will be used!\n", XLALGPSToStr(bufGPS1, &minStartTime), XLALGPSToStr(bufGPS2, &maxStartTime) );
        } /* if start+duration given */
      XLAL_CHECK ( (cfg->noiseCatalog = XLALSFTdataFind ( uvar->noiseSFTs, &constraints )) != NULL, XLAL_EFUNC );
      XLAL_CHECK (  cfg->noiseCatalog->length > 0, XLAL_EINVAL, "No noise-SFTs matching (start+duration, timestamps) were found!\n" );
      XLAL_CHECK ( (cfg->multiNoiseCatalogView = XLALGetMultiSFTCatalogView ( cfg->noiseCatalog )) != NULL, XLAL_EFUNC );

      // extract multi-timestamps from the multi-SFT-catalog view
      XLAL_CHECK ( (cfg->multiTimestamps = XLALTimestampsFromMultiSFTCatalogView ( cfg->multiNoiseCatalogView )) != NULL, XLAL_EFUNC );
      // extract IFOs from multi-SFT catalog
      XLAL_CHECK ( XLALMultiLALDetectorFromMultiSFTCatalogView ( &(cfg->multiIFO), cfg->multiNoiseCatalogView ) == XLAL_SUCCESS, XLAL_EFUNC );

    } // endif have_noiseSFTs
  else if ( have_timestampsFiles )
    {
      XLAL_CHECK ( (cfg->multiTimestamps = XLALReadMultiTimestampsFiles ( uvar->timestampsFiles )) != NULL, XLAL_EFUNC );

      XLAL_CHECK ( (cfg->multiTimestamps->length > 0) && (cfg->multiTimestamps->data != NULL), XLAL_EINVAL, "Got empty timestamps-list from XLALReadMultiTimestampsFiles()\n" );

      for ( UINT4 X=0; X < cfg->multiTimestamps->length; X ++ ) {
        cfg->multiTimestamps->data[X]->deltaT = uvar->Tsft;	// Tsft information not given by timestamps-file
      }
    } // endif have_timestampsFiles
  else if ( have_startTime && have_duration )
    {
      XLAL_CHECK ( ( cfg->multiTimestamps = XLALMakeMultiTimestamps ( uvar->startTime, uvar->duration, uvar->Tsft, uvar->SFToverlap, cfg->multiIFO.length )) != NULL, XLAL_EFUNC );
    } // endif have_startTime

  // check if the user asked for Gaussian white noise to be produced (sqrtSn[X]!=0), otherwise leave noise-floors at 0
  if ( uvar->sqrtSX != NULL ) {
    XLAL_CHECK ( XLALParseMultiNoiseFloor ( &(cfg->multiNoiseFloor), uvar->sqrtSX, cfg->multiIFO.length ) == XLAL_SUCCESS, XLAL_EFUNC );
  } else {
    cfg->multiNoiseFloor.length = cfg->multiIFO.length;
    // values remain at their default sqrtSn[X] = 0;
  }

#ifdef HAVE_LIBLALFRAME
  // if user requested time-series data from frames to be added: try to read the frames now
  if ( have_frames )
    {
      UINT4 numDetectors = uvar->inFrChannels->length;
      XLAL_CHECK ( uvar->inFrames->length == numDetectors, XLAL_EINVAL, "Need equal number of channel names (%d) as frame specifications (%d)\n", uvar->inFrChannels->length, numDetectors );

      XLAL_CHECK ( (cfg->inputMultiTS = XLALCalloc ( 1, sizeof(*cfg->inputMultiTS))) != NULL, XLAL_ENOMEM );
      cfg->inputMultiTS->length = numDetectors;
      XLAL_CHECK ( (cfg->inputMultiTS->data = XLALCalloc ( numDetectors, sizeof(cfg->inputMultiTS->data[0]) )) != NULL, XLAL_ENOMEM );
      if ( cfg->multiTimestamps == NULL )
        {
          XLAL_CHECK ( (cfg->multiTimestamps = XLALCalloc ( 1, sizeof(*cfg->multiTimestamps) )) != NULL, XLAL_ENOMEM );
          XLAL_CHECK ( (cfg->multiTimestamps->data = XLALCalloc ( numDetectors, sizeof(cfg->multiTimestamps->data[0]))) != NULL, XLAL_ENOMEM );
          cfg->multiTimestamps->length = numDetectors;
        }
      for ( UINT4 X = 0; X < numDetectors; X ++ )
        {
          LALCache *cache;
          XLAL_CHECK ( (cache = XLALCacheImport ( uvar->inFrames->data[X] )) != NULL, XLAL_EFUNC, "Failed to import cache file '%s'\n", uvar->inFrames->data[X] );
          // this is a sorted cache, so extract its time-range:
          REAL8 cache_tStart = cache->list[0].t0;
          REAL8 cache_tEnd   = cache->list[cache->length-1].t0 + cache->list[cache->length-1].dt;
          REAL8 cache_duration = (cache_tEnd - cache_tStart);
          LIGOTimeGPS ts_start;
          REAL8 ts_duration;
          // check that it's consistent with timestamps, if given, otherwise create timestamps from this
          if ( cfg->multiTimestamps->data[X] != NULL )	// FIXME: implicitly assumes timestamps are sorted, which is not guaranteed by timestamps-reading from file
            {
              const LIGOTimeGPSVector *timestampsX = cfg->multiTimestamps->data[X];
              REAL8 tStart = XLALGPSGetREAL8( &timestampsX->data[0] );
              REAL8 tEnd   = XLALGPSGetREAL8( &timestampsX->data[timestampsX->length-1]) + timestampsX->deltaT;
              XLAL_CHECK ( tStart >= cache_tStart && tEnd <= cache_tEnd, XLAL_EINVAL, "Detector X=%d: Requested timestamps-range [%.0f, %.0f]s outside of cache range [%.0f,%.0f]s\n",
                           X, tStart, tEnd, cache_tStart, cache_tEnd );
              XLALGPSSetREAL8 ( &ts_start, tStart );
              ts_duration = (tEnd - tStart);
            }
          else
            {
              XLALGPSSetREAL8 ( &ts_start, (REAL8)cache_tStart + 1); // cache times can apparently be by rounded up or down by 1s, so shift by 1s to be safe
              ts_duration = cache_duration - 1;
              XLAL_CHECK ( (cfg->multiTimestamps->data[X] = XLALMakeTimestamps ( ts_start, ts_duration, uvar->Tsft, uvar->SFToverlap ) ) != NULL, XLAL_EFUNC );
            }
          // ----- now open frame stream and read *all* the data within this time-range [FIXME] ----------
          LALFrStream *stream;
          XLAL_CHECK ( (stream = XLALFrStreamCacheOpen ( cache )) != NULL, XLAL_EFUNC, "Failed to open stream from cache file '%s'\n", uvar->inFrames->data[X] );
          XLALDestroyCache ( cache );

          const char *channel = uvar->inFrChannels->data[X];
          size_t limit = 0;	// unlimited read
          REAL8TimeSeries *ts;
          XLAL_CHECK ( (ts = XLALFrStreamInputREAL8TimeSeries ( stream, channel, &ts_start, ts_duration, limit )) != NULL,
                       XLAL_EFUNC, "Frame reading failed for stream created for '%s': ts_start = {%d,%d}, duration=%.0f\n", uvar->inFrames->data[X], ts_start.gpsSeconds, ts_start.gpsNanoSeconds, ts_duration );
          cfg->inputMultiTS->data[X] = ts;

          XLAL_CHECK ( XLALFrStreamClose ( stream ) == XLAL_SUCCESS, XLAL_EFUNC, "Stream closing failed for cache file '%s'\n", uvar->inFrames->data[X] );
        } // for X < numDetectors
    } // if inFrames

  // if user requested timeseries *output* to frame files, handle deprecated options
  XLAL_CHECK ( !(uvar->TDDframedir && uvar->outFrameDir), XLAL_EINVAL, "Specify only ONE of {--TDDframedir or --outFrameDir} or NONE\n");
  if ( uvar->TDDframedir ) {
    cfg->outFrameDir = uvar->TDDframedir;
  } else if ( uvar->outFrameDir ) {
    cfg->outFrameDir = uvar->outFrameDir;
  }
#endif

  return XLAL_SUCCESS;

} /* XLALInitMakefakedata() */
/**
 * Unit test for metric functions XLALComputeDopplerPhaseMetric()
 * and XLALComputeDopplerFstatMetric()
 *
 * Initially modelled afer testMetricCodes.py script:
 * Check metric codes 'getMetric' 'FstatMetric' and 'FstatMetric_v2' by
 * comparing them against each other.
 * Given that they represent 3 very different implementations of
 * metric calculations, this provides a very powerful consistency test
 *
 */
static int
test_XLALComputeDopplerMetrics ( void )
{
  int ret;
  const REAL8 tolPh = 0.01;	// 1% tolerance on phase metrics [taken from testMetricCodes.py]

  // ----- load ephemeris
  const char earthEphem[] = TEST_DATA_DIR "earth00-19-DE200.dat.gz";
  const char sunEphem[]   = TEST_DATA_DIR "sun00-19-DE200.dat.gz";
  EphemerisData *edat = XLALInitBarycenter ( earthEphem, sunEphem );
  XLAL_CHECK ( edat != NULL, XLAL_EFUNC, "XLALInitBarycenter('%s','%s') failed with xlalErrno = %d\n", earthEphem, sunEphem, xlalErrno );

  // ----- set test-parameters ----------
  const LIGOTimeGPS startTimeGPS = { 792576013, 0 };
  const REAL8 Tseg = 60000;

  const REAL8 Alpha = 1.0;
  const REAL8 Delta = 0.5;
  const REAL8 Freq  = 100;
  const REAL8 f1dot = 0;// -1e-8;

  LALStringVector *detNames = XLALCreateStringVector ( "H1", "L1", "V1",  NULL );
  LALStringVector *sqrtSX   = XLALCreateStringVector ( "1.0", "0.5", "1.5", NULL );

  MultiLALDetector multiIFO;
  XLAL_CHECK ( XLALParseMultiLALDetector ( &multiIFO, detNames ) == XLAL_SUCCESS, XLAL_EFUNC );
  XLALDestroyStringVector ( detNames );

  MultiNoiseFloor multiNoiseFloor;
  XLAL_CHECK ( XLALParseMultiNoiseFloor ( &multiNoiseFloor, sqrtSX, multiIFO.length ) == XLAL_SUCCESS, XLAL_EFUNC );
  XLALDestroyStringVector ( sqrtSX );

  // prepare metric parameters for modern XLALComputeDopplerFstatMetric() and mid-old XLALOldDopplerFstatMetric()
  const DopplerCoordinateSystem coordSys = { 4, { DOPPLERCOORD_FREQ, DOPPLERCOORD_ALPHA, DOPPLERCOORD_DELTA, DOPPLERCOORD_F1DOT } };
  const PulsarAmplitudeParams Amp = { 0.03, -0.3, 0.5, 0.0 };	// h0, cosi, psi, phi0
  const PulsarDopplerParams dop = {
    .refTime  = startTimeGPS,
    .Alpha    = Alpha,
    .Delta    = Delta,
    .fkdot    = { Freq, f1dot },
  };

  LALSegList XLAL_INIT_DECL(segList);
  ret = XLALSegListInitSimpleSegments ( &segList, startTimeGPS, 1, Tseg );
  XLAL_CHECK ( ret == XLAL_SUCCESS, XLAL_EFUNC, "XLALSegListInitSimpleSegments() failed with xlalErrno = %d\n", xlalErrno );

  const DopplerMetricParams master_pars2 = {
    .coordSys			= coordSys,
    .detMotionType		= DETMOTION_SPIN | DETMOTION_ORBIT,
    .segmentList		= segList,
    .multiIFO			= multiIFO,
    .multiNoiseFloor		= multiNoiseFloor,
    .signalParams		= { .Amp = Amp, .Doppler = dop },
    .projectCoord		= - 1,	// -1==no projection
    .approxPhase		= 0,
  };


  // ========== BEGINNING OF TEST CALLS ==========


  XLALPrintWarning("\n---------- ROUND 1: ephemeris-based, single-IFO phase metrics ----------\n");
  {
    OldDopplerMetric *metric1;
    DopplerPhaseMetric *metric2P;
    REAL8 diff_2_1;

    DopplerMetricParams pars2 = master_pars2;

    pars2.multiIFO.length = 1;	// truncate to first detector
    pars2.multiNoiseFloor.length = 1;	// truncate to first detector

    // 1) compute metric using old FstatMetric code, now wrapped into XLALOldDopplerFstatMetric()
    XLAL_CHECK ( (metric1 = XLALOldDopplerFstatMetric ( OLDMETRIC_TYPE_PHASE, &pars2, edat )) != NULL, XLAL_EFUNC );
    // 2) compute metric using modern UniversalDopplerMetric module: (used in lalapps_FstatMetric_v2)
    XLAL_CHECK ( (metric2P = XLALComputeDopplerPhaseMetric ( &pars2, edat )) != NULL, XLAL_EFUNC );

    // compare metrics against each other:
    XLAL_CHECK ( (diff_2_1 = XLALCompareMetrics ( metric2P->g_ij, metric1->g_ij )) < tolPh, XLAL_ETOL, "Error(g2,g1)= %g exceeds tolerance of %g\n", diff_2_1, tolPh );
    XLALPrintWarning ("diff_2_1 = %e\n", diff_2_1 );

    XLALDestroyOldDopplerMetric ( metric1 );
    XLALDestroyDopplerPhaseMetric ( metric2P );
  }


  XLALPrintWarning("\n---------- ROUND 2: Ptolemaic-based, single-IFO phase metrics ----------\n");
  {
    OldDopplerMetric *metric1;
    DopplerPhaseMetric *metric2P;
    REAL8 diff_2_1;

    DopplerMetricParams pars2 = master_pars2;

    pars2.multiIFO.length = 1;	// truncate to first detector
    pars2.multiNoiseFloor.length = 1;	// truncate to first detector

    pars2.detMotionType = DETMOTION_SPIN | DETMOTION_PTOLEORBIT;

    // 1) compute metric using old FstatMetric code, now wrapped into XLALOldDopplerFstatMetric()
    XLAL_CHECK ( (metric1 = XLALOldDopplerFstatMetric ( OLDMETRIC_TYPE_PHASE, &pars2, edat )) != NULL, XLAL_EFUNC );
    // 2) compute metric using modern UniversalDopplerMetric module: (used in lalapps_FstatMetric_v2)
    XLAL_CHECK ( (metric2P = XLALComputeDopplerPhaseMetric ( &pars2, edat )) != NULL, XLAL_EFUNC );

    // compare all 3 metrics against each other:
    XLAL_CHECK ( (diff_2_1 = XLALCompareMetrics ( metric2P->g_ij, metric1->g_ij )) < tolPh, XLAL_ETOL, "Error(g2,g1)= %g exceeds tolerance of %g\n", diff_2_1, tolPh );
    XLALPrintWarning ("diff_2_1 = %e\n", diff_2_1 );

    XLALDestroyOldDopplerMetric ( metric1 );
    XLALDestroyDopplerPhaseMetric ( metric2P );
  }


  XLALPrintWarning("\n---------- ROUND 3: ephemeris-based, multi-IFO F-stat metrics ----------\n");
  {
    OldDopplerMetric *metric1;
    DopplerFstatMetric *metric2F;
    REAL8 diff_2_1;

    DopplerMetricParams pars2 = master_pars2;

    pars2.detMotionType = DETMOTION_SPIN | DETMOTION_ORBIT;
    pars2.multiIFO      = multiIFO;	// 3 IFOs
    pars2.multiNoiseFloor = multiNoiseFloor;// 3 IFOs

    // 1) compute metric using old FstatMetric code, now wrapped into XLALOldDopplerFstatMetric()
    XLAL_CHECK ( (metric1 = XLALOldDopplerFstatMetric ( OLDMETRIC_TYPE_FSTAT, &pars2, edat )) != NULL, XLAL_EFUNC );
    // 2) compute metric using modern UniversalDopplerMetric module: (used in lalapps_FstatMetric_v2)
    XLAL_CHECK ( (metric2F = XLALComputeDopplerFstatMetric ( &pars2, edat )) != NULL, XLAL_EFUNC );

    // compare both metrics against each other:
    XLAL_CHECK ( (diff_2_1 = XLALCompareMetrics ( metric2F->gF_ij,   metric1->gF_ij ))   < tolPh, XLAL_ETOL, "Error(gF2,gF1)= %e exceeds tolerance of %e\n", diff_2_1, tolPh );
    XLALPrintWarning ("gF:   diff_2_1 = %e\n", diff_2_1 );
    XLAL_CHECK ( (diff_2_1 = XLALCompareMetrics ( metric2F->gFav_ij, metric1->gFav_ij )) < tolPh, XLAL_ETOL, "Error(gFav2,gFav1)= %e exceeds tolerance of %e\n", diff_2_1, tolPh );
    XLALPrintWarning ("gFav: diff_2_1 = %e\n", diff_2_1 );

    XLALDestroyOldDopplerMetric ( metric1 );
    XLALDestroyDopplerFstatMetric ( metric2F );
  }


  XLALPrintWarning("\n---------- ROUND 4: compare analytic {f,f1dot,f2dot,f3dot} phase metric vs XLALComputeDopplerPhaseMetric() ----------\n");
  {
    DopplerPhaseMetric *metric2P;
    REAL8 diff_2_1;

    DopplerMetricParams pars2 = master_pars2;

    pars2.multiIFO.length  = 1;	// truncate to 1st detector
    pars2.multiNoiseFloor.length  = 1;	// truncate to 1st detector
    pars2.detMotionType   = DETMOTION_SPIN | DETMOTION_ORBIT;
    pars2.approxPhase     = 1;	// use same phase-approximation as in analytic solution to improve comparison

    DopplerCoordinateSystem coordSys2 = { 4, { DOPPLERCOORD_FREQ, DOPPLERCOORD_F1DOT, DOPPLERCOORD_F2DOT, DOPPLERCOORD_F3DOT } };
    pars2.coordSys = coordSys2;
    gsl_matrix* gN_ij;

    // a) compute metric at refTime = startTime
    pars2.signalParams.Doppler.refTime = startTimeGPS;
    XLAL_CHECK ( (metric2P = XLALComputeDopplerPhaseMetric ( &pars2, edat )) != NULL, XLAL_EFUNC );
    gN_ij = NULL;
    XLAL_CHECK ( XLALNaturalizeMetric ( &gN_ij, NULL, metric2P->g_ij, &pars2 ) == XLAL_SUCCESS, XLAL_EFUNC );

    REAL8 gStart_ij[] = {   1.0/3,      2.0/3,    6.0/5,    32.0/15,      \
                            2.0/3,    64.0/45,    8.0/3,  512.0/105,      \
                            6.0/5,      8.0/3,   36.0/7,     48.0/5,      \
                            32.0/15,  512.0/105, 48.0/5, 4096.0/225 };
    const gsl_matrix_view gStart = gsl_matrix_view_array ( gStart_ij, 4, 4 );

    // compare natural-units metric against analytic solution
    XLAL_CHECK ( (diff_2_1 = XLALCompareMetrics ( gN_ij,   &(gStart.matrix) )) < tolPh, XLAL_ETOL,
                 "RefTime=StartTime: Error(g_ij,g_analytic)= %e exceeds tolerance of %e\n", diff_2_1, tolPh );
    XLALPrintWarning ("Analytic (refTime=startTime): diff_2_1 = %e\n", diff_2_1 );

    XLALDestroyDopplerPhaseMetric ( metric2P );
    gsl_matrix_free ( gN_ij );

    // b) compute metric at refTime = midTime
    pars2.signalParams.Doppler.refTime = startTimeGPS;
    pars2.signalParams.Doppler.refTime.gpsSeconds += Tseg / 2;

    XLAL_CHECK ( (metric2P = XLALComputeDopplerPhaseMetric ( &pars2, edat )) != NULL, XLAL_EFUNC );
    gN_ij = NULL;
    XLAL_CHECK ( XLALNaturalizeMetric ( &gN_ij, NULL, metric2P->g_ij, &pars2 ) == XLAL_SUCCESS, XLAL_EFUNC );

    REAL8 gMid_ij[] = { 1.0/3,    0,        1.0/5,         0,       \
                        0,        4.0/45,       0,   8.0/105,       \
                        1.0/5,    0,        1.0/7,         0,       \
                        0,        8.0/105,      0,  16.0/225  };
    const gsl_matrix_view gMid = gsl_matrix_view_array ( gMid_ij, 4, 4 );

    // compare natural-units metric against analytic solution
    XLAL_CHECK ( (diff_2_1 = XLALCompareMetrics ( gN_ij,   &(gMid.matrix) )) < tolPh, XLAL_ETOL,
                 "RefTime=MidTime: Error(g_ij,g_analytic)= %e exceeds tolerance of %e\n", diff_2_1, tolPh );
    XLALPrintWarning ("Analytic (refTime=midTime):   diff_2_1 = %e\n\n", diff_2_1 );

    XLALDestroyDopplerPhaseMetric ( metric2P );
    gsl_matrix_free ( gN_ij );
  }


  XLALPrintWarning("\n---------- ROUND 5: ephemeris-based, single-IFO, segment-averaged phase metrics ----------\n");
  {
    OldDopplerMetric *metric1;
    DopplerPhaseMetric *metric2P;
    REAL8 diff_2_1;

    DopplerMetricParams pars2 = master_pars2;

    pars2.detMotionType = DETMOTION_SPIN | DETMOTION_ORBIT;
    pars2.multiIFO.length = 1;	// truncate to first detector
    pars2.multiNoiseFloor.length = 1;	// truncate to first detector
    pars2.approxPhase = 1;

    const UINT4 Nseg = 10;
    LALSegList XLAL_INIT_DECL(NsegList);
    ret = XLALSegListInitSimpleSegments ( &NsegList, startTimeGPS, Nseg, Tseg );
    XLAL_CHECK ( ret == XLAL_SUCCESS, XLAL_EFUNC, "XLALSegListInitSimpleSegments() failed with xlalErrno = %d\n", xlalErrno );
    pars2.segmentList = NsegList;

    LALSegList XLAL_INIT_DECL(segList_k);
    LALSeg segment_k;
    XLALSegListInit( &segList_k );	// prepare single-segment list containing segment k
    segList_k.arraySize = 1;
    segList_k.length = 1;
    segList_k.segs = &segment_k;

    // 1) compute metric using old FstatMetric code, now wrapped into XLALOldDopplerFstatMetric()
    metric1 = NULL;
    for (UINT4 k = 0; k < Nseg; ++k) {
      // setup 1-segment segment-list pointing k-th segment
      DopplerMetricParams pars2_k = pars2;
      pars2_k.segmentList = segList_k;
      pars2_k.segmentList.segs[0] = pars2.segmentList.segs[k];
      // XLALOldDopplerFstatMetric() does not agree numerically with UniversalDopplerMetric when using refTime != startTime
      pars2_k.signalParams.Doppler.refTime = pars2_k.segmentList.segs[0].start;

      OldDopplerMetric *metric1_k;   // per-segment coherent metric
      XLAL_CHECK ( (metric1_k = XLALOldDopplerFstatMetric ( OLDMETRIC_TYPE_PHASE, &pars2_k, edat )) != NULL, XLAL_EFUNC );

      // manually correct reference time of metric1_k->g_ij; see Prix, "Frequency metric for CW searches" (2014-08-17), p. 4
      const double dt = XLALGPSDiff( &(pars2_k.signalParams.Doppler.refTime), &(pars2.signalParams.Doppler.refTime) );
      const double gFF = gsl_matrix_get( metric1_k->g_ij, 0, 0 );
      const double gFA = gsl_matrix_get( metric1_k->g_ij, 0, 1 );
      const double gFD = gsl_matrix_get( metric1_k->g_ij, 0, 2 );
      const double gFf = gsl_matrix_get( metric1_k->g_ij, 0, 3 );
      const double gAf = gsl_matrix_get( metric1_k->g_ij, 1, 3 );
      const double gDf = gsl_matrix_get( metric1_k->g_ij, 2, 3 );
      const double gff = gsl_matrix_get( metric1_k->g_ij, 3, 3 );
      gsl_matrix_set( metric1_k->g_ij, 0, 3, gFf + gFF*dt ); gsl_matrix_set( metric1_k->g_ij, 3, 0, gsl_matrix_get( metric1_k->g_ij, 0, 3 ) );
      gsl_matrix_set( metric1_k->g_ij, 1, 3, gAf + gFA*dt ); gsl_matrix_set( metric1_k->g_ij, 3, 1, gsl_matrix_get( metric1_k->g_ij, 1, 3 ) );
      gsl_matrix_set( metric1_k->g_ij, 2, 3, gDf + gFD*dt ); gsl_matrix_set( metric1_k->g_ij, 3, 2, gsl_matrix_get( metric1_k->g_ij, 2, 3 ) );
      gsl_matrix_set( metric1_k->g_ij, 3, 3, gff + 2*gFf*dt + gFF*dt*dt );

      XLAL_CHECK ( XLALAddOldDopplerMetric ( &metric1, metric1_k ) == XLAL_SUCCESS, XLAL_EFUNC );
      XLALDestroyOldDopplerMetric ( metric1_k );
    }
    XLAL_CHECK ( XLALScaleOldDopplerMetric ( metric1, 1.0 / Nseg ) == XLAL_SUCCESS, XLAL_EFUNC );

    // 2) compute metric using modern UniversalDopplerMetric module: (used in lalapps_FstatMetric_v2)
    XLAL_CHECK ( (metric2P = XLALComputeDopplerPhaseMetric ( &pars2, edat )) != NULL, XLAL_EFUNC );

    GPMAT( metric1->g_ij, "%0.4e" );
    GPMAT( metric2P->g_ij, "%0.4e" );

    // compare both metrics against each other:
    XLAL_CHECK ( (diff_2_1 = XLALCompareMetrics ( metric2P->g_ij, metric1->g_ij )) < tolPh, XLAL_ETOL, "Error(g2,g1)= %g exceeds tolerance of %g\n", diff_2_1, tolPh );
    XLALPrintWarning ("diff_2_1 = %e\n", diff_2_1 );

    XLALDestroyOldDopplerMetric ( metric1 );
    XLALDestroyDopplerPhaseMetric ( metric2P );

    XLALSegListClear ( &NsegList );
  }


  XLALPrintWarning("\n---------- ROUND 6: directed binary orbital metric ----------\n");
  {
    REAL8 Period = 68023.70496;
    REAL8 Omega = LAL_TWOPI / Period;
    REAL8 asini = 1.44;
    REAL8 tAsc = 897753994;
    REAL8 argp = 0;
    LIGOTimeGPS tP; XLALGPSSetREAL8 ( &tP, tAsc + argp / Omega );

    const PulsarDopplerParams dopScoX1 = {
      .refTime  = startTimeGPS,
      .Alpha    = Alpha,
      .Delta    = Delta,
      .fkdot    = { Freq },
      .asini    = asini,
      .period   = Period,
      .tp       = tP
    };
    REAL8 TspanScoX1 = 20 * 19 * 3600;	// 20xPorb for long-segment regime
    LALSegList XLAL_INIT_DECL(segListScoX1);
    XLAL_CHECK ( XLALSegListInitSimpleSegments ( &segListScoX1, startTimeGPS, 1, TspanScoX1 ) == XLAL_SUCCESS, XLAL_EFUNC );
    REAL8 tMid = XLALGPSGetREAL8(&startTimeGPS) + 0.5 * TspanScoX1;
    REAL8 DeltaMidAsc = tMid - tAsc;
    const DopplerCoordinateSystem coordSysScoX1 = { 6, { DOPPLERCOORD_FREQ, DOPPLERCOORD_ASINI, DOPPLERCOORD_TASC, DOPPLERCOORD_PORB, DOPPLERCOORD_KAPPA, DOPPLERCOORD_ETA } };
    DopplerMetricParams pars_ScoX1 = {
      .coordSys			= coordSysScoX1,
      .detMotionType		= DETMOTION_SPIN | DETMOTION_ORBIT,
      .segmentList		= segListScoX1,
      .multiIFO			= multiIFO,
      .multiNoiseFloor		= multiNoiseFloor,
      .signalParams		= { .Amp = Amp, .Doppler = dopScoX1 },
      .projectCoord		= - 1,	// -1==no projection
      .approxPhase		= 1,
    };
    pars_ScoX1.multiIFO.length = 1;	// truncate to first detector
    pars_ScoX1.multiNoiseFloor.length = 1;	// truncate to first detector

    // compute metric using modern UniversalDopplerMetric module: (used in lalapps_FstatMetric_v2)
    DopplerPhaseMetric *metric_ScoX1;
    XLAL_CHECK ( (metric_ScoX1 = XLALComputeDopplerPhaseMetric ( &pars_ScoX1, edat )) != NULL, XLAL_EFUNC );

    // compute analytic metric computed from Eq.(47) in Leaci,Prix PRD91, 102003 (2015):
    gsl_matrix *g0_ij;
    XLAL_CHECK ( (g0_ij = gsl_matrix_calloc ( 6, 6 )) != NULL, XLAL_ENOMEM, "Failed to gsl_calloc a 6x6 matrix\n");
    gsl_matrix_set ( g0_ij, 0, 0, pow ( LAL_PI * TspanScoX1, 2 ) / 3.0 );
    gsl_matrix_set ( g0_ij, 1, 1, 2.0 * pow ( LAL_PI * Freq, 2 ) );
    gsl_matrix_set ( g0_ij, 2, 2, 2.0 * pow ( LAL_PI * Freq * asini * Omega, 2 ) );
    gsl_matrix_set ( g0_ij, 3, 3, 0.5 * pow ( Omega, 4 ) * pow ( Freq * asini, 2 ) * ( pow ( TspanScoX1, 2 ) / 12.0 + pow ( DeltaMidAsc, 2 ) ) );
    REAL8 gPAsc = LAL_PI * pow ( Freq * asini, 2 ) * pow ( Omega, 3 ) * DeltaMidAsc;
    gsl_matrix_set ( g0_ij, 2, 3, gPAsc );
    gsl_matrix_set ( g0_ij, 3, 2, gPAsc );
    gsl_matrix_set ( g0_ij, 4, 4, 0.5 * pow ( LAL_PI * Freq * asini, 2 ) );
    gsl_matrix_set ( g0_ij, 5, 5, 0.5 * pow ( LAL_PI * Freq * asini, 2 ) );

    GPMAT ( metric_ScoX1->g_ij, "%0.4e" );
    GPMAT ( g0_ij, "%0.4e" );

    // compare metrics against each other
    REAL8 diff, tolScoX1 = 0.05;
    XLAL_CHECK ( (diff = XLALCompareMetrics ( metric_ScoX1->g_ij, g0_ij )) < tolScoX1, XLAL_ETOL, "Error(gNum,gAn)= %g exceeds tolerance of %g\n", diff, tolScoX1 );
    XLALPrintWarning ("diff_Num_An = %e\n", diff );

    gsl_matrix_free ( g0_ij );
    XLALDestroyDopplerPhaseMetric ( metric_ScoX1 );
    XLALSegListClear ( &segListScoX1 );
  }