示例#1
0
// ----- local function definitions ----------
static int
XLALComputeFstatDemod ( FstatResults* Fstats,
                        const FstatCommon *common,
                        void *method_data
                      )
{
  // Check input
  XLAL_CHECK(Fstats != NULL, XLAL_EFAULT);
  XLAL_CHECK(common != NULL, XLAL_EFAULT);
  XLAL_CHECK(method_data != NULL, XLAL_EFAULT);

  DemodMethodData *demod = (DemodMethodData*) method_data;
  // get internal timing info
  DemodTimingInfo *ti = &(demod->timingInfo);
  REAL8 tic = 0, toc = 0;

  // Get which F-statistic quantities to compute
  const FstatQuantities whatToCompute = Fstats->whatWasComputed;

  // handy shortcuts
  BOOLEAN returnAtoms = (whatToCompute & FSTATQ_ATOMS_PER_DET);
  PulsarDopplerParams thisPoint = Fstats->doppler;
  const REAL8 fStart = thisPoint.fkdot[0];
  const MultiSFTVector *multiSFTs = demod->multiSFTs;
  const MultiNoiseWeights *multiWeights = common->multiNoiseWeights;
  const MultiDetectorStateSeries *multiDetStates = common->multiDetectorStates;

  UINT4 numDetectors = multiSFTs->length;
  XLAL_CHECK ( multiDetStates->length == numDetectors, XLAL_EINVAL );
  XLAL_CHECK ( multiWeights==NULL || (multiWeights->length == numDetectors), XLAL_EINVAL );
  UINT4 numSFTs = 0;
  for ( UINT4 X = 0; X < numDetectors; X ++ ) {
    numSFTs += multiDetStates->data[X]->length;
  }

  // initialize timing info struct
  if ( ti->collectTiming )
    {
      XLAL_INIT_MEM ( (*ti) );
      ti->collectTiming = 1;

      ti->numDetectors = numDetectors;
      ti->numFreqBins = Fstats->numFreqBins;
      ti->numSFTs = numSFTs;

      tic = XLALGetCPUTime();
    }

  MultiSSBtimes *multiSSB = NULL;
  MultiAMCoeffs *multiAMcoef = NULL;
  // ----- check if we have buffered SSB+AMcoef for current sky-position
  if ( (demod->prevAlpha == thisPoint.Alpha) && (demod->prevDelta == thisPoint.Delta ) &&
       (demod->prevMultiSSBtimes != NULL) && ( XLALGPSDiff(&demod->prevRefTime, &thisPoint.refTime) == 0 ) &&	// have SSB times for same reftime?
       (demod->prevMultiAMcoef != NULL)
       )
    { // if yes ==> reuse
      multiSSB    = demod->prevMultiSSBtimes;
      multiAMcoef = demod->prevMultiAMcoef;
    }
  else
    { // if not, compute SSB + AMcoef for this skyposition
      SkyPosition skypos;
      skypos.system = COORDINATESYSTEM_EQUATORIAL;
      skypos.longitude = thisPoint.Alpha;
      skypos.latitude  = thisPoint.Delta;
      XLAL_CHECK ( (multiSSB = XLALGetMultiSSBtimes ( multiDetStates, skypos, thisPoint.refTime, common->SSBprec )) != NULL, XLAL_EFUNC );
      XLAL_CHECK ( (multiAMcoef = XLALComputeMultiAMCoeffs ( multiDetStates, multiWeights, skypos )) != NULL, XLAL_EFUNC );

      // store these for possible later re-use in buffer
      XLALDestroyMultiSSBtimes ( demod->prevMultiSSBtimes );
      demod->prevMultiSSBtimes = multiSSB;
      demod->prevRefTime = thisPoint.refTime;
      XLALDestroyMultiAMCoeffs ( demod->prevMultiAMcoef );
      demod->prevMultiAMcoef = multiAMcoef;
      demod->prevAlpha = thisPoint.Alpha;
      demod->prevDelta = thisPoint.Delta;
    } // if could not reuse previously buffered quantites

  MultiSSBtimes *multiBinary = NULL;
  MultiSSBtimes *multiSSBTotal = NULL;
  // handle binary-orbital timing corrections, if applicable
  if ( thisPoint.asini > 0 )
    {
      // compute binary time corrections to the SSB time delays and SSB time derivitive
      XLAL_CHECK ( XLALAddMultiBinaryTimes ( &multiBinary, multiSSB, &thisPoint ) == XLAL_SUCCESS, XLAL_EFUNC );
      multiSSBTotal = multiBinary;
    }
  else
    {
      multiSSBTotal = multiSSB;
    }

  if ( ti->collectTiming ) {
    toc = XLALGetCPUTime();
    ti->tauBary = (toc - tic);
  }

  // ----- compute final Fstatistic-value -----
  REAL4 Ad = multiAMcoef->Mmunu.Ad;
  REAL4 Bd = multiAMcoef->Mmunu.Bd;
  REAL4 Cd = multiAMcoef->Mmunu.Cd;
  REAL4 Ed = multiAMcoef->Mmunu.Ed;;
  REAL4 Dd_inv = 1.0 / multiAMcoef->Mmunu.Dd;

  // ---------- Compute F-stat for each frequency bin ----------
  for ( UINT4 k = 0; k < Fstats->numFreqBins; k++ )
    {
      // Set frequency to search at
      thisPoint.fkdot[0] = fStart + k * Fstats->dFreq;

      COMPLEX8 Fa = 0;       		// complex amplitude Fa
      COMPLEX8 Fb = 0;                 // complex amplitude Fb
      MultiFstatAtomVector *multiFstatAtoms = NULL;	// per-IFO, per-SFT arrays of F-stat 'atoms', ie quantities required to compute F-stat

      // prepare return of 'FstatAtoms' if requested
      if ( returnAtoms )
        {
          XLAL_CHECK ( (multiFstatAtoms = XLALMalloc ( sizeof(*multiFstatAtoms) )) != NULL, XLAL_ENOMEM );
          multiFstatAtoms->length = numDetectors;
          XLAL_CHECK ( (multiFstatAtoms->data = XLALMalloc ( numDetectors * sizeof(*multiFstatAtoms->data) )) != NULL, XLAL_ENOMEM );
        } // if returnAtoms

      // loop over detectors and compute all detector-specific quantities
      for ( UINT4 X=0; X < numDetectors; X ++)
        {
          COMPLEX8 FaX, FbX;
          FstatAtomVector *FstatAtoms = NULL;
          FstatAtomVector **FstatAtoms_p = returnAtoms ? (&FstatAtoms) : NULL;

          // call XLALComputeFaFb_...() function for the user-requested hotloop variant
          XLAL_CHECK ( (demod->computefafb_func) ( &FaX, &FbX, FstatAtoms_p, multiSFTs->data[X], thisPoint.fkdot,
                                                   multiSSBTotal->data[X], multiAMcoef->data[X], demod->Dterms ) == XLAL_SUCCESS, XLAL_EFUNC );

          if ( returnAtoms ) {
            multiFstatAtoms->data[X] = FstatAtoms;     // copy pointer to IFO-specific Fstat-atoms 'contents'
          }

          XLAL_CHECK ( isfinite(creal(FaX)) && isfinite(cimag(FaX)) && isfinite(creal(FbX)) && isfinite(cimag(FbX)), XLAL_EFPOVRFLW );

          if ( whatToCompute & FSTATQ_FAFB_PER_DET )
            {
              Fstats->FaPerDet[X][k] = FaX;
              Fstats->FbPerDet[X][k] = FbX;
            }

          // compute single-IFO F-stats, if requested
          if ( whatToCompute & FSTATQ_2F_PER_DET )
            {
              REAL4 AdX = multiAMcoef->data[X]->A;
              REAL4 BdX = multiAMcoef->data[X]->B;
              REAL4 CdX = multiAMcoef->data[X]->C;
              REAL4 EdX = 0;
              REAL4 DdX_inv = 1.0 / multiAMcoef->data[X]->D;

              // compute final single-IFO F-stat
              Fstats->twoFPerDet[X][k] = XLALComputeFstatFromFaFb ( FaX, FbX, AdX, BdX, CdX, EdX, DdX_inv );

            } // if FSTATQ_2F_PER_DET

          /* Fa = sum_X Fa_X */
          Fa += FaX;

          /* Fb = sum_X Fb_X */
          Fb += FbX;

        } // for  X < numDetectors

      if ( whatToCompute & FSTATQ_2F )
        {
          Fstats->twoF[k] = XLALComputeFstatFromFaFb ( Fa, Fb, Ad, Bd, Cd, Ed, Dd_inv );
        }

      // Return multi-detector Fa & Fb
      if ( whatToCompute & FSTATQ_FAFB )
        {
          Fstats->Fa[k] = Fa;
          Fstats->Fb[k] = Fb;
        }

      // Return F-atoms per detector
      if ( whatToCompute & FSTATQ_ATOMS_PER_DET )
        {
          XLALDestroyMultiFstatAtomVector ( Fstats->multiFatoms[k] );
          Fstats->multiFatoms[k] = multiFstatAtoms;
        }

    } // for k < Fstats->numFreqBins

  // this needs to be free'ed, as it's currently not buffered
  XLALDestroyMultiSSBtimes ( multiBinary );

  // Return amplitude modulation coefficients
  Fstats->Mmunu = demod->prevMultiAMcoef->Mmunu;

  // return per-detector antenna-pattern matrices
  for ( UINT4 X=0; X < numDetectors; X ++ )
    {
      Fstats->MmunuX[X].Ad = multiAMcoef->data[X]->A;
      Fstats->MmunuX[X].Bd = multiAMcoef->data[X]->B;
      Fstats->MmunuX[X].Cd = multiAMcoef->data[X]->C;
      Fstats->MmunuX[X].Dd = multiAMcoef->data[X]->D;
      Fstats->MmunuX[X].Ed = 0;
    }

  if ( ti->collectTiming ) {
    toc = XLALGetCPUTime();
    ti->tauTotal = (toc - tic);
    ti->tauF1NoBuf = ti->tauTotal / ( Fstats->numFreqBins * numDetectors );
    ti->tauF1Buf   = (ti->tauTotal - ti->tauBary) / ( Fstats->numFreqBins * numDetectors );
  }

  return XLAL_SUCCESS;

} // XLALComputeFstatDemod()
/** Compute the semi-coherent statistics
 *
 * This function computes the semi-coherent s.
 *
 */
int XLALComputeSemiCoherentStat(FILE *fp,                                /**< [in] the output file pointer */
                                REAL4DemodulatedPowerVector *power,      /**< [in] the input data in the form of power */
                                ParameterSpace *pspace,                  /**< [in] the parameter space */
                                GridParametersVector *fgrid,		/**< UNDOCUMENTED */
                                GridParameters *bingrid,                 /**< [in] the grid parameters */
                                INT4 ntoplist,		/**< UNDOCUMENTED */
                                BOOLEAN with_xbins                       /**< enable fast summing of extra bins */
                                )
{

  toplist TL;                                         /* the results toplist */
  Template *bintemp = NULL;                           /* the binary parameter space template */
  Template *fdots = NULL;                             /* the freq derivitive template for each segment */
  UINT4 i,j;                                          /* counters */
  UINT4 percent = 0;                                  /* counter for status update */
  REAL8 mean = 0.0;
  REAL8 var = 0.0;
  UINT4 Ntemp = 0;

  /* validate input parameters */
 /*  if ((*SemiCo) != NULL) { */
/*     LogPrintf(LOG_CRITICAL,"%s: Invalid input, output BayesianProducts structure != NULL.\n",__func__); */
/*     XLAL_ERROR(XLAL_EINVAL); */
/*   } */
  if (power == NULL) {
    LogPrintf(LOG_CRITICAL,"%s: Invalid input, input REAL4DemodulatedPowerVector structure = NULL.\n",__func__);
    XLAL_ERROR(XLAL_EINVAL);
  }
  if (pspace == NULL) {
    LogPrintf(LOG_CRITICAL,"%s: Invalid input, input GridParameters structure = NULL.\n",__func__);
    XLAL_ERROR(XLAL_EINVAL);
  }
  if (fgrid == NULL) {
    LogPrintf(LOG_CRITICAL,"%s: Invalid input, input GridParametersVector structure = NULL.\n",__func__);
    XLAL_ERROR(XLAL_EINVAL);
  }
  if (bingrid == NULL) {
    LogPrintf(LOG_CRITICAL,"%s: Invalid input, input GridParameters structure = NULL.\n",__func__);
    XLAL_ERROR(XLAL_EINVAL);
  }

  /* check for same frequency spacing */
  const REAL8 dfreq = fgrid->segment[0]->grid[0].delta;
  for (i=0;i<power->length;i++) {
    if ( dfreq != fgrid->segment[i]->grid[0].delta ) {
      LogPrintf(LOG_CRITICAL,"%s : inconsistent frequency spacing in segment %u, %.10g != %.10g\n",__func__,i,fgrid->segment[i]->grid[0].delta,dfreq);
      XLAL_ERROR(XLAL_EINVAL);
    }
  }

  /* check that coherent grids step by 1 in frequency */
  for (i=0;i<power->length;i++) {
    GridParameters *fdotgrid = fgrid->segment[i];
    if ( fdotgrid->prod[0] != 1 ) {
      LogPrintf(LOG_CRITICAL,"%s : coherent grid step in segment %u does not equal 1\n",__func__,i);
      XLAL_ERROR(XLAL_EINVAL);
    }
  }

  /* allocate memory for the results toplist */
  TL.n = ntoplist;
  if ((TL.data = (REAL4 *)XLALCalloc(TL.n,sizeof(REAL4))) == NULL) {
    LogPrintf(LOG_CRITICAL,"%s : XLALCalloc() failed with error = %d\n",__func__,xlalErrno);
    XLAL_ERROR(XLAL_ENOMEM);
  }
  if ((TL.params = (REAL8 **)XLALCalloc(TL.n,sizeof(REAL8 *))) == NULL) {
    LogPrintf(LOG_CRITICAL,"%s : XLALCalloc() failed with error = %d\n",__func__,xlalErrno);
    XLAL_ERROR(XLAL_ENOMEM);
  }
  for (i=0;i<(UINT4)TL.n;i++) {
    TL.params[i] = NULL;
    if ((TL.params[i] = (REAL8 *)XLALCalloc(bingrid->ndim,sizeof(REAL8))) == NULL) {
      LogPrintf(LOG_CRITICAL,"%s : XLALCalloc() failed with error = %d\n",__func__,xlalErrno);
      XLAL_ERROR(XLAL_ENOMEM);
    }
  }
  TL.idx = 0;

  /* allocate memory for the fdots */
  if ((fdots = XLALCalloc(power->length, sizeof(*fdots))) == NULL) {
    LogPrintf(LOG_CRITICAL,"%s : XLALCalloc() failed with error = %d\n",__func__,xlalErrno);
    XLAL_ERROR(XLAL_ENOMEM);
  }
  for (i=0;i<power->length;i++) {
    if ((fdots[i].x = XLALCalloc(fgrid->segment[0]->ndim,sizeof(REAL8))) == NULL) {
      LogPrintf(LOG_CRITICAL,"%s : XLALCalloc() failed with error = %d\n",__func__,xlalErrno);
      XLAL_ERROR(XLAL_ENOMEM);
    }
    if ((fdots[i].idx = XLALCalloc(fgrid->segment[0]->ndim,sizeof(INT4))) == NULL) {
      LogPrintf(LOG_CRITICAL,"%s : XLALCalloc() failed with error = %d\n",__func__,xlalErrno);
      XLAL_ERROR(XLAL_ENOMEM);
    }
    fdots[i].ndim = fgrid->segment[0]->ndim;
  }

  /* define the chi-squared threshold */
  /* REAL8 thr = gsl_cdf_chisq_Qinv(frac,2*power->length);
  LogPrintf(LOG_DEBUG,"%s : computed the threshold as %f\n",__func__,thr); */

  int (*getnext)(Template **temp,GridParameters *gridparams, ParameterSpace *space,void *);
  UINT8 newmax = bingrid->max;
  ParameterSpace *temppspace = NULL;
  if (bingrid->coverage>0) {
    getnext = &XLALGetNextRandomBinaryTemplate;
    newmax = bingrid->Nr;
    temppspace = pspace;
  }
  else getnext = &XLALGetNextTemplate;

  REAL4 *logLratiosumvec = NULL;

  /* single loop over binary templates */
  double fine_deriv_t = 0;
  UINT8 num_fine_deriv = 0;
  double fine_sum_t = 0;
  UINT8 num_fine_sum = 0;
  INT4 max_tot_xbins = 0;
  while (getnext(&bintemp,bingrid,temppspace,r)) {

    const REAL8 asini = bintemp->x[1];           /* define asini */
    const REAL8 omega = bintemp->x[3];           /* define omega */

    /* maximum extra bins to sum in frequency at this template,
       while keeping correct derivative bins (minus 10% for safety) */
    const INT4 xbins = !with_xbins ? 0 :
      (INT4) floor( 0.45 * dfreq / ( asini * omega ) );
    XLAL_CHECK( xbins >= 0, XLAL_EDOM, "Invalid xbins=%d\n", xbins );

    INT4 left_xbins = xbins, right_xbins = xbins;

    /** loop over segments **********************************************************************************/
    const double fine_deriv_t0 = XLALGetCPUTime();
    for (i=0;i<power->length;i++) {

      REAL8 tmid = XLALGPSGetREAL8(&(power->segment[i]->epoch)) + 0.5*pspace->tseg;
      GridParameters *fdotgrid = fgrid->segment[i];
      /* REAL8 norm = (REAL8)background->data[i]; */

      /* compute instantaneous frequency derivitives corresponding to the current template for this segment */
      XLALComputeBinaryFreqDerivitives(&fdots[i],bintemp,tmid);

      /* find ndim-D indices corresponding to the spin derivitive values for the segment power */
      for (j=0;j<fdots[i].ndim;j++) {
        fdots[i].idx[j] = lround( (fdots[i].x[j] - fdotgrid->grid[j].min)*fdotgrid->grid[j].oneoverdelta );

        /* check that index is in range */
        if ( fdots[i].idx[j] < 0 || fdots[i].idx[j] >= (INT4)fdotgrid->grid[j].length ) {
          LogPrintf(LOG_CRITICAL,"%s: stepped outside grid in segment %d, nu=%g, asini=%g, tasc=%g, omega=%g, fdots[%d] = [%g <= %g <= %g, 0 <= %d < %d]\n", __func__, i, bintemp->x[0], bintemp->x[1], bintemp->x[2], bintemp->x[3], j, fdotgrid->grid[j].min, fdots[i].x[j], fdotgrid->grid[j].min + fdotgrid->grid[j].delta*fdotgrid->grid[j].length, fdots[i].idx[j], fdotgrid->grid[j].length);
          XLAL_ERROR(XLAL_EDOM);
        }

      }

      /* ensure number of extra frequency bins do not go out of range of coherent grids */
      left_xbins = GSL_MIN( left_xbins, (INT4)( fdots[i].idx[0] ) );
      right_xbins = GSL_MIN( right_xbins, (INT4)( fdotgrid->grid[0].length - fdots[i].idx[0] - 1 ) );
      XLAL_CHECK( left_xbins >= 0, XLAL_EDOM, "Invalid left_xbins=%d\n", left_xbins );
      XLAL_CHECK( right_xbins >= 0, XLAL_EDOM, "Invalid right_xbins=%d\n", right_xbins );

    } /* end loop over segments */
    fine_deriv_t += XLALGetCPUTime() - fine_deriv_t0;
    num_fine_deriv += power->length;
    /*************************************************************************************/

    const INT4 tot_xbins = 1 + left_xbins + right_xbins;
    if ( max_tot_xbins < tot_xbins ) {
      max_tot_xbins = tot_xbins;

      /* reallocate logLratiosumvec */
      logLratiosumvec = XLALRealloc( logLratiosumvec, max_tot_xbins * sizeof( *logLratiosumvec ) );
      XLAL_CHECK( logLratiosumvec != NULL, XLAL_ENOMEM );

    }

    /** loop over segments **********************************************************************************/
    const double fine_sum_t0 = XLALGetCPUTime();
    for (i=0;i<power->length;i++) {

      REAL4DemodulatedPower *currentpower = power->segment[i];
      GridParameters *fdotgrid = fgrid->segment[i];

      /* find starting 1-D index corresponding to the spin derivitive values for the segment power */
      INT4 idx0 = fdots[i].idx[0] - left_xbins;
      for (j=1;j<fdots[i].ndim;j++) {
        idx0 += fdots[i].idx[j] * fdotgrid->prod[j];
      }

      /* define the power at this location in this segment */
      if (i==0) {
        memcpy( logLratiosumvec, &currentpower->data->data[idx0], tot_xbins * sizeof( *logLratiosumvec ) );
      } else {
        XLAL_CHECK( XLALVectorAddREAL4( logLratiosumvec, logLratiosumvec, &currentpower->data->data[idx0], tot_xbins ) == XLAL_SUCCESS, XLAL_EFUNC );
      }

    } /* end loop over segments */
    fine_sum_t += XLALGetCPUTime() - fine_sum_t0;
    num_fine_sum += ( power->length - 1 ) * tot_xbins;
    /*************************************************************************************/

    /* make it a true chi-squared variable */
    XLAL_CHECK( XLALVectorScaleREAL4( logLratiosumvec, 2.0, logLratiosumvec, tot_xbins ) == XLAL_SUCCESS, XLAL_EFUNC );

    /* save central binary template frequency */
    const REAL8 nu0 = bintemp->x[0];

    for (INT4 x = -left_xbins; x <= right_xbins; ++x) {

      /* set binary template frequency */
      bintemp->x[0] = nu0 + dfreq*x;

      /* output semi-coherent statistic for this template if it exceeds the threshold*/
      const REAL4 logLratiosum = logLratiosumvec[x + left_xbins];
      mean += logLratiosum;
      var += logLratiosum*logLratiosum;
      ++Ntemp;
      XLALtoplist(logLratiosum,bintemp,&TL);

    }

    /* if (logLratiosum>thr) {
      for (j=0;j<bingrid->ndim;j++) fprintf(fp,"%6.12f\t",bintemp->x[j]);
      fprintf(fp,"%6.12e\n",logLratiosum);
    } */

    /* output status to screen */
    if ( (bintemp->currentidx == 0) || (floor(100.0*(REAL8)bintemp->currentidx/(REAL8)newmax) > (REAL8)percent) ) {
      percent = (UINT4)floor(100*(REAL8)bintemp->currentidx/(REAL8)newmax);
      LogPrintf(LOG_NORMAL,"%s : completed %d%% (%"LAL_UINT8_FORMAT"/%"LAL_UINT8_FORMAT")\n",__func__,percent,bintemp->currentidx,newmax);
    }

    /* we've computed this number of extra templates */
    bintemp->currentidx += left_xbins + right_xbins;

  } /* end loop over templates */
  LogPrintf(LOG_NORMAL,"%s : time to compute fine grid derivatives = %0.12e\n",__func__, fine_deriv_t);
  LogPrintf(LOG_NORMAL,"%s : number of fine grid derivatives = %"LAL_UINT8_FORMAT"\n",__func__, num_fine_deriv);
  LogPrintf(LOG_NORMAL,"%s : time to compute fine summations = %0.12e\n",__func__, fine_sum_t);
  LogPrintf(LOG_NORMAL,"%s : number of fine grid summations = %"LAL_UINT8_FORMAT"\n",__func__, num_fine_sum);
  LogPrintf(LOG_NORMAL,"%s : summed up to %d frequency bins at a time\n", __func__, max_tot_xbins);
  /*************************************************************************************/

  /* compute mean and variance of results */
  mean = mean/(REAL8)Ntemp;
  var = var/(REAL8)(Ntemp-1);
  var = (var - mean*mean);

  /* modify toplist to have correct mean and variance */
  for (i=0;i<(UINT4)TL.n;i++) TL.data[i] = (TL.data[i] - mean)*sqrt(4.0*power->length)/sqrt(var) + 2.0*power->length;

  /* output toplist to file */
  for (i=0;i<(UINT4)TL.n;i++) {
    for (j=0;j<bingrid->ndim;j++) fprintf(fp,"%6.12f\t",TL.params[i][j]);
    fprintf(fp,"%6.12e\n",TL.data[i]);
  }

  /* free template memory */
  for (i=0;i<power->length;i++) {
    XLALFree(fdots[i].x);
    XLALFree(fdots[i].idx);
  }
  XLALFree(fdots);
  XLALFree(TL.data);
  for (i=0;i<(UINT4)TL.n;i++) XLALFree(TL.params[i]);
  XLALFree(TL.params);

  XLALFree(logLratiosumvec);

  LogPrintf(LOG_DEBUG,"%s : leaving.\n",__func__);
  return XLAL_SUCCESS;

}