コード例 #1
0
ファイル: FindChirpTDTemplate.c プロジェクト: Solaro/lalsuite
void
LALFindChirpTDTemplate (
    LALStatus                  *status,
    FindChirpTemplate          *fcTmplt,
    InspiralTemplate           *tmplt,
    FindChirpTmpltParams       *params
    )

{
  UINT4         j;
  UINT4         shift;
  UINT4         waveLength;
  UINT4         numPoints;
  REAL4        *xfac;
  REAL8         deltaF;
  REAL8         deltaT;
  REAL8         sampleRate;
  const REAL4   cannonDist = 1.0; /* Mpc */
  /*CHAR          infomsg[512];*/
  PPNParamStruc ppnParams;
  CoherentGW    waveform;

  REAL4Vector  *tmpxfac = NULL; /* Used for band-passing */


  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );


  /*
   *
   * check that the arguments are reasonable
   *
   */


  /* check that the output structures exist */
  ASSERT( fcTmplt, status,
      FINDCHIRPTDH_ENULL, FINDCHIRPTDH_MSGENULL );
  ASSERT( fcTmplt->data, status,
      FINDCHIRPTDH_ENULL, FINDCHIRPTDH_MSGENULL );
  ASSERT( fcTmplt->data->data, status,
      FINDCHIRPTDH_ENULL, FINDCHIRPTDH_MSGENULL );

  /* check that the parameter structure exists */
  ASSERT( params, status,
      FINDCHIRPTDH_ENULL, FINDCHIRPTDH_MSGENULL );
  ASSERT( params->xfacVec, status,
      FINDCHIRPTDH_ENULL, FINDCHIRPTDH_MSGENULL );
  ASSERT( params->xfacVec->data, status,
      FINDCHIRPTDH_ENULL, FINDCHIRPTDH_MSGENULL );

  /* check we have an fft plan for the template */
  ASSERT( params->fwdPlan, status,
      FINDCHIRPTDH_ENULL, FINDCHIRPTDH_MSGENULL );

  /* check that the timestep is positive */
  ASSERT( params->deltaT > 0, status,
      FINDCHIRPTDH_EDELT, FINDCHIRPTDH_MSGEDELT );

  /* check that the input exists */
  ASSERT( tmplt, status, FINDCHIRPTDH_ENULL, FINDCHIRPTDH_MSGENULL );

  /* check that the parameter structure is set to a time domain approximant */
  switch ( params->approximant )
  {
    case TaylorT1:
    case TaylorT2:
    case TaylorT3:
    case TaylorT4:
    case GeneratePPN:
    case PadeT1:
    case EOB:
    case EOBNR:
    case FindChirpPTF:
    case EOBNRv2:
    case IMRPhenomB:
    case IMRPhenomC:
      break;

    default:
      ABORT( status, FINDCHIRPTDH_EMAPX, FINDCHIRPTDH_MSGEMAPX );
      break;
  }

  /* store deltaT and zero out the time domain waveform vector */
  deltaT = params->deltaT;
  sampleRate = 1.0 / deltaT;
  xfac = params->xfacVec->data;
  numPoints =  params->xfacVec->length;
  memset( xfac, 0, numPoints * sizeof(REAL4) );

  ASSERT( numPoints == (2 * (fcTmplt->data->length - 1)), status,
      FINDCHIRPTDH_EMISM, FINDCHIRPTDH_MSGEMISM );


  /* choose the time domain template */
  if ( params->approximant == GeneratePPN )
  {


    /*
     *
     * generate the waveform using LALGeneratePPNInspiral() from inject
     *
     */



    /* input parameters */
    memset( &ppnParams, 0, sizeof(PPNParamStruc) );
    ppnParams.deltaT = deltaT;
    ppnParams.mTot = tmplt->mass1 + tmplt->mass2;
    ppnParams.eta = tmplt->mass1 * tmplt->mass2 /
      ( ppnParams.mTot * ppnParams.mTot );
    ppnParams.d = 1.0;
    ppnParams.fStartIn = params->fLow;
    ppnParams.fStopIn = -1.0 /
      (6.0 * sqrt(6.0) * LAL_PI * ppnParams.mTot * LAL_MTSUN_SI);

    /* generate waveform amplitude and phase */
    memset( &waveform, 0, sizeof(CoherentGW) );
    LALGeneratePPNInspiral( status->statusPtr, &waveform, &ppnParams );
    CHECKSTATUSPTR( status );

    /* print termination information and check sampling */
    LALInfo( status, ppnParams.termDescription );
    if ( ppnParams.dfdt > 2.0 )
    {
      ABORT( status, FINDCHIRPTDH_ESMPL, FINDCHIRPTDH_MSGESMPL );
    }
    if ( waveform.a->data->length > numPoints )
    {
      ABORT( status, FINDCHIRPTDH_ELONG, FINDCHIRPTDH_MSGELONG );
    }

    /* compute h(t) */
    for ( j = 0; j < waveform.a->data->length; ++j )
    {
      xfac[j] =
        waveform.a->data->data[2*j] * cos( waveform.phi->data->data[j] );
    }

    /* free the memory allocated by LALGeneratePPNInspiral() */
    LALSDestroyVectorSequence( status->statusPtr, &(waveform.a->data) );
    CHECKSTATUSPTR( status );

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

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

    LALFree( waveform.a );
    LALFree( waveform.f );
    LALFree( waveform.phi );

    /* waveform parameters needed for findchirp filter */
    tmplt->approximant = params->approximant;
    tmplt->tC = ppnParams.tc;
    tmplt->fFinal = ppnParams.fStop;

    fcTmplt->tmpltNorm = params->dynRange / ( cannonDist * 1.0e6 * LAL_PC_SI );
    fcTmplt->tmpltNorm *= fcTmplt->tmpltNorm;
  }
  else
  {


    /*
     *
     * generate the waveform by calling LALInspiralWave() from inspiral
     *
     */


    /* set up additional template parameters */
    deltaF = 1.0 / ((REAL8) numPoints * deltaT);
    tmplt->ieta            = 1;
    tmplt->approximant     = params->approximant;
    tmplt->order           = params->order;
    tmplt->massChoice      = m1Andm2;
    tmplt->tSampling       = sampleRate;
    tmplt->fLower          = params->fLow;
    tmplt->fCutoff         = sampleRate / 2.0 - deltaF;
    /* get the template norm right */
    if ( params->approximant==EOBNR )
    {
     /* lalinspiral EOBNR code produces correct norm when 
        fed unit signalAmplitude and non-physical distance */
      tmplt->signalAmplitude = 1.0;
      tmplt->distance      = -1.0;
    }
    else if ( params->approximant==EOBNRv2 )
    {
     /* this formula sets the ampl0 variable to 1.0 
      * within the lalsimulation EOBNRv2 waveform engine 
      * which again produces a correct template norm     */
      tmplt->distance      = tmplt->totalMass*LAL_MRSUN_SI;
    }
    else if ( (params->approximant==IMRPhenomB) || (params->approximant==IMRPhenomC) )
    {
      /* 1Mpc standard distance - not clear if this produces correct norm */
      tmplt->distance      = 1.0;
      tmplt->spin1[2]      = 2 * tmplt->chi/(1. + sqrt(1.-4.*tmplt->eta));
    }

    /* compute the tau parameters from the input template */
    LALInspiralParameterCalc( status->statusPtr, tmplt );
    CHECKSTATUSPTR( status );

    /* determine the length of the chirp in sample points */
    LALInspiralWaveLength( status->statusPtr, &waveLength, *tmplt );
    CHECKSTATUSPTR( status );

    if ( waveLength > numPoints )
    {
      ABORT( status, FINDCHIRPTDH_ELONG, FINDCHIRPTDH_MSGELONG );
    }

    /* generate the chirp in the time domain */
    LALInspiralWave( status->statusPtr, params->xfacVec, tmplt );
    CHECKSTATUSPTR( status );


    /* template dependent normalization */
    fcTmplt->tmpltNorm  = 2 * tmplt->mu;
    fcTmplt->tmpltNorm *= 2 * LAL_MRSUN_SI / ( cannonDist * 1.0e6 * LAL_PC_SI );
    fcTmplt->tmpltNorm *= params->dynRange;
    fcTmplt->tmpltNorm *= fcTmplt->tmpltNorm;
  }


  /* Taper the waveform if required */
  if ( params->taperTmplt != LAL_SIM_INSPIRAL_TAPER_NONE )
  {
    if ( XLALSimInspiralREAL4WaveTaper( params->xfacVec, params->taperTmplt )
           == XLAL_FAILURE )
    {
      ABORTXLAL( status );
    }
  }

  /* Find the end of the chirp */
  j = numPoints - 1;
  while ( xfac[j] == 0 )
  {
    /* search for the end of the chirp but don't fall off the array */
    if ( --j == 0 )
    {
      ABORT( status, FINDCHIRPTDH_EEMTY, FINDCHIRPTDH_MSGEEMTY );
    }
  }
  ++j;

  /* Band pass the template if required */
  if ( params->bandPassTmplt )
  {
    REAL4Vector bpVector; /*Used to save time */

    /* We want to shift the template to the middle of the vector so */
    /* that band-passing will work properly */
    shift = ( numPoints - j ) / 2;
    memmove( xfac + shift, xfac, j * sizeof( *xfac ) );
    memset( xfac, 0, shift * sizeof( *xfac ) );
    memset( xfac + ( numPoints + j ) / 2, 0,
         ( numPoints - ( numPoints + j ) / 2 ) * sizeof( *xfac ) );


    /* Select an appropriate part of the vector to band pass. */
    /* band passing the whole thing takes a lot of time */
    if ( j > 2 * sampleRate && 2 * j <= numPoints )
    {
      bpVector.length = 2 * j;
      bpVector.data   = params->xfacVec->data + numPoints / 2 - j;
    }
    else if ( j <= 2 * sampleRate && j + 2 * sampleRate <= numPoints )
    {
      bpVector.length = j + 2 * sampleRate;
      bpVector.data   = params->xfacVec->data
                   + ( numPoints - j ) / 2 - (INT4)sampleRate;
    }
    else
    {
      bpVector.length = params->xfacVec->length;
      bpVector.data   = params->xfacVec->data;
    }

    if ( XLALBandPassInspiralTemplate( &bpVector, 0.95 * tmplt->fLower,
                 1.02 * tmplt->fFinal, sampleRate ) == XLAL_FAILURE )
    {
      ABORTXLAL( status );
    }

    /* Now we need to do the shift to the end. */
    /* Use a temporary vector to avoid mishaps */
    if ( ( tmpxfac = XLALCreateREAL4Vector( numPoints ) ) == NULL )
    {
      ABORTXLAL( status );
    }

    if ( params->approximant == EOBNR || params->approximant == EOBNRv2
        || params->approximant == IMRPhenomB || params->approximant == IMRPhenomC )
    {
      /* We need to do something slightly different for EOBNR */
      UINT4 endIndx = (UINT4) (tmplt->tC * sampleRate);

      memcpy( tmpxfac->data, xfac + ( numPoints - j ) / 2 + endIndx,
          ( numPoints - ( numPoints - j ) / 2 - endIndx ) * sizeof( *xfac ) );

      memcpy( tmpxfac->data + numPoints - ( numPoints - j ) / 2 - endIndx,
                  xfac, ( ( numPoints - j ) / 2 + endIndx ) * sizeof( *xfac ) );
    }
    else
    {
      memcpy( tmpxfac->data, xfac + ( numPoints + j ) / 2,
          ( numPoints - ( numPoints + j ) / 2 ) * sizeof( *xfac ) );

      memcpy( tmpxfac->data + numPoints - ( numPoints + j ) / 2,
                    xfac, ( numPoints + j ) / 2 * sizeof( *xfac ) );
    }

    memcpy( xfac, tmpxfac->data, numPoints * sizeof( *xfac ) );

    XLALDestroyREAL4Vector( tmpxfac );
    tmpxfac = NULL;
  }
  else if ( params->approximant == EOBNR || params->approximant == EOBNRv2
      || params->approximant == IMRPhenomB || params->approximant == IMRPhenomC )
  {
    /* For EOBNR we shift so that tC is at the end of the vector */
    if ( ( tmpxfac = XLALCreateREAL4Vector( numPoints ) ) == NULL )
    {
      ABORTXLAL( status );
    }

    /* Set the coalescence index depending on tC */
    j = (UINT4) (tmplt->tC * sampleRate);
    memcpy( tmpxfac->data + numPoints - j, xfac, j * sizeof( *xfac ) );
    memcpy( tmpxfac->data, xfac + j, ( numPoints - j ) * sizeof( *xfac ) );
    memcpy( xfac, tmpxfac->data, numPoints * sizeof( *xfac ) );
    XLALDestroyREAL4Vector( tmpxfac );
    tmpxfac = NULL;
  }
  else
  {
    /* No need for so much shifting around if not band passing */
    /* shift chirp to end of vector so it is the correct place for the filter */
    memmove( xfac + numPoints - j, xfac, j * sizeof( *xfac ) );
    memset( xfac, 0, ( numPoints - j ) * sizeof( *xfac ) );
  }

  /*
   *
   * create the frequency domain findchirp template
   *
   */

  /* fft chirp */
  if ( XLALREAL4ForwardFFT( fcTmplt->data, params->xfacVec,
      params->fwdPlan ) == XLAL_FAILURE )
  {
    ABORTXLAL( status );
  }

  /* copy the template parameters to the findchirp template structure */
  memcpy( &(fcTmplt->tmplt), tmplt, sizeof(InspiralTemplate) );

  /* normal exit */
  DETATCHSTATUSPTR( status );
  RETURN( status );
}
コード例 #2
0
ファイル: FindChirpSPTemplate.c プロジェクト: Solaro/lalsuite
void
LALFindChirpSPTemplate (
    LALStatus                  *status,
    FindChirpTemplate          *fcTmplt,
    InspiralTemplate           *tmplt,
    FindChirpTmpltParams       *params
    )

{
  UINT4         numPoints  = 0;
  REAL4         deltaF     = 0.0;
  REAL4         m          = 0.0;
  REAL4         eta        = 0.0;
  REAL4         mu         = 0.0;
  REAL4         S1z        = 0.0;
  REAL4         S2z        = 0.0;
  REAL4         mass_delta = 0.0;
  REAL4         chis       = 0.0;
  REAL4         chia       = 0.0;
  REAL4         chi1       = 0.0;
  REAL4         chi2       = 0.0;
  REAL4         qm_def1    = 0.0;
  REAL4         qm_def2    = 0.0;
  REAL4         pn_beta    = 0.0;
  REAL4         pn_sigma   = 0.0;
  REAL4         pn_gamma   = 0.0;
  COMPLEX8     *expPsi     = NULL;
  REAL4        *xfac       = NULL;
  REAL4         x1         = 0.0;
  REAL4         psi        = 0.0;
  REAL4         psi0       = 0.0;
  INT4          k          = 0;
  INT4          f          = 0;
  INT4          kmin       = 0;
  INT4          kmax       = 0;
  REAL4         fLow       = -1;
  CHAR          infomsg[512];

  REAL4         distNorm;
  const REAL4   cannonDist = 1.0; /* Mpc */

  /* pn constants */
  REAL4 c0, c10, c15, c20, c25, c25Log, c30, c30Log, c35, c40P;
  REAL4 x;

  /* chebychev coefficents for expansion of sin and cos */
  const REAL4 s2 = -0.16605;
  const REAL4 s4 =  0.00761;
  const REAL4 c2 = -0.49670;
  const REAL4 c4 =  0.03705;


  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );


  /*
   *
   * check that the arguments are reasonable
   *
   */


  /* check that the output structures exist */
  ASSERT( fcTmplt, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( fcTmplt->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( fcTmplt->data->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );

  /* check that the parameter structure exists */
  ASSERT( params, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( params->xfacVec, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( params->xfacVec->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );

  /* check that the timestep is positive */
  ASSERT( params->deltaT > 0, status,
      FINDCHIRPSPH_EDELT, FINDCHIRPSPH_MSGEDELT );

  /* check that the input exists */
  ASSERT( tmplt, status, FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );

  /* check that the parameter structure is set */
  /* to the correct waveform approximant       */
  if ( params->approximant != FindChirpSP )
  {
    ABORT( status, FINDCHIRPSPH_EMAPX, FINDCHIRPSPH_MSGEMAPX );
  }
  LALInfo( status, "Generating template using FindChirpSP" );


  /*
   *
   * compute the stationary phase template
   *
   */


  /* set up pointers */
  expPsi = fcTmplt->data->data;
  xfac = params->xfacVec->data;
  numPoints = 2 * (fcTmplt->data->length - 1);

  /* set the waveform approximant */
  tmplt->approximant = params->approximant;

  /* set the pN order of the template */
  tmplt->order = params->order;

  /* zero output */
  memset( expPsi, 0, fcTmplt->data->length * sizeof(COMPLEX8) );

  /* parameters */
  deltaF = 1.0 / ( (REAL4) params->deltaT * (REAL4) numPoints );
  m      = (REAL4) tmplt->totalMass;
  eta    = (REAL4) tmplt->eta;
  mu     = (REAL4) tmplt->mu;
  S1z    = tmplt->spin1[2];
  S2z    = tmplt->spin2[2];
  mass_delta = (tmplt->mass1 - tmplt->mass2) / (m);
  chis   = 0.5 * (tmplt->spin1[2] + tmplt->spin2[2]);
  chia   = 0.5 * (tmplt->spin1[2] - tmplt->spin2[2]);
  chi1 = tmplt->mass1 / m;
  chi2 = tmplt->mass2 / m;
  qm_def1 = 1; /* The QM deformability parameters */
  qm_def2 = 1; /* This is 1 for black holes and larger for neutron stars */

  /* Eq. (6.23) in arXiv:0810.5336 */
  pn_beta = (113./12.- 19./3. * eta) * chis + 113./12. * mass_delta * chia;
  
  /* See Eq. (6.24) in arXiv:0810.5336 */
  /* 9b,c,d in arXiv:astro-ph/0504538 */
  pn_sigma = eta * (721./48. *S1z*S2z-247./48.*S1z*S2z);
  pn_sigma += (720*qm_def1 - 1)/96.0 * (chi1*chi1*S1z*S1z);
  pn_sigma += (720*qm_def2 - 1)/96.0 * (chi2*chi2*S2z*S2z);
  pn_sigma -= (240*qm_def1 - 7)/96.0 * (chi1*chi1*S1z*S1z);
  pn_sigma -= (240*qm_def2 - 7)/96.0 * (chi2*chi2*S2z*S2z);

  /* See Eq. (6.25) in arXiv:0810.5336 */
  pn_gamma = (732985./2268. - 24260./81. * eta - 340./9. * eta * eta ) * chis;
  pn_gamma += (732985./2268. +140./9.0 * eta) * chia * mass_delta;

  if ( m <= 0 || eta <= 0 || mu <= 0 )
  {
    ABORT( status, FINDCHIRPH_EMASS, FINDCHIRPH_MSGEMASS );
  }

  /* template dependent normalisation */
  distNorm = 2.0 * LAL_MRSUN_SI / (cannonDist * 1.0e6 * LAL_PC_SI);
  distNorm *= params->dynRange;

  fcTmplt->tmpltNorm = sqrt( (5.0*mu) / 96.0 ) *
    pow( m / (LAL_PI*LAL_PI) , 1.0/3.0 ) *
    pow( LAL_MTSUN_SI / (REAL4) params->deltaT, -1.0/6.0 );
  fcTmplt->tmpltNorm *= fcTmplt->tmpltNorm;
  fcTmplt->tmpltNorm *= distNorm * distNorm;

  if ( lalDebugLevel & LALINFO )
  {
    snprintf( infomsg, sizeof(infomsg) / sizeof(*infomsg),
        "tmpltNorm = %e\n", fcTmplt->tmpltNorm );
    LALInfo( status, infomsg );
  }

  /* Initialize all PN phase coeffs to zero. */
  c0 = c10 = c15 = c20 = c25 = c25Log = 0.;
  c30 = c30Log = c35 = c40P = 0.;

  /* Switch on PN order, set the appropriate phase coeffs for that order */
  switch( params->order )
  {
    case LAL_PNORDER_PSEUDO_FOUR:
      c40P = 3923.0;
    case LAL_PNORDER_THREE_POINT_FIVE:
      c35 = LAL_PI*(77096675.0/254016.0 + eta*378515.0/1512.0
            - eta*eta*74045.0/756.0);
    case LAL_PNORDER_THREE:
      c30 = 11583231236531.0/4694215680.0 - LAL_GAMMA*6848.0/21.0
            - LAL_PI*LAL_PI*640.0/3.0 + eta*(LAL_PI*LAL_PI*2255.0/12.0
            - 15737765635.0/3048192.0) + eta*eta*76055.0/1728.0
            - eta*eta*eta*127825.0/1296.0 - 6848.0*log(4.0)/21.0;
      c30Log = -6848.0/21.0;
    case LAL_PNORDER_TWO_POINT_FIVE:
      c25 = LAL_PI*38645.0/756.0 - LAL_PI*eta*65.0/9.0 - pn_gamma;
      c25Log = 3*c25;
    case LAL_PNORDER_TWO:
      c20 = 15293365.0/508032.0 + eta*(27145.0/504.0 + eta*3085.0/72.0);
      c20 -= 10. * pn_sigma;
      c15 = -16*LAL_PI + 4.*pn_beta;
      c10 = 3715.0/756.0 + eta*55.0/9.0;
      c0  = 3.0/(eta*128.0);
      break;
    default:
      ABORT( status, FINDCHIRPSPH_EORDR, FINDCHIRPSPH_MSGEORDR );
      break;
  }

  /* x1 */
  x1 = pow( LAL_PI * m * LAL_MTSUN_SI * deltaF, -1.0/3.0 );

  /* frequency cutoffs */
  if (params->dynamicTmpltFlow)
  {
    /* Dynamic lower cutoff
     * Work out longest length for template
     * Keep a few extra sample points for safety */
    REAL4 currTime,maxT;
    if (params->maxTempLength > 0)
    {
      /* If the maximum length is given use that */
      maxT = params->maxTempLength;
    }
    else
    {
      /* If not work it out assuming middle of segment is analysed */
      maxT = ((REAL4) params->deltaT * (REAL4) (numPoints-12))/4.;
      maxT -= 0.5 * (REAL4) params->invSpecTrunc * (REAL4) params->deltaT;
    }
    fLow = -1;
    for (f=1; f < 100; f++)
    {
      currTime = XLALFindChirpChirpTime( tmplt->mass1,
                                        tmplt->mass2,
                                        (double) f,
                                        params->order);
      if (currTime < maxT)
      {
        fLow = (REAL4) f;
        break;
      }
    }   
    /* If nothing passed then fail */
    if ( fLow < 0)
    {
      ABORT( status, FINDCHIRPH_EFLOX, FINDCHIRPH_MSGEFLOX );
    }
  }
  else
  {
    fLow = params->fLow;
  }

  kmin = fLow / deltaF > 1 ? fLow / deltaF : 1;
  kmax = tmplt->fFinal / deltaF < numPoints/2 ?
    tmplt->fFinal / deltaF : numPoints/2;

  /* compute psi0: used in range reduction */

  /* This formula works for any PN order, because */
  /* higher order coeffs will be set to zero.     */

    x = x1 * xfac[kmin];
    psi = c0 * ( x * ( c20 + x * ( c15 + x * (c10 + x * x ) ) )
                + c25 - c25Log * log(x) + (1.0/x)
                * ( c30 - c30Log * log(x) + (1.0/x) * ( c35 - (1.0/x)
                * c40P * log(x) ) ) );
    psi0 = -2 * LAL_PI * ( floor ( 0.5 * psi / LAL_PI ) );


  /*
   *
   * calculate the stationary phase chirp
   *
   */

  /* This formula works for any PN order, because */
  /* higher order coeffs will be set to zero.     */

    for ( k = kmin; k < kmax ; ++k )
    {
      REAL4 x_0 = x1 * xfac[k];
      REAL4 psi_0 = c0 * ( x_0 * ( c20 + x_0 * ( c15 + x_0 * (c10 + x_0 * x_0 ) ) )
                  + c25 - c25Log * log(x_0) + (1.0/x_0) * ( c30 - c30Log * log(x_0)
                  + (1.0/x_0) * ( c35 - (1.0/x_0) * c40P * log(x_0) ) ) );
      REAL4 psi1 = psi_0 + psi0;
      REAL4 psi2;

      /* range reduction of psi1 */
      while ( psi1 < -LAL_PI )
      {
        psi1 += 2 * LAL_PI;
        psi0 += 2 * LAL_PI;
      }
      while ( psi1 > LAL_PI )
      {
        psi1 -= 2 * LAL_PI;
        psi0 -= 2 * LAL_PI;
      }

      /* compute approximate sine and cosine of psi1 */
      if ( psi1 < -LAL_PI/2 )
      {
        psi1 = -LAL_PI - psi1;
        psi2 = psi1 * psi1;
        /* XXX minus sign added because of new sign convention for fft */
        expPsi[k] = crectf( -1 - psi2 * ( c2 + psi2 * c4 ), - psi1 * ( 1 + psi2 * ( s2 + psi2 * s4 ) ) );
      }
      else if ( psi1 > LAL_PI/2 )
      {
        psi1 = LAL_PI - psi1;
        psi2 = psi1 * psi1;
        /* XXX minus sign added because of new sign convention for fft */
        expPsi[k] = crectf( -1 - psi2 * ( c2 + psi2 * c4 ), - psi1 * ( 1 + psi2 * ( s2 + psi2 * s4 ) ) );
      }
      else
      {
        psi2 = psi1 * psi1;
        /* XXX minus sign added because of new sign convention for fft */
        expPsi[k] = crectf( 1 + psi2 * ( c2 + psi2 * c4 ), - psi1 * ( 1 + psi2 * ( s2 + psi2 * s4 ) ) );
      }

      /* if reverse chirp bank option selected, switch sign of imag. part */
      if ( params->reverseChirpBank )
      {
        expPsi[k] = crectf( crealf(expPsi[k]), - cimagf(expPsi[k]) );
      }

    }


  /*
   *
   * compute the length of the stationary phase chirp
   *
   */

    tmplt->tC = XLALFindChirpChirpTime( tmplt->mass1,
					tmplt->mass2,
					fLow,
					params->order);

  /* copy the template parameters to the findchirp template structure */
  memcpy( &(fcTmplt->tmplt), tmplt, sizeof(InspiralTemplate) );

  /* normal exit */
  DETATCHSTATUSPTR( status );
  RETURN( status );
}
コード例 #3
0
/**
 * \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 );
}
コード例 #4
0
/**
 * \ingroup LALInspiralBank_h
 * \author Churches, D. K. and Sathyaprakash, B.S.
 * \brief Function which checks whether or not a pair of parameter values are consistent with the search space.
 *
 * Module which checks whether or not a pair of parameter
 * values \f$\tau_{0}\f$ and \f$\tau_{2(3)}\f$ correspond to
 * a user specified range of component masses <tt>(mMin,mMax)</tt> OR to a
 * minimum value of the component masses \c mMin and maximum total
 * mass <tt>MMax.</tt> In the first case chirptimes satisfying the
 * constraint \c mMin\f$\le m_1, m_2 \le\f$\c mMax are accepted
 * as valid systems. In the second cases chirptimes satisfying the
 * constraint \c mMin\f$\le m_1, m_2,\f$ and \c MMax\f$\le m=m_1+m_2\f$
 * are treated as valid.
 *
 * ### Description ###
 *
 * We start with the definition of the chirp times \f$\tau_{0}\f$ and \f$\tau_{3}\f$,
 * \f{equation}{
 * \tau_{0} = \frac{5}{256 (\pi f_{a} )^{8/3} m^{5/3} \eta}
 * \f}
 * and
 * \f{equation}{
 * \tau_{3} = \frac{1}{8 (\pi^{2} f_{a}^{5} )^{1/3} m^{2/3} \eta}
 * \f}
 * These equations may be inverted to yield
 * \f{equation}{
 * m = \frac{5}{32 \pi^{2} f_{a}} \frac{\tau_{3}}{\tau_{0}}
 * \f}
 * and
 * \f{equation}{
 * \eta = \left( \frac{2 \pi^{2}}{25 f_{a}^{3}} \frac{\tau_{0}^{2}}{\tau_{3}^{1/3}}
 * \right)^{5}\f}
 *
 * The individual masses may be calculated as follows.  We have
 * \f{equation}{
 * \label{eq_mass}
 * m = m_{1} + m_{2}
 * \f}
 * and
 * \f{equation}{
 * \label{eq_eta}
 * \eta = \frac{m_{1} m_{2}}{(m_{1} + m_{2})^{2}}
 * \f}
 * From \eqref{eq_mass} we may eliminate either \f$m_{1}\f$ or \f$m_{2}\f$,
 * \f{equation}{
 * m_{1} = m - m_{2}
 * \f}
 * This may be substituted into \eqref{eq_eta} to give
 * \f{equation}{
 * \eta = \frac{(m - m_{2}) m_{2}}{\left[ (m - m_{2}) + m_{2} \right]^{2}}
 * = \frac{(m - m_{2}) m_{2}}{m^{2}}
 * \f}
 * which may be re--arranged to give
 * \f{equation}{
 * m_{2}^{2} - m m_{2} + \eta m^{2} = 0,
 * \f}
 * i.e.
 * \f{equation}{
 * m_{2} = \frac{ m \pm \sqrt{m^{2}(1 - 4 \eta) }}{2}
 * \f}
 * Therefore, since we know that \f$\eta \leq 1/4\f$, real roots are guaranteed.
 * If we had eliminated \f$m_{2}\f$ rather than \f$m_{1}\f$ then we would have arrived at an identical
 * expression for
 * \f$m_{1}\f$, and so of one object has mass
 * \f{equation}{
 * m_{1} = \frac{m + \sqrt{m^{2}(1-4 \eta)}}{2}
 * \f}
 * then the other object must have mass
 * \f{equation}{
 * m_{2} = \frac{m - \sqrt{m^{2}(1-4 \eta)}}{2}
 * \f}
 * This function is also given \c mMin and \c MMax as inputs, which it may
 * use to calculate the minimum value of \f$\eta\f$ which is possible with those inputs,
 * \f{equation}{
 * \eta_{min} = \mathtt{ \frac{mMin(MMax - mMin)}{MMax^{2}} }
 * \f}
 *
 * To recap, the function calculates \f$m\f$, \f$\eta\f$, \f$\eta_{min}\f$ and \f$m_{1,2}\f$.
 * It then checks that
 * \f{equation}{
 * \eta_{min} \leq \eta \leq 1/4
 * \f}
 * and that
 * \f{equation}{
 * m_{1} \geq \mathtt{mMin}
 * \f}
 * and
 * \f{equation}{
 * m_{2} \geq \mathtt{mMin}
 * \f}
 */
void LALInspiralValidParams(
    LALStatus            *status,	/**< LAL status pointer */
    INT4                 *valid,	/**< [out] 0 means invalid template, 1 means valid */
    InspiralBankParams   bankParams,	/**< [in] Input */
    InspiralCoarseBankIn coarseIn	/**< [in] Input */
    )

{

  InspiralTemplate *Pars=NULL;

  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );

  ASSERT( coarseIn.fLower > 0.L, status,
      LALINSPIRALBANKH_ESIZE, LALINSPIRALBANKH_MSGESIZE );

  *valid = 0;

  if ( bankParams.x0 <=0 || bankParams.x1 <=0 )
  {
    LALInfo( status, "x0 or x1 are less than or equal to zero" );
    DETATCHSTATUSPTR( status );
    RETURN( status );
  }

  Pars = (InspiralTemplate *) LALCalloc( 1, sizeof(InspiralTemplate) );
  if ( ! Pars )
  {
    ABORT (status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
  }

  /* First set the chirp times of Pars to be as in bankParams */
  Pars->t0 = bankParams.x0;
  Pars->fLower = coarseIn.fLower;
  switch ( coarseIn.space )
  {
    case Tau0Tau2:
      Pars->t2 = bankParams.x1;
      Pars->massChoice = t02;
      break;
    case Tau0Tau3:
      Pars->t3 = bankParams.x1;
      Pars->massChoice = t03;
      break;
    default:
      ABORT( status, LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
  }

  /* Compute all the parameters, including masses, */
  /* corresponding to (t0,t2/t3)                   */
  LALInspiralParameterCalc( status->statusPtr, Pars );
  CHECKSTATUSPTR( status );

  /* If the masses are in the correct range accept as valid parameters */
  switch (coarseIn.massRange)
  {
    case MinComponentMassMaxTotalMass:
      if (
          Pars->mass1 >= coarseIn.mMin &&
          Pars->mass2 >= coarseIn.mMin &&
          Pars->totalMass <= coarseIn.MMax &&
          Pars->eta <= 0.25 &&
          Pars->eta >= coarseIn.etamin
         )
      {
        *valid = 1;
      }
      break;

    case MinMaxComponentMass:
      if (
          Pars->mass1 >= coarseIn.mMin &&
          Pars->mass2 >= coarseIn.mMin &&
          Pars->mass1 <= coarseIn.mMax &&
          Pars->mass2 <= coarseIn.mMax &&
          Pars->eta <= 0.25 &&
          Pars->eta >= coarseIn.etamin
         )
      {
        *valid = 1;
      }
      break;

    case MinMaxComponentTotalMass:
      if (
          Pars->mass1 >= coarseIn.mMin &&
          Pars->mass2 >= coarseIn.mMin &&
          Pars->totalMass <= coarseIn.MMax &&
          Pars->totalMass >= coarseIn.MMin &&
          Pars->eta <= 0.25 &&
          Pars->eta >= coarseIn.etamin
         )
      {
        *valid = 1;
      }
      break;

    default:
      ABORT(status, 999, "Invalid choice for enum InspiralBankMassRange");
  }

  LALFree( Pars );

  DETATCHSTATUSPTR( status );
  RETURN( status );
}
コード例 #5
0
/**
 * \author Creighton, T. D.
 *
 * \brief Computes the response of a detector to a coherent gravitational wave.
 *
 * This function takes a quasiperiodic gravitational waveform given in
 * <tt>*signal</tt>, and estimates the corresponding response of the
 * detector whose position, orientation, and transfer function are
 * specified in <tt>*detector</tt>.  The result is stored in
 * <tt>*output</tt>.
 *
 * The fields <tt>output-\>epoch</tt>, <tt>output->deltaT</tt>, and
 * <tt>output-\>data</tt> must already be set, in order to specify the time
 * period and sampling rate for which the response is required.  If
 * <tt>output-\>f0</tt> is nonzero, idealized heterodyning is performed (an
 * amount \f$2\pi f_0(t-t_0)\f$ is subtracted from the phase before computing
 * the sinusoid, where \f$t_0\f$ is the heterodyning epoch defined in
 * \c detector).  For the input signal, <tt>signal-\>h</tt> is ignored,
 * and the signal is treated as zero at any time for which either
 * <tt>signal-\>a</tt> or <tt>signal-\>phi</tt> is not defined.
 *
 * This routine will convert <tt>signal-\>position</tt> to equatorial
 * coordinates, if necessary.
 *
 * ### Algorithm ###
 *
 * The routine first accounts for the time delay between the detector and
 * the solar system barycentre, based on the detector position
 * information stored in <tt>*detector</tt> and the propagation direction
 * specified in <tt>*signal</tt>.  Values of the propagation delay are
 * precomuted at fixed intervals and stored in a table, with the
 * intervals \f$\Delta T_\mathrm{delay}\f$ chosen such that the value
 * interpolated from adjacent table entries will never differ from the
 * true value by more than some timing error \f$\sigma_T\f$.  This implies
 * that:
 * \f[
 * \Delta T_\mathrm{delay} \leq \sqrt{
 * \frac{8\sigma_T}{\max\{a/c\}} } \; ,
 * \f]
 * where \f$\max\{a/c\}=1.32\times10^{-10}\mathrm{s}^{-1}\f$ is the maximum
 * acceleration of an Earth-based detector in the barycentric frame.  The
 * total propagation delay also includes Einstein and Shapiro delay, but
 * these are more slowly varying and thus do not constrain the table
 * spacing.  At present, a 400s table spacing is hardwired into the code,
 * implying \f$\sigma_T\approx3\mu\f$s, comparable to the stated accuracy of
 * <tt>LALBarycenter()</tt>.
 *
 * Next, the polarization response functions of the detector
 * \f$F_{+,\times}(\alpha,\delta)\f$ are computed for every 10 minutes of the
 * signal's duration, using the position of the source in <tt>*signal</tt>,
 * the detector information in <tt>*detector</tt>, and the function
 * <tt>LALComputeDetAMResponseSeries()</tt>.  Subsequently, the
 * polarization functions are estimated for each output sample by
 * interpolating these precomputed values.  This guarantees that the
 * interpolated value is accurate to \f$\sim0.1\%\f$.
 *
 * Next, the frequency response of the detector is estimated in the
 * quasiperiodic limit as follows:
 * <ul>
 * <li> At each sample point in <tt>*output</tt>, the propagation delay is
 * computed and added to the sample time, and the instantaneous
 * amplitudes \f$A_1\f$, \f$A_2\f$, frequency \f$f\f$, phase \f$\phi\f$, and polarization
 * shift \f$\Phi\f$ are found by interpolating the nearest values in
 * <tt>signal-\>a</tt>, <tt>signal-\>f</tt>, <tt>signal-\>phi</tt>, and
 * <tt>signal-\>shift</tt>, respectively.  If <tt>signal-\>f</tt> is not
 * defined at that point in time, then \f$f\f$ is estimated by differencing
 * the two nearest values of \f$\phi\f$, as \f$f\approx\Delta\phi/2\pi\Delta
 * t\f$.  If <tt>signal-\>shift</tt> is not defined, then \f$\Phi\f$ is treated as
 * zero.</li>
 * <li> The complex transfer function of the detector the frequency \f$f\f$
 * is found by interpolating <tt>detector-\>transfer</tt>.  The amplitude of
 * the transfer function is multiplied with \f$A_1\f$ and \f$A_2\f$, and the
 * phase of the transfer function is added to \f$\phi\f$,</li>
 * <li> The plus and cross contributions \f$o_+\f$, \f$o_\times\f$ to the
 * detector output are computed as in \eqref{eq_quasiperiodic_hpluscross}
 * of \ref PulsarSimulateCoherentGW_h, but
 * using the response-adjusted amplitudes and phase.</li>
 * <li> The final detector response \f$o\f$ is computed as
 * \f$o=(o_+F_+)+(o_\times F_\times)\f$.</li>
 * </ul>
 *
 * ### A note on interpolation: ###
 *
 * Much of the computational work in this routine involves interpolating
 * various time series to find their values at specific output times.
 * The algorithm is summarized below.
 *
 * Let \f$A_j = A( t_A + j\Delta t_A )\f$ be a sampled time series, which we
 * want to resample at new (output) time intervals \f$t_k = t_0 + k\Delta
 * t\f$.  We first precompute the following quantities:
 * \f{eqnarray}{
 * t_\mathrm{off} & = & \frac{t_0-t_A}{\Delta t_A}  \; , \\
 * dt & = & \frac{\Delta t}{\Delta t_A} \; .
 * \f}
 * Then, for each output sample time \f$t_k\f$, we compute:
 * \f{eqnarray}{
 * t & = & t_\mathrm{off} + k \times dt \; , \\
 * j & = & \lfloor t \rfloor            \; , \\
 * f & = & t - j                        \; ,
 * \f}
 * where \f$\lfloor x\rfloor\f$ is the "floor" function; i.e.\ the largest
 * integer \f$\leq x\f$.  The time series sampled at the new time is then:
 * \f[
 * A(t_k) = f \times A_{j+1} + (1-f) \times A_j \; .
 * \f]
 *
 * ### Notes ###
 *
 * The major computational hit in this routine comes from computing the
 * sine and cosine of the phase angle in
 * \eqref{eq_quasiperiodic_hpluscross} of
 * \ref PulsarSimulateCoherentGW_h.  For better online performance, these can
 * be replaced by other (approximate) trig functions.  Presently the code
 * uses the native \c libm functions by default, or the function
 * <tt>sincosp()</tt> in \c libsunmath \e if this function is
 * available \e and the constant \c ONLINE is defined.
 * Differences at the level of 0.01 begin to appear only for phase
 * arguments greater than \f$10^{14}\f$ or so (corresponding to over 500
 * years between phase epoch and observation time for frequencies of
 * around 1kHz).
 *
 * To activate this feature, be sure that <tt>sunmath.h</tt> and
 * \c libsunmath are on your system, and add <tt>-DONLINE</tt> to the
 * <tt>--with-extra-cppflags</tt> configuration argument.  In future this
 * flag may be used to turn on other efficient trig algorithms on other
 * (non-Solaris) platforms.
 *
 */
void
LALPulsarSimulateCoherentGW( LALStatus        *stat,
                       REAL4TimeSeries  *output,
                       PulsarCoherentGW       *CWsignal,
                       PulsarDetectorResponse *detector )
{
  INT4 i, n;          /* index over output->data, and its final value */
  INT4 nMax;          /* used to store limits on index ranges */
  INT4 fInit, fFinal; /* index range for which CWsignal->f is defined */
  INT4 shiftInit, shiftFinal; /* ditto for CWsignal->shift */
  UINT4 dtDelayBy2;     /* delay table half-interval (s) */
  UINT4 dtPolBy2;       /* polarization table half-interval (s) */
  REAL4 *outData;             /* pointer to output data */
  REAL8 delayMin, delayMax;   /* min and max values of time delay */
  SkyPosition source;         /* source sky position */
  BOOLEAN transfer;  /* 1 if transfer function is specified */
  BOOLEAN fFlag = 0; /* 1 if frequency left detector->transfer range */
  BOOLEAN pFlag = 0; /* 1 if frequency was estimated from phase */

  /* get delay table and polaristion tables half intervals if defined (>0) in
     the PulsarCoherentGW structure otherwise default to 400s for dtDelatBy2 and 300s
     for dtPolBy2 */
  dtDelayBy2 = CWsignal->dtDelayBy2 > 0 ? CWsignal->dtDelayBy2 : 400;
  dtPolBy2   = CWsignal->dtPolBy2   > 0 ? CWsignal->dtPolBy2   : 300;

  /* The amplitude, frequency, phase, polarization shift, polarization
     response, and propagation delay are stored in arrays that must be
     interpolated.  For a quantity x, we define a pointer xData to the
     data array.  At some time t measured in units of output->deltaT,
     the interpolation point in xData is given by ( xOff + t*xDt ),
     where xOff is an offset and xDt is a relative sampling rate. */
  LALDetAMResponseSeries polResponse;
  REAL8Vector *delay = NULL;
  REAL4 *aData, *fData, *shiftData, *plusData, *crossData;
  REAL8 *phiData, *delayData;
  REAL8 aOff, fOff, phiOff, shiftOff, polOff, delayOff;
  REAL8 aDt, fDt, phiDt, shiftDt, polDt, delayDt;

  /* Frequencies in the detector transfer function are interpolated
     similarly, except everything is normalized with respect to
     detector->transfer->deltaF. */
  REAL4Vector *aTransfer = NULL;
  REAL4Vector *phiTransfer = NULL;
  REAL4Vector *phiTemp = NULL;
  REAL4 *aTransData = NULL, *phiTransData = NULL;
  REAL8 f0 = 1.0;
  REAL8 phiFac = 1.0, fFac = 1.0;

  /* Heterodyning phase factor LAL_TWOPI*output->f0*output->deltaT,
     and phase offset at the start of the series
     LAL_TWOPI*output->f0*(time offset). */
  REAL8 heteroFac, phi0;

  /* Variables required by the TCENTRE() macro, above. */
  REAL8 realIndex;
  INT4 intIndex;
  REAL8 indexFrac;

  INITSTATUS(stat);
  ATTATCHSTATUSPTR( stat );

  /* Make sure parameter structures and their fields exist. */
  ASSERT( CWsignal, stat, SIMULATECOHERENTGWH_ENUL,
          SIMULATECOHERENTGWH_MSGENUL );
  if ( !( CWsignal->a ) ) {
    ABORT( stat, SIMULATECOHERENTGWH_ESIG,
           SIMULATECOHERENTGWH_MSGESIG );
  }
  ASSERT( CWsignal->a->data, stat,
          SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  ASSERT( CWsignal->a->data->data, stat,
          SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  if ( !( CWsignal->phi ) ) {
    ABORT( stat, SIMULATECOHERENTGWH_ESIG,
           SIMULATECOHERENTGWH_MSGESIG );
  }
  ASSERT( CWsignal->phi->data, stat,
          SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  ASSERT( CWsignal->phi->data->data, stat,
          SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  if ( CWsignal->f ) {
    ASSERT( CWsignal->f->data, stat,
            SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
    ASSERT( CWsignal->f->data->data, stat,
            SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  }
  if ( CWsignal->shift ) {
    ASSERT( CWsignal->shift->data, stat,
            SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
    ASSERT( CWsignal->shift->data->data, stat,
            SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  }
  ASSERT( detector, stat,
          SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  if ( ( transfer = ( detector->transfer != NULL ) ) ) {
    ASSERT( detector->transfer->data, stat,
            SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
    ASSERT( detector->transfer->data->data, stat,
            SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  }
  ASSERT( output, stat,
          SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  ASSERT( output->data, stat,
          SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
  ASSERT( output->data->data, stat,
          SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );

  /* Check dimensions of amplitude array. */
  ASSERT( CWsignal->a->data->vectorLength == 2, stat,
          SIMULATECOHERENTGWH_EDIM, SIMULATECOHERENTGWH_MSGEDIM );

  /* Make sure we never divide by zero. */
  ASSERT( CWsignal->a->deltaT != 0.0, stat,
          SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
  ASSERT( CWsignal->phi->deltaT != 0.0, stat,
          SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
  aDt = output->deltaT / CWsignal->a->deltaT;
  phiDt = output->deltaT / CWsignal->phi->deltaT;
  ASSERT( aDt != 0.0, stat,
          SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
  ASSERT( phiDt != 0.0, stat,
          SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
  if ( CWsignal->f ) {
    ASSERT( CWsignal->f->deltaT != 0.0, stat,
            SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
    fDt = output->deltaT / CWsignal->f->deltaT;
    ASSERT( fDt != 0.0, stat,
            SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
  } else
    fDt = 0.0;
  if ( CWsignal->shift ) {
    ASSERT( CWsignal->shift->deltaT != 0.0, stat,
            SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
    shiftDt = output->deltaT / CWsignal->shift->deltaT;
    ASSERT( shiftDt != 0.0, stat,
            SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
  } else
    shiftDt = 0.0;
  if ( transfer ) {
    ASSERT( detector->transfer->deltaF != 0.0, stat,
            SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
    fFac = 1.0 / detector->transfer->deltaF;
    phiFac = fFac / ( LAL_TWOPI*CWsignal->phi->deltaT );
    f0 = detector->transfer->f0/detector->transfer->deltaF;
  }
  heteroFac = LAL_TWOPI*output->f0*output->deltaT;
  phi0 = (REAL8)( output->epoch.gpsSeconds -
                  detector->heterodyneEpoch.gpsSeconds );
  phi0 += 0.000000001*(REAL8)( output->epoch.gpsNanoSeconds -
                               detector->heterodyneEpoch.gpsNanoSeconds );
  phi0 *= LAL_TWOPI*output->f0;
  if ( phi0 > 1.0/LAL_REAL8_EPS ) {
    LALWarning( stat, "REAL8 arithmetic is not sufficient to maintain"
                " heterodyne phase to within a radian." );
  }

  /* Check units on input, and set units on output. */
  {
    ASSERT( XLALUnitCompare( &(CWsignal->f->sampleUnits), &lalHertzUnit ) == 0, stat, SIMULATECOHERENTGWH_EUNIT, SIMULATECOHERENTGWH_MSGEUNIT );
    ASSERT( XLALUnitCompare( &(CWsignal->phi->sampleUnits), &lalDimensionlessUnit ) == 0, stat, SIMULATECOHERENTGWH_EUNIT, SIMULATECOHERENTGWH_MSGEUNIT );
    if( CWsignal->shift ) {
      ASSERT( XLALUnitCompare( &(CWsignal->shift->sampleUnits), &lalDimensionlessUnit ) == 0, stat, SIMULATECOHERENTGWH_EUNIT, SIMULATECOHERENTGWH_MSGEUNIT );
    }
    if ( transfer ) {
      if ( XLALUnitMultiply( &(output->sampleUnits), &(CWsignal->a->sampleUnits), &(detector->transfer->sampleUnits) ) == NULL ) {
        ABORT( stat, SIMULATECOHERENTGWH_EUNIT, SIMULATECOHERENTGWH_MSGEUNIT );
      }
    } else {
      output->sampleUnits = CWsignal->a->sampleUnits;
    }
    snprintf( output->name, LALNameLength, "response to %s", CWsignal->a->name );
  }

  /* Define temporary variables to access the data of CWsignal->a,
     CWsignal->f, and CWsignal->phi. */
  aData = CWsignal->a->data->data;
  INT4 aLen = CWsignal->a->data->length * CWsignal->a->data->vectorLength;
  phiData = CWsignal->phi->data->data;
  INT4 phiLen = CWsignal->phi->data->length;
  outData = output->data->data;
  INT4 fLen=0, shiftLen=0;
  if ( CWsignal->f )
    {
      fData = CWsignal->f->data->data;
      fLen = CWsignal->f->data->length;
    }
  else
    {
      fData = NULL;
    }

  if ( CWsignal->shift )
    {
      shiftData = CWsignal->shift->data->data;
      shiftLen = CWsignal->shift->data->length;
    }
  else
    {
      shiftData = NULL;
    }

  /* Convert source position to equatorial coordinates, if
     required. */
  if ( detector->site ) {
    source = CWsignal->position;
    if ( source.system != COORDINATESYSTEM_EQUATORIAL ) {
      ConvertSkyParams params; /* parameters for conversion */
      EarthPosition location;  /* location of detector */
      params.gpsTime = &( output->epoch );
      params.system = COORDINATESYSTEM_EQUATORIAL;
      if ( source.system == COORDINATESYSTEM_HORIZON ) {
        params.zenith = &( location.geodetic );
        location.x = detector->site->location[0];
        location.y = detector->site->location[1];
        location.z = detector->site->location[2];
        TRY( LALGeocentricToGeodetic( stat->statusPtr, &location ),
             stat );
      }
      TRY( LALConvertSkyCoordinates( stat->statusPtr, &source,
                                     &source, &params ), stat );
    }
  }

  /* Generate the table of propagation delays.
     dtDelayBy2 = (UINT4)( 38924.9/sqrt( output->f0 +
     1.0/output->deltaT ) ); */
  delayDt = output->deltaT/( 2.0*dtDelayBy2 );
  nMax = (UINT4)( output->data->length*delayDt ) + 3;
  TRY( LALDCreateVector( stat->statusPtr, &delay, nMax ), stat );
  delayData = delay->data;

  /* Compute delay from solar system barycentre. */
  if ( detector->site && detector->ephemerides ) {
    LIGOTimeGPS gpsTime;   /* detector time when we compute delay */
    EarthState state;      /* Earth position info at that time */
    BarycenterInput input; /* input structure to LALBarycenter() */
    EmissionTime emit;     /* output structure from LALBarycenter() */

    /* Arrange nested pointers, and set initial values. */
    gpsTime = input.tgps = output->epoch;
    gpsTime.gpsSeconds -= dtDelayBy2;
    input.tgps.gpsSeconds -= dtDelayBy2;
    input.site = *(detector->site);
    for ( i = 0; i < 3; i++ )
      input.site.location[i] /= LAL_C_SI;
    input.alpha = source.longitude;
    input.delta = source.latitude;
    input.dInv = 0.0;
    delayMin = delayMax = 1.1*LAL_AU_SI/( LAL_C_SI*output->deltaT );
    delayMax *= -1;

    /* Compute table. */
    for ( i = 0; i < nMax; i++ ) {
      REAL8 tDelay; /* propagation time */
      LALBarycenterEarth( stat->statusPtr, &state, &gpsTime,
                          detector->ephemerides );
      BEGINFAIL( stat )
        TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
      ENDFAIL( stat );
      LALBarycenter( stat->statusPtr, &emit, &input, &state );
      BEGINFAIL( stat )
        TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
      ENDFAIL( stat );
      delayData[i] = tDelay = emit.deltaT/output->deltaT;
      if ( tDelay < delayMin )
        delayMin = tDelay;
      if ( tDelay > delayMax )
        delayMax = tDelay;
      gpsTime.gpsSeconds += 2*dtDelayBy2;
      input.tgps.gpsSeconds += 2*dtDelayBy2;
    }
  }

  /* No information from which to compute delays. */
  else {
    LALInfo( stat, "Detector site and ephemerides absent; simulating hplus with no"
             " propagation delays" );
    memset( delayData, 0, nMax*sizeof(REAL8) );
    delayMin = delayMax = 0.0;
  }

  /* Generate the table of polarization response functions. */
  polDt = output->deltaT/( 2.0*dtPolBy2 );
  nMax = (UINT4)( output->data->length*polDt ) + 3;
  memset( &polResponse, 0, sizeof( LALDetAMResponseSeries ) );
  polResponse.pPlus = (REAL4TimeSeries *)
    LALMalloc( sizeof(REAL4TimeSeries) );
  polResponse.pCross = (REAL4TimeSeries *)
    LALMalloc( sizeof(REAL4TimeSeries) );
  polResponse.pScalar = (REAL4TimeSeries *)
    LALMalloc( sizeof(REAL4TimeSeries) );
  if ( !polResponse.pPlus || !polResponse.pCross ||
       !polResponse.pScalar ) {
    if ( polResponse.pPlus )
      LALFree( polResponse.pPlus );
    if ( polResponse.pCross )
      LALFree( polResponse.pCross );
    if ( polResponse.pScalar )
      LALFree( polResponse.pScalar );
    TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
    ABORT( stat, SIMULATECOHERENTGWH_EMEM,
           SIMULATECOHERENTGWH_MSGEMEM );
  }
  memset( polResponse.pPlus, 0, sizeof(REAL4TimeSeries) );
  memset( polResponse.pCross, 0, sizeof(REAL4TimeSeries) );
  memset( polResponse.pScalar, 0, sizeof(REAL4TimeSeries) );
  LALSCreateVector( stat->statusPtr, &( polResponse.pPlus->data ),
                    nMax );
  BEGINFAIL( stat ) {
    LALFree( polResponse.pPlus );
    LALFree( polResponse.pCross );
    LALFree( polResponse.pScalar );
    TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
  } ENDFAIL( stat );
  LALSCreateVector( stat->statusPtr, &( polResponse.pCross->data ),
                    nMax );
  BEGINFAIL( stat ) {
    TRY( LALSDestroyVector( stat->statusPtr,
                            &( polResponse.pPlus->data ) ), stat );
    LALFree( polResponse.pPlus );
    LALFree( polResponse.pCross );
    LALFree( polResponse.pScalar );
    TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
  } ENDFAIL( stat );
  LALSCreateVector( stat->statusPtr, &( polResponse.pScalar->data ),
                    nMax );
  BEGINFAIL( stat ) {
    TRY( LALSDestroyVector( stat->statusPtr,
                            &( polResponse.pPlus->data ) ), stat );
    TRY( LALSDestroyVector( stat->statusPtr,
                            &( polResponse.pCross->data ) ), stat );
    LALFree( polResponse.pPlus );
    LALFree( polResponse.pCross );
    LALFree( polResponse.pScalar );
    TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
  } ENDFAIL( stat );
  plusData = polResponse.pPlus->data->data;
  crossData = polResponse.pCross->data->data;
  INT4 plusLen = polResponse.pPlus->data->length;
  INT4 crossLen = polResponse.pCross->data->length;
  if ( plusLen != crossLen ) {
    XLALPrintError ("plusLen = %d != crossLen = %d\n", plusLen, crossLen );
    ABORT ( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
  }

  if ( detector->site ) {
    LALSource polSource;     /* position and polarization angle */
    LALDetAndSource input;            /* response input structure */
    LALTimeIntervalAndNSample params; /* response parameter structure */

    /* Arrange nested pointers, and set initial values. */
    polSource.equatorialCoords = source;
    polSource.orientation = (REAL8)( CWsignal->psi );
    input.pSource = &polSource;
    input.pDetector = detector->site;
    params.epoch = output->epoch;
    params.epoch.gpsSeconds -= dtPolBy2;
    params.deltaT = 2.0*dtPolBy2;
    params.nSample = nMax;

    /* Compute table of responses. */
    LALComputeDetAMResponseSeries( stat->statusPtr, &polResponse,
                                   &input, &params );
    BEGINFAIL( stat ) {
      TRY( LALSDestroyVector( stat->statusPtr,
                              &( polResponse.pPlus->data ) ), stat );
      TRY( LALSDestroyVector( stat->statusPtr,
                              &( polResponse.pCross->data ) ), stat );
      TRY( LALSDestroyVector( stat->statusPtr,
                              &( polResponse.pScalar->data ) ), stat );
      LALFree( polResponse.pPlus );
      LALFree( polResponse.pCross );
      LALFree( polResponse.pScalar );
      TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
    } ENDFAIL( stat );
  } else {
コード例 #6
0
void
LALFindChirpBCVCFilterSegment (
    LALStatus                  *status,
    SnglInspiralTable         **eventList,
    FindChirpFilterInput       *input,
    FindChirpFilterParams      *params
    )

{
  UINT4                 j, k, kFinal/*, kOpt*/;
  UINT4                 numPoints;
  UINT4                 deltaEventIndex = 0;
  UINT4                 ignoreIndex;
  REAL4                 UNUSED myfmin;
  REAL4                 deltaT, deltaF;
  REAL4                 norm;
  REAL4                 modqsqThresh;
  REAL4                 rhosqThresh;
  REAL4                 mismatch;
  REAL4                 UNUSED chisqThreshFac = 0;
  /* REAL4                 modChisqThresh; */
  UINT4                 numChisqBins = 0;
  UINT4                 eventStartIdx = 0;
  UINT4                UNUSED *chisqBin      = NULL;
  UINT4                UNUSED *chisqBinBCV   = NULL;
  REAL4                 chirpTime     = 0;
  REAL4                UNUSED *tmpltPower    = NULL;
  REAL4                UNUSED *tmpltPowerBCV = NULL;
  COMPLEX8             *qtilde        = NULL;
  COMPLEX8             *qtildeBCV     = NULL;
  COMPLEX8             *q             = NULL;
  COMPLEX8             *qBCV          = NULL;
  COMPLEX8             *inputData     = NULL;
  COMPLEX8             *inputDataBCV = NULL;
  COMPLEX8             *tmpltSignal   = NULL;
  SnglInspiralTable    *thisEvent     = NULL;
  REAL4                 a1 = 0.0;
  REAL4                 b1 = 0.0;
  REAL4                 b2 = 0.0;
  REAL4                 UNUSED templateNorm;
  REAL4                 m, psi0, psi3, fFinal;



  /* some declarations for the constrained  BCV codet (Thomas)*/
  REAL4         alphaUnity;     /* intermediate variable to get thetab  */
  REAL4         thetab;         /* critical angle for constraint        */
  REAL4         thetav;         /* angle between V1 and V2              */
  REAL4         V0;             /* intermediate quantity to compute rho */
  REAL4         V1;             /* intermediate quantity to compute rho */
  REAL4         V2;             /* intermediate quantity to compute rho */
  REAL4         alphaC;         /* constraint alpha value               */
  REAL4         alphaU;         /* unconstraint alpha value for fun     */
  REAL4         rhosqConstraint;
  REAL4         rhosqUnconstraint;      /* before constraint            */
  REAL4         deltaTPower2By3;        /* alias variable               */
  REAL4         deltaTPower1By6;        /* alias variable               */
  REAL4         ThreeByFive = 3.0/5.0;
  REAL4         FiveByThree = 5.0/3.0;
  REAL4         mchirp;
  REAL4         eta;
  REAL4         SQRTNormA1;             /* an alias                     */

  /* Most of the code below is identical and should be identical to
   * FindChirpBCVFilter.c execpt when entering the constraint code.
   * */


  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );

  /*
   *
   * check that the arguments are reasonable
   *
   */

  /* make sure the output handle exists, but points to a null pointer */
  ASSERT( eventList, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT( !*eventList, status, FINDCHIRPH_ENNUL, FINDCHIRPH_MSGENNUL );

  /* make sure that the parameter structure exists */
  ASSERT( params, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );

  /* check that the filter parameters are reasonable */
  ASSERT( params->deltaT > 0, status,
      FINDCHIRPH_EDTZO, FINDCHIRPH_MSGEDTZO );
  ASSERT( params->rhosqThresh >= 0, status,
      FINDCHIRPH_ERHOT, FINDCHIRPH_MSGERHOT );
  ASSERT( params->chisqThresh >= 0, status,
      FINDCHIRPH_ECHIT, FINDCHIRPH_MSGECHIT );

  /* check that the fft plan exists */
  ASSERT( params->invPlan, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );

  /* check that the workspace vectors exist */
  ASSERT(params->qVec, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT(params->qVec->data, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT(params->qtildeVec, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT(params->qtildeVec->data,status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL);
  ASSERT(params->qVecBCV, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT(params->qVecBCV->data, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT(params->qtildeVecBCV, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT(params->qtildeVecBCV->data,status, FINDCHIRPH_ENULL,
      FINDCHIRPH_MSGENULL);

  /* check that the chisq parameter and input structures exist */
  ASSERT( params->chisqParams, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT( params->chisqInput,   status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT( params->chisqInputBCV,status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );

  /* if a rhosqVec vector has been created, check we can store data in it */
  if ( params->rhosqVec )
  {
    ASSERT( params->rhosqVec->data->data, status,
        FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
    ASSERT( params->rhosqVec->data, status,
        FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  }

  /* if a chisqVec vector has been created, check we can store data in it */
  if ( params->chisqVec )
    {
      ASSERT( params->chisqVec->data, status,
          FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  }

  /* make sure that the input structure exists */
  ASSERT( input, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );

  /* make sure that the input structure contains some input */
  ASSERT( input->fcTmplt, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );
  ASSERT( input->segment, status, FINDCHIRPH_ENULL, FINDCHIRPH_MSGENULL );

  /* make sure the filter has been initialized for the correct approximant */
  if ( params->approximant != BCV )
  {
    ABORT( status, FINDCHIRPH_EAPRX, FINDCHIRPH_MSGEAPRX );
  }

  /* make sure that the template and the segment are both BCVC */
  ASSERT( input->fcTmplt->tmplt.approximant == BCV, status,
      FINDCHIRPH_EAPRX, FINDCHIRPH_MSGEAPRX );
  ASSERT( input->segment->approximant == BCV, status,
      FINDCHIRPH_EAPRX, FINDCHIRPH_MSGEAPRX );


  /*
   *
   * point local pointers to input and output pointers
   *
   */


  /* workspace vectors */
  q    = params->qVec->data;
  qBCV = params->qVecBCV->data;
  qtilde    = params->qtildeVec->data;
  qtildeBCV = params->qtildeVecBCV->data;


  /* template and data */
  inputData     = input->segment->data->data->data;
  inputDataBCV  = input->segment->dataBCV->data->data;
  tmpltSignal   = input->fcTmplt->data->data;
  templateNorm  = input->fcTmplt->tmpltNorm;
  deltaT        = params->deltaT;

  /* some aliases for later use (Thomas) */
  deltaTPower2By3 = pow(params->deltaT, 2./3.);
  deltaTPower1By6 = pow(params->deltaT, 1./6.);

  /* the length of the chisq bin vec is the number of bin   */
  /* _boundaries_ so the number of chisq bins is length - 1 */

  if ( input->segment->chisqBinVec->length )
    {
    /*
     * at this point, numChisqBins is only used as a parameter
     * on the basis of which we decide whether we will do a chisq test or not.
     * the actual number of chisq bins is:
     */
    numChisqBins = input->segment->chisqBinVec->length - 1;
    chisqBin    = input->segment->chisqBinVec->data;
    chisqBinBCV = input->segment->chisqBinVecBCV->data;
    tmpltPower    = input->segment->tmpltPowerVec->data;
    tmpltPowerBCV = input->segment->tmpltPowerVecBCV->data;
  }


  /* number of points in a segment */
  if (params->qVec->length != params->qVecBCV->length)
  {
    ABORT(status, FINDCHIRPBCVH_EQLEN, FINDCHIRPBCVH_MSGEQLEN);
  }
  numPoints = params->qVec->length;

  /*
   * template parameters, since FindChirpBCVCFilterSegment is run
   * for every template
   */
  psi0   = input->fcTmplt->tmplt.psi0;
  psi3   = input->fcTmplt->tmplt.psi3;
  fFinal = input->fcTmplt->tmplt.fFinal;

  {
    /* Calculate deltaEventIndex : the only acceptable clustering */
    /* is "window" method, for BCV                                */
    if ( params->clusterMethod == FindChirpClustering_window )
    {
      deltaEventIndex=(UINT4) rint((params->clusterWindow/params->deltaT)+1.0);
    }
    else if ( params->clusterMethod == FindChirpClustering_tmplt )
    {
      ABORT( status, FINDCHIRPBCVH_ECLUW, FINDCHIRPBCVH_MSGECLUW );
    }


    /* ignore corrupted data at start and end */
    ignoreIndex = ( input->segment->invSpecTrunc / 2 ) + deltaEventIndex;

    if ( lalDebugLevel & LALINFO )
    {
      CHAR newinfomsg[256];


      snprintf( newinfomsg, XLAL_NUM_ELEM(newinfomsg),
          "chirp time = %e seconds => %d points\n"
          "invSpecTrunc = %d => ignoreIndex = %d\n",
          chirpTime, deltaEventIndex,
          input->segment->invSpecTrunc, ignoreIndex );
      LALInfo( status, newinfomsg );
    }

    /* XXX check that we are not filtering corrupted data XXX */
    /* XXX this is hardwired to 1/4 segment length        XXX */
    if ( ignoreIndex > numPoints / 4 )
    {
      ABORT( status, FINDCHIRPH_ECRUP, FINDCHIRPH_MSGECRUP );
    }
    /* XXX reset ignoreIndex to one quarter of a segment XXX */
    ignoreIndex = numPoints / 4;
 }

  if ( lalDebugLevel & LALINFO )
  {
    CHAR newinfomsg[256];

    snprintf( newinfomsg, XLAL_NUM_ELEM(newinfomsg),
        "filtering from %d to %d\n",
        ignoreIndex, numPoints - ignoreIndex );
    LALInfo( status, newinfomsg );
  }

  /* k that corresponds to fFinal */
  deltaF = 1.0 / ( (REAL4) params->deltaT * (REAL4) numPoints );
  kFinal = fFinal / deltaF < numPoints/2 ? floor(fFinal / deltaF)
    : floor(numPoints/2);
  myfmin = input->segment->fLow;

  /* assign the values to a1, b1 and b2 */
  a1 = input->segment->a1->data[kFinal];
  b1 = input->segment->b1->data[kFinal];
  b2 = input->segment->b2->data[kFinal];


  /*
   * if one or more of a1, b1 and b2 are 0, output a message
   */

  if ( !fabs(a1) || !fabs(b1) || !fabs(b2) )
  {
    if ( lalDebugLevel & LALINFO )
    {
       CHAR newinfomsg[256];
       snprintf( newinfomsg, XLAL_NUM_ELEM(newinfomsg),
              "a1 = %e b1 = %e b2 = %e\n"
              "fFinal = %e deltaF = %e numPoints = %d => kFinal = %d\n",
               a1, b1, b2, fFinal, deltaF, numPoints, kFinal );
       LALInfo( status, newinfomsg );
    }
  }

  /*
   *
   * compute qtilde, qtildeBCVC, and q, qBCVC
   * using the correct combination of inputData and inputDataBCVC
   *
   */


  memset( qtilde,    0, numPoints * sizeof(COMPLEX8) );
  memset( qtildeBCV, 0, numPoints * sizeof(COMPLEX8) );

  /* qtilde positive frequency, not DC or nyquist */
  for ( k = 1; k < numPoints/2; ++k )
  {
    REAL4 r    = a1 * crealf(inputData[k]);
    REAL4 s    = a1 * cimagf(inputData[k]);
    REAL4 rBCV = b1 * crealf(inputData[k]) + b2 * crealf(inputDataBCV[k]);
    REAL4 sBCV = b1 * cimagf(inputData[k]) + b2 * cimagf(inputDataBCV[k]);
    REAL4 x = crealf(tmpltSignal[k]);
    REAL4 y = 0.0 - cimagf(tmpltSignal[k]); /* note complex conjugate */

    qtilde[k] = crectf( r * x - s * y, r * y + s * x );
    qtildeBCV[k] = crectf( rBCV * x - sBCV * y, rBCV * y + sBCV * x );
  }

  /* inverse fft to get q, and qBCV */
  LALCOMPLEX8VectorFFT( status->statusPtr, params->qVec,
      params->qtildeVec, params->invPlan );
  CHECKSTATUSPTR( status );
  LALCOMPLEX8VectorFFT( status->statusPtr, params->qVecBCV,
      params->qtildeVecBCV, params->invPlan );
  CHECKSTATUSPTR( status );



  /*
   *
   * calculate signal to noise squared
   *
   */



  /* if full snrsq vector is required, set it to zero */
  if ( params->rhosqVec )
    memset( params->rhosqVec->data->data, 0, numPoints * sizeof( REAL4 ) );

  rhosqThresh = params->rhosqThresh;

  norm = deltaT / ((REAL4) numPoints) ;
  /* notice difference from corresponding factor in the sp templates: */
  /* no factor of 4 (taken care of in inputData and inputDataBCV      */
  /* and no segnorm, since we already multiplied by a1, b1 and b2.    */


  /* normalized snr threhold */
  modqsqThresh = rhosqThresh / norm ;

  /* we threshold on the "modified" chisq threshold computed from       */
  /*   chisqThreshFac = delta^2 * norm / p                              */
  /*   rho^2 = norm * modqsq                                            */
  /*                                                                    */
  /* So we actually threshold on                                        */
  /*                                                                    */
  /*    r^2 < chisqThresh * ( 1 + modqsq * chisqThreshFac )             */
  /*                                                                    */
  /* which is the same as thresholding on                               */
  /*    r^2 < chisqThresh * ( 1 + rho^2 * delta^2 / p )                 */
  /* and since                                                          */
  /*    chisq = p r^2                                                   */
  /* this is equivalent to thresholding on                              */
  /*    chisq < chisqThresh * ( p + rho^2 delta^2 )                     */
  /*                                                                    */
  /* The raw chisq is stored in the database. this quantity is chisq    */
  /* distributed with 2p-2 degrees of freedom.                          */

  mismatch = 1.0 - input->fcTmplt->tmplt.minMatch;
  if ( !numChisqBins )
  {
    chisqThreshFac = norm * mismatch * mismatch / (REAL4) numChisqBins;
  }

  /* if full snrsq vector is required, store the snrsq */
  if ( params->rhosqVec )
  {
    memcpy( params->rhosqVec->name, input->segment->data->name,
        LALNameLength * sizeof(CHAR) );
    memcpy( &(params->rhosqVec->epoch), &(input->segment->data->epoch),
        sizeof(LIGOTimeGPS) );
    params->rhosqVec->deltaT = input->segment->deltaT;

    for ( j = 0; j < numPoints; ++j )
    {
      REAL4 modqsqSP  = crealf(q[j]) * crealf(q[j]) + cimagf(q[j]) * cimagf(q[j]) ;
      REAL4 modqsqBCV = crealf(qBCV[j]) * crealf(qBCV[j]) + cimagf(qBCV[j]) * cimagf(qBCV[j]) ;
      REAL4 ImProd = 2.0 * ( - crealf(q[j]) * cimagf(qBCV[j]) + crealf(qBCV[j]) * cimagf(q[j]) ) ;

      REAL4 newmodqsq = ( 0.5 * sqrt( modqsqSP + modqsqBCV + ImProd ) +
          0.5 * sqrt( modqsqSP + modqsqBCV - ImProd ) ) *
        ( 0.5 * sqrt( modqsqSP + modqsqBCV + ImProd ) +
          0.5 * sqrt( modqsqSP + modqsqBCV - ImProd ) ) ;

      params->rhosqVec->data->data[j] = norm * newmodqsq;
    }
  }

  /*
   * Here starts the actual constraint code.
   * */

  /* First for debugging purpose. dont erase  (Thomas)*/

/*
   {
    FILE  *V0File, *V1File,*V2File,
    *alphaFile,  *rho1File, *rho2File, *rho3File,
    *phaseFile, *phaseFileE, *alphaFileE,  *rhoFile, *thetavFile;

    fprintf(stderr, "a1=%e b1=%e b2 =%e fFinal=%e deltTa=%e\n", a1, b1, b2, fFinal, params->deltaT);

   alphaUnity = pow(fFinal, -2./3.)*pow(params->deltaT,-2./3.);


   thetab   = -(a1 * alphaUnity)/(b2+b1*alphaUnity);
   thetab   = atan(thetab);
   fprintf(stderr, "alphaMax -->thetab = %e\n", thetab);

   V0File=fopen("V0File.dat","w");
   V1File=fopen("V1File.dat","w");
   V2File=fopen("V2File.dat","w");
   rho1File=fopen("rho1File.dat","w");
   rho2File=fopen("rho2File.dat","w");
   rho3File=fopen("rho3File.dat","w");
   alphaFile=fopen("alphaFile.dat","w");
   thetavFile=fopen("thetavFile.dat","w");
   phaseFile=fopen("phaseFile.dat","w");

   phaseFileE=fopen("phaseFileE.dat","w");
   alphaFileE=fopen("alphaFileE.dat","w");

   rhoFile=fopen("rhoFile.dat","w");

   for ( j = 0; j < numPoints; ++j )
     {
       REAL4 K1 = q[j].re;
       REAL4 K2 = qBCV[j].re;
       REAL4 K3 = q[j].im;
       REAL4 K4 = qBCV[j].im;

       REAL4 V0 = q[j].re * q[j].re
	 + qBCV[j].re * qBCV[j].re
	 + q[j].im * q[j].im
	 + qBCV[j].im * qBCV[j].im ;

       REAL4 V1 = q[j].re * q[j].re
	 + q[j].im * q[j].im
	 - qBCV[j].im * qBCV[j].im
	 -  qBCV[j].re * qBCV[j].re;

       REAL4 V2 =  2 * ( q[j].re * qBCV[j].re + qBCV [j].im * q[j].im);

       REAL4 rhosqUnconstraint = 0.5 * (V0+sqrt(V1*V1+V2*V2));

       REAL4 thetav = atan2(V2,V1);

       REAL4 Num1 = K2 + K3 ;
       REAL4 Num2 = K2 - K3 ;
       REAL4 Den1 = K1 - K4;
       REAL4 Den2 = K1 + K4;

       REAL4 InvTan1 = (REAL4) atan2(Num1, Den1);
       REAL4 InvTan2 = (REAL4) atan2(Num2, Den2);

       REAL4 omega = 0.5 * InvTan1 + 0.5 * InvTan2 ;

       fprintf(V0File,"%e\n",V0);
       fprintf(V1File,"%e\n",V1);
       fprintf(V2File,"%e\n",V2);


       fprintf(phaseFileE,"%e\n",0.5 * InvTan1 + 0.5 * InvTan2);


       fprintf(alphaFileE,"%e\n", (- b2 * tan(omega)
				   / ( a1 + b1 * tan(omega)))
	       *pow(params->deltaT*fFinal, 2.0/3.0) );


       fprintf(alphaFile,"%e\n", -(b2 * tan(.5*thetav))
	       / (a1 + b1* tan(.5*thetav))*pow(params->deltaT*fFinal, 2.0/3.0));
       fprintf(phaseFile,"%e\n", thetav);


       fprintf(rho1File,"%e\n",sqrt(rhosqUnconstraint*norm));
       fprintf(rho2File,"%e\n",sqrt(.5*(V0 + V1)*norm));
       fprintf(rho3File,"%e\n",sqrt((V0+V1*cos(2*thetab)+V2*sin(2*thetab))/2.*norm));

       if (thetab >= 0){
	 if ( 0  <= thetav && thetav <= 2 * thetab){
	   rhosqConstraint  = sqrt(0.5 * (V0+sqrt(V1*V1+V2*V2)));
	   fprintf(rhoFile,"%e\n",rhosqConstraint);

	 }
	 else if (thetab-LAL_PI <= thetav && thetav < 0) {
	   rhosqConstraint = sqrt((V0 + V1)/2.);
	   fprintf(rhoFile,"%e\n",rhosqConstraint);
	 }
	 else if( (2*thetab  < thetav && thetav<LAL_PI )
		  || thetab-LAL_PI>thetav){
	   rhosqConstraint =sqrt((V0+V1*cos(2*thetab)+V2*sin(2*thetab))/2.);;
	   fprintf(rhoFile,"%e\n",rhosqConstraint);

	 }
	 else
	   {
	     fprintf(stderr,"must not enter here  thetav = %e thetab=%e\n ", thetav , thetab);
	     exit(0);
	   }
       }
       else{
	 if ( 2*thetab  <= thetav && thetav <= 0){
	   rhosqConstraint  = 0.5 * (V0+sqrt(V1*V1+V2*V2));
	   fprintf(rhoFile,"%e\n",sqrt(norm*rhosqConstraint));
	 }
	 else if (0 < thetav &&  thetav  <= LAL_PI +thetab) {
	   rhosqConstraint = (V0 + V1)/2.;
	   fprintf(rhoFile,"%e\n",sqrt(norm*rhosqConstraint));
	 }
        else if( (-LAL_PI-1e-4  <= thetav && thetav < 2*thetab ) ||
	       (LAL_PI +thetab <= thetav && thetav <= LAL_PI+1e-4))
        {
	   rhosqConstraint =(V0+V1*cos(2*thetab)+V2*sin(2*thetab))/2.;
	   fprintf(rhoFile,"%e\n",sqrt(norm*rhosqConstraint));
	 }
	 else
	   {
	     fprintf(stderr,"must not enter herethetav = %e thetab=%e %e %e %d\n ",thetav , thetab, V1, V2);
	     fprintf(rhoFile,"%e\n",-1);
	   }
       }

     }
   fclose(rhoFile);
   fclose(alphaFileE);
   fclose(thetavFile);

   fclose(V0File);
   fclose(V1File);
   fclose(V2File);

   fclose(alphaFile);
   fclose(phaseFile);
   fclose(phaseFileE);
   fclose(rho1File);
   fclose(rho2File);
   fclose(rho3File);
 }

*/


  /* let us create some aliases which are going to be constantly used in the
   * storage of the results. */
  mchirp = (1.0 / LAL_MTSUN_SI) * LAL_1_PI *
        pow( 3.0 / 128.0 / psi0 , ThreeByFive );
  m =  fabs(psi3) /
    (16.0 * LAL_MTSUN_SI * LAL_PI * LAL_PI * psi0) ;
  eta = 3.0 / (128.0*psi0 *
       pow( (m*LAL_MTSUN_SI*LAL_PI), FiveByThree) );
  SQRTNormA1 = sqrt(norm / a1);


  /* BCV Constraint code (Thomas)*/
  /* first we compute what alphaF=1 corresponds to */
  alphaUnity = pow(fFinal, -2./3.) * pow(params->deltaT,-2./3.);
  /* and what is its corresponding angle thetab */
  thetab   = -(a1 * alphaUnity) / (b2 + b1*alphaUnity);
  thetab   = atan(thetab);

  if ( lalDebugLevel & LALINFO )
    {
      CHAR newinfomsg[256];
      snprintf( newinfomsg, XLAL_NUM_ELEM(newinfomsg),
		   "thetab = %e and alphaUnity = %e\n",
		   thetab, alphaUnity);
      LALInfo( status, newinfomsg );
    }

  /* look for an event in the filter output */
  for ( j = ignoreIndex; j < numPoints - ignoreIndex; ++j )
  {
    /* First, we compute the quantities V0, V1 and V2 */
    V0 = crealf(q[j]) * crealf(q[j])
      + crealf(qBCV[j]) * crealf(qBCV[j])
      + cimagf(q[j]) * cimagf(q[j])
      + cimagf(qBCV[j]) * cimagf(qBCV[j]) ;

    V1 = crealf(q[j]) * crealf(q[j])
      + cimagf(q[j]) * cimagf(q[j])
      - cimagf(qBCV[j]) * cimagf(qBCV[j])
      -  crealf(qBCV[j]) * crealf(qBCV[j]);

    V2 =  2 * ( crealf(q[j]) * crealf(qBCV[j]) + cimagf(qBCV [j]) * cimagf(q[j]));

    /* and finally the unconstraint SNR which is equivalent to
     * the unconstrained BCV situation */
    rhosqUnconstraint = 0.5*( V0 + sqrt(V1*V1 + V2*V2));

    /* We also get the angle between V1 and V2 vectors used later in the
     * constraint part of BCV filtering. */
    thetav = atan2(V2,V1);

    /* Now, we can compare the angle with thetab. Taking care of the angle is
     * quite important.  */
    if (thetab >= 0){
      if ( 0  <= thetav && thetav <= 2 * thetab){
        rhosqConstraint = rhosqUnconstraint;
      }
      else if (thetab-LAL_PI <= thetav && thetav < 0) {
        rhosqConstraint = (V0 + V1)/2.;
      }
     else if( (2*thetab  < thetav && thetav<=LAL_PI+1e-4 )
		 || (-LAL_PI-1e-4<=thetav && thetav < -LAL_PI+thetab)){
        rhosqConstraint =(V0+V1*cos(2*thetab)+V2*sin(2*thetab))/2.;;
      }
      else
      {
	CHAR newinfomsg[256];
	snprintf( newinfomsg, XLAL_NUM_ELEM(newinfomsg),
		     "thetab = %e and thetav = %e\n"
		     "thetav not in the range allowed...V1= %e and V2 = %e\n",
		     thetab, thetav, V1, V2 );
	LALInfo( status, newinfomsg );
        ABORT( status, FINDCHIRPH_EALOC, FINDCHIRPH_MSGEALOC );
      }
    }
    else{
      if ( 2*thetab  <= thetav && thetav <= 0){
        rhosqConstraint = rhosqUnconstraint;
      }
      else if (0 < thetav &&  thetav  <= LAL_PI+thetab ) {
        rhosqConstraint = (V0 + V1)/2.;
      }
      else if( (-LAL_PI-1e-4  <= thetav && thetav < 2*thetab ) ||
	       (LAL_PI +thetab <= thetav && thetav <= LAL_PI+1e-4))
	{
	  rhosqConstraint =(V0+V1*cos(2*thetab)+V2*sin(2*thetab))/2.;
	}
      else
	{
	  CHAR newinfomsg[256];
	  snprintf( newinfomsg, XLAL_NUM_ELEM(newinfomsg),
		       "thetab = %e and thetav = %e\n"
		       "thetav not in the range allowed...V1= %e and V2 = %e\n",
		       thetab, thetav, V1, V2 );
	  LALInfo( status, newinfomsg );
	  ABORT( status, FINDCHIRPH_EALOC, FINDCHIRPH_MSGEALOC );
	}
    }

    /* If one want to check that the code is equivalent to BCVFilter.c, just
     * uncomment the following line.
     */
    /*rhosqConstraint = rhosqUnconstraint; */

    if ( rhosqConstraint > modqsqThresh )
    {
      /* alpha computation needed*/
      alphaU  =   -(b2 * tan(.5*thetav))
        / (a1 + b1* tan(.5*thetav));

      /* I decided to store both constraint and unconstraint alpha */
      if (alphaU > alphaUnity) {
        alphaC = alphaUnity * deltaTPower2By3 ;
         alphaU*= deltaTPower2By3;
      }
      else if (alphaU < 0  ){
        alphaC = 0;
         alphaU*= deltaTPower2By3;
      }
      else {
         alphaU*= deltaTPower2By3;
         alphaC = alphaU;
      }


      if ( ! *eventList )
      {
        /* store the start of the crossing */
        eventStartIdx = j;

        /* if this is the first event, start the list */
        thisEvent = *eventList = (SnglInspiralTable *)
          LALCalloc( 1, sizeof(SnglInspiralTable) );
        if ( ! thisEvent )
        {
          ABORT( status, FINDCHIRPH_EALOC, FINDCHIRPH_MSGEALOC );
        }

        /* record the data that we need for the clustering algorithm */
        thisEvent->end.gpsSeconds = j;
        thisEvent->snr   = rhosqConstraint;
        thisEvent->alpha = alphaC;
        /* use some variable which are not filled in BCV filterinf to keep
         * track of different intermediate values. */
        thisEvent->tau0  = V0;
        thisEvent->tau2  = V1;
        thisEvent->tau3  = V2;
        thisEvent->tau4  = rhosqUnconstraint;
        thisEvent->tau5  = alphaU;
      }
      else if ( !(params->clusterMethod == FindChirpClustering_none) &&
          j <= thisEvent->end.gpsSeconds + deltaEventIndex &&
          rhosqConstraint > thisEvent->snr )
      {
        /* if this is the same event, update the maximum */
        thisEvent->end.gpsSeconds = j;
        thisEvent->snr = rhosqConstraint;
        thisEvent->alpha = alphaC;
        thisEvent->tau0  = V0;
        thisEvent->tau2  = V1;
        thisEvent->tau3  = V2;
        thisEvent->tau4  = rhosqUnconstraint;
        thisEvent->tau5  = alphaU;
      }
      else if (j > thisEvent->end.gpsSeconds + deltaEventIndex ||
          params->clusterMethod == FindChirpClustering_none )
      {
        /* clean up this event */
        SnglInspiralTable *lastEvent;
        INT8               timeNS;
        INT4               timeIndex = thisEvent->end.gpsSeconds;

        /* set the event LIGO GPS time of the event */
        timeNS = 1000000000L *
          (INT8) (input->segment->data->epoch.gpsSeconds);
        timeNS += (INT8) (input->segment->data->epoch.gpsNanoSeconds);
        timeNS += (INT8) (1e9 * timeIndex * deltaT);
        thisEvent->end.gpsSeconds = (INT4) (timeNS/1000000000L);
        thisEvent->end.gpsNanoSeconds = (INT4) (timeNS%1000000000L);
        thisEvent->end_time_gmst = fmod(XLALGreenwichMeanSiderealTime(
            &(thisEvent->end)), LAL_TWOPI) * 24.0 / LAL_TWOPI;	/* hours */
        ASSERT( !XLAL_IS_REAL8_FAIL_NAN(thisEvent->end_time_gmst), status, LAL_FAIL_ERR, LAL_FAIL_MSG );

        /* set the impuse time for the event */
        thisEvent->template_duration = (REAL8) chirpTime;

        /* record the ifo and channel name for the event */
        strncpy( thisEvent->ifo, input->segment->data->name,
            2 * sizeof(CHAR) );
        strncpy( thisEvent->channel, input->segment->data->name + 3,
            (LALNameLength - 3) * sizeof(CHAR) );
        thisEvent->impulse_time = thisEvent->end;

        /* copy the template into the event */
        thisEvent->psi0   = (REAL4) input->fcTmplt->tmplt.psi0;
        thisEvent->psi3   = (REAL4) input->fcTmplt->tmplt.psi3;

        /* chirp mass in units of M_sun */
        thisEvent->mchirp   = mchirp;
        thisEvent->eta      = eta;
        thisEvent->f_final  = (REAL4) input->fcTmplt->tmplt.fFinal ;

        /* set the type of the template used in the analysis */
        snprintf( thisEvent->search, LIGOMETA_SEARCH_MAX * sizeof(CHAR),
            "FindChirpBCVC" );

        thisEvent->chisq     = 0;
        thisEvent->chisq_dof = 0;

        thisEvent->sigmasq = SQRTNormA1;
        thisEvent->eff_distance =
          input->fcTmplt->tmpltNorm / norm / thisEvent->snr;
        thisEvent->eff_distance = sqrt( thisEvent->eff_distance ) / deltaTPower1By6;

        thisEvent->snr *= norm;
        thisEvent->snr = sqrt( thisEvent->snr );

        thisEvent->tau4 = sqrt( thisEvent->tau4 *  norm );

        /* compute the time since the snr crossing */
        thisEvent->event_duration =  (REAL8) timeIndex - (REAL8) eventStartIdx;
        thisEvent->event_duration *= (REAL8) deltaT;

        /* store the start of the crossing */
        eventStartIdx = j;

        /* allocate memory for the newEvent */
        lastEvent = thisEvent;

        lastEvent->next = thisEvent = (SnglInspiralTable *)
          LALCalloc( 1, sizeof(SnglInspiralTable) );
        if ( ! lastEvent->next )
        {
          ABORT( status, FINDCHIRPH_EALOC, FINDCHIRPH_MSGEALOC );
        }

        /* stick minimal data into the event */
        thisEvent->end.gpsSeconds = j;
        thisEvent->snr = rhosqConstraint;
        thisEvent->alpha = alphaC;
        thisEvent->tau0  = V0;
        thisEvent->tau2  = V1;
        thisEvent->tau3  = V2;
        thisEvent->tau4  = rhosqUnconstraint;
        thisEvent->tau5  = alphaU;
      }
    }
  }



  /*
   *
   * clean up the last event if there is one
   *
   */

 if ( thisEvent )
  {
    INT8           timeNS;
    INT4           timeIndex = thisEvent->end.gpsSeconds;

    /* set the event LIGO GPS time of the event */
    timeNS = 1000000000L *
      (INT8) (input->segment->data->epoch.gpsSeconds);
    timeNS += (INT8) (input->segment->data->epoch.gpsNanoSeconds);
    timeNS += (INT8) (1e9 * timeIndex * deltaT);
    thisEvent->end.gpsSeconds = (INT4) (timeNS/1000000000L);
    thisEvent->end.gpsNanoSeconds = (INT4) (timeNS%1000000000L);
    thisEvent->end_time_gmst = fmod(XLALGreenwichMeanSiderealTime(
        &(thisEvent->end)), LAL_TWOPI) * 24.0 / LAL_TWOPI;	/* hours */
    ASSERT( !XLAL_IS_REAL8_FAIL_NAN(thisEvent->end_time_gmst), status, LAL_FAIL_ERR, LAL_FAIL_MSG );

    /* set the impuse time for the event */
    thisEvent->template_duration = (REAL8) chirpTime;

    /* record the ifo name for the event */
    strncpy( thisEvent->ifo, input->segment->data->name,
        2 * sizeof(CHAR) );
    strncpy( thisEvent->channel, input->segment->data->name + 3,
        (LALNameLength - 3) * sizeof(CHAR) );
    thisEvent->impulse_time = thisEvent->end;


    /* copy the template into the event */
    thisEvent->psi0   = (REAL4) input->fcTmplt->tmplt.psi0;
    thisEvent->psi3   = (REAL4) input->fcTmplt->tmplt.psi3;

    /* chirp mass in units of M_sun */
    thisEvent->mchirp = mchirp;
    thisEvent->f_final  = (REAL4) input->fcTmplt->tmplt.fFinal;
    thisEvent->eta = eta;



    /* set the type of the template used in the analysis */
    snprintf( thisEvent->search, LIGOMETA_SEARCH_MAX * sizeof(CHAR),
        "FindChirpBCVC" );

    /* set snrsq, chisq, sigma and effDist for this event */
    if ( input->segment->chisqBinVec->length )
    {
      /* we store chisq distributed with 2p - 2 degrees of freedom */
      /* in the database. params->chisqVec->data = r^2 = chisq / p */
      /* so we multiply r^2 by p here to get chisq                 */
      thisEvent->chisq =
        params->chisqVec->data[timeIndex] * (REAL4) numChisqBins;
      thisEvent->chisq_dof =  2 * numChisqBins; /* double for BCV */
    }
    else
    {
      thisEvent->chisq     = 0;
      thisEvent->chisq_dof = 0;
    }
    thisEvent->sigmasq = SQRTNormA1;
    thisEvent->eff_distance =
      input->fcTmplt->tmpltNorm / norm / thisEvent->snr;
    thisEvent->eff_distance = sqrt( thisEvent->eff_distance ) / deltaTPower1By6;

    thisEvent->snr *=  norm ;
    thisEvent->snr = sqrt( thisEvent->snr );

    thisEvent->tau4 = sqrt( thisEvent->tau4 * norm );

    /* compute the time since the snr crossing */
    thisEvent->event_duration = (REAL8) timeIndex - (REAL8) eventStartIdx;
    thisEvent->event_duration *= (REAL8) deltaT;
  }


  /* normal exit */
  DETATCHSTATUSPTR( status );
  RETURN( status );
}
コード例 #7
0
void
LALFindChirpSPData (
    LALStatus                  *status,
    FindChirpSegmentVector     *fcSegVec,
    DataSegmentVector          *dataSegVec,
    FindChirpDataParams        *params
    )

{
  UINT4                 i, k;
  UINT4                 cut;
  CHAR                  infoMsg[512];

  REAL4                *w;
  REAL4                *amp;
  COMPLEX8             *wtilde;
  REAL4                *tmpltPower;

  REAL4Vector          *dataVec;
  REAL4                *spec;
  COMPLEX8             *resp;

  COMPLEX8             *outputData;
  REAL4                 segNormSum;

  /* stuff added for continous chisq test */
  REAL4Vector          *dataPower = NULL;
  REAL4		        PSDsum = 0;
  INT4 			startIX = 0;
  INT4			endIX = 0;
  COMPLEX8Vector       *fftVec = NULL;
  FindChirpSegment     *fcSeg;
  DataSegment          *dataSeg;
  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );


  /*
   *
   * make sure that the arguments are reasonable
   *
   */


  /* check that the output exists */
  ASSERT( fcSegVec, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL
      ": fcSegVec" );
  ASSERT( fcSegVec->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL
      ": fcSegVec->data" );
  ASSERT( fcSegVec->data->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL
      ": fcSegVec->data->dat" );
  ASSERT( fcSegVec->data->data->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL
      ": fcSegVec->data->data->data" );

  /* check that the parameter structure exists */
  ASSERT( params, status, FINDCHIRPSPH_ENULL,
      FINDCHIRPSPH_MSGENULL ": params" );

  /* check that the workspace vectors exist */
  ASSERT( params->ampVec, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( params->ampVec->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );

  ASSERT( params->wVec, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( params->wVec->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );

  ASSERT( params->wtildeVec, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( params->wtildeVec->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );

  ASSERT( params->tmpltPowerVec, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( params->tmpltPowerVec->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );

  /* check that the fft plans exist */
  ASSERT( params->fwdPlan, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );
  ASSERT( params->invPlan, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL );

  /* check that the parameter values are reasonable */
  ASSERT( params->fLow >= 0, status,
      FINDCHIRPSPH_EFLOW, FINDCHIRPSPH_MSGEFLOW );
  ASSERT( params->dynRange > 0, status,
      FINDCHIRPSPH_EDYNR, FINDCHIRPSPH_MSGEDYNR );

  /* check that the input exists */
  ASSERT( dataSegVec, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL
      ": dataSegVec" );
  ASSERT( dataSegVec->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL
      ": dataSegVec->data" );
  ASSERT( dataSegVec->data->chan, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL
      ": dataSegVec->data->chan" );
  ASSERT( dataSegVec->data->chan->data, status,
      FINDCHIRPSPH_ENULL, FINDCHIRPSPH_MSGENULL
      ": dataSegVec->data->chan->data" );

  /* check that the parameter structure is set */
  /* to the correct waveform approximant       */
  if ( params->approximant != FindChirpSP )
  {
    ABORT( status, FINDCHIRPSPH_EMAPX, FINDCHIRPSPH_MSGEMAPX );
  }


  /*
   *
   * set up local segment independent pointers
   *
   */


  w          = params->wVec->data;
  amp        = params->ampVec->data;
  wtilde     = params->wtildeVec->data;
  tmpltPower = params->tmpltPowerVec->data;

  /* allocate memory to store some temporary info for the
     continous chisq test */
  fcSeg        = &(fcSegVec->data[0]);
  fftVec = XLALCreateCOMPLEX8Vector( fcSeg->data->data->length );

  /*
   *
   * loop over data segments
   *
   */


  for ( i = 0; i < dataSegVec->length; ++i )
  {


    /*
     *
     * set up segment dependent pointers
     *
     */


    dataSeg      = &(dataSegVec->data[i]);
    fcSeg        = &(fcSegVec->data[i]);

    dataVec      = dataSeg->chan->data;
    spec         = dataSeg->spec->data->data;
    resp         = dataSeg->resp->data->data;

    outputData   = fcSeg->data->data->data;
    dataPower    = fcSeg->dataPower->data;

    ASSERT( params->wtildeVec->length == fcSeg->data->data->length, status,
        FINDCHIRPSPH_EMISM, FINDCHIRPSPH_MSGEMISM );


    /* store the waveform approximant in the data segment */
    fcSeg->approximant = params->approximant;


    /*
     *
     * compute htilde and store in fcSeg
     *
     */


    LALForwardRealFFT( status->statusPtr, fcSeg->data->data,
        dataVec, params->fwdPlan );
    CHECKSTATUSPTR( status );

    /* compute strain */
    for ( k = 0; k < fcSeg->data->data->length; ++k )
    {
      REAL4 p = crealf(outputData[k]);
      REAL4 q = cimagf(outputData[k]);
      REAL4 x = crealf(resp[k]) * params->dynRange;
      REAL4 y = cimagf(resp[k]) * params->dynRange;

      outputData[k] = crectf( p*x - q*y, p*y + q*x );
    }


    /*
     *
     * compute inverse power spectrum
     *
     */


    /* set low frequency cutoff inverse power spectrum */
    cut = params->fLow / dataSeg->spec->deltaF > 1 ?
      params->fLow / dataSeg->spec->deltaF : 1;
    snprintf( infoMsg, XLAL_NUM_ELEM(infoMsg),
        "low frequency cut off index = %d\n", cut );
    LALInfo( status, infoMsg );

    /* set inverse power spectrum to zero */
    memset( wtilde, 0, params->wtildeVec->length * sizeof(COMPLEX8) );

    /* compute inverse of S_v */
    for ( k = cut; k < params->wtildeVec->length; ++k )
    {
      if ( spec[k] == 0 )
      {

        ABORT( status, FINDCHIRPSPH_EDIVZ, FINDCHIRPSPH_MSGEDIVZ );
      }
      wtilde[k] = crectf( 1.0 / spec[k], cimagf(wtilde[k]) );
    }

    /*
     *
     * truncate inverse power spectrum in time domain if required
     *
     */


    if ( params->invSpecTrunc )
    {
      /* compute square root of inverse power spectrum */
      for ( k = cut; k < params->wtildeVec->length; ++k )
      {
        wtilde[k] = crectf( sqrt( crealf(wtilde[k]) ), cimagf(wtilde[k]) );
      }

      /* set nyquist and dc to zero */
      wtilde[params->wtildeVec->length-1] = crectf( 0.0, cimagf(wtilde[params->wtildeVec->length-1]) );
      wtilde[0] = crectf( 0.0, cimagf(wtilde[0]) );

      /* transform to time domain */
      LALReverseRealFFT( status->statusPtr, params->wVec, params->wtildeVec,
          params->invPlan );
      CHECKSTATUSPTR (status);

      /* truncate in time domain */
      memset( w + params->invSpecTrunc/2, 0,
          (params->wVec->length - params->invSpecTrunc) * sizeof(REAL4) );

      /* transform to frequency domain */
      LALForwardRealFFT( status->statusPtr, params->wtildeVec, params->wVec,
          params->fwdPlan );
      CHECKSTATUSPTR (status);

      /* normalise fourier transform and square */
      {
        REAL4 norm = 1.0 / (REAL4) params->wVec->length;
        for ( k = cut; k < params->wtildeVec->length; ++k )
        {
          wtilde[k] = crectf( crealf(wtilde[k]) * ( norm ), cimagf(wtilde[k]) );
          wtilde[k] = crectf( crealf(wtilde[k]) * ( crealf(wtilde[k]) ), cimagf(wtilde[k]) );
          wtilde[k] = crectf( crealf(wtilde[k]), 0.0 );
        }
      }

      /* set nyquist and dc to zero */
      wtilde[params->wtildeVec->length-1] = crectf( 0.0, cimagf(wtilde[params->wtildeVec->length-1]) );
      wtilde[0] = crectf( 0.0, cimagf(wtilde[0]) );
    }

    /* set inverse power spectrum below cut to zero */
    memset( wtilde, 0, cut * sizeof(COMPLEX8) );

    /* convert from S_v to S_h */
    for ( k = cut; k < params->wtildeVec->length; ++k )
    {
      REAL4 respRe = crealf(resp[k]) * params->dynRange;
      REAL4 respIm = cimagf(resp[k]) * params->dynRange;
      REAL4 modsqResp = (respRe * respRe + respIm * respIm);
      REAL4 invmodsqResp;
      if ( modsqResp == 0 )
      {
        ABORT( status, FINDCHIRPSPH_EDIVZ, FINDCHIRPSPH_MSGEDIVZ );
      }
      invmodsqResp = 1.0 / modsqResp;
      wtilde[k] = crectf( crealf(wtilde[k]) * ( invmodsqResp ), cimagf(wtilde[k]) );
    }


    /*
     *
     * compute segment normalisation, outputData, point fcSeg at data segment
     *
     */



    for ( k = 0; k < cut; ++k )
    {
      outputData[k] = 0.0;
    }

    for ( k = 0; k < cut; ++k )
    {
      fftVec->data[k] = 0.0;
    }


    memset( tmpltPower, 0, params->tmpltPowerVec->length * sizeof(REAL4) );
    memset( fcSeg->segNorm->data, 0, fcSeg->segNorm->length * sizeof(REAL4) );

    fcSeg->tmpltPowerVec = params->tmpltPowerVec;

    segNormSum = 0.0;
    for ( k = 1; k < fcSeg->data->data->length; ++k )
    {
      tmpltPower[k] = amp[k] * amp[k] * crealf(wtilde[k]);
      segNormSum += tmpltPower[k];
      fcSeg->segNorm->data[k] = segNormSum;
    }

    /*  Compute whitened data for continous chisq test */
    for ( k = 0; k < fcSeg->data->data->length; ++k )
    {
      fftVec->data[k] = crectf( crealf(outputData[k]) * sqrt( crealf(wtilde[k]) ), cimagf(outputData[k]) * sqrt( crealf(wtilde[k]) ) );
    }

    /* get the whitened time series */
    LALReverseRealFFT( status->statusPtr, dataPower, fftVec,
          params->invPlan );
    dataPower->data[0] = 0;

    /* compute the cumulative power used for the continous
       chisq test */
    for ( k = 1; k < dataPower->length; k++ )
      {
      dataPower->data[k] =
        dataPower->data[k-1] +
        dataPower->data[k] * dataPower->data[k];
      }

    /* hard wired to quarter segment !! */
    startIX = floor(1.0/4.0 * (REAL4) dataPower->length + 0.5);
    endIX = floor(3.0/4.0 * (REAL4) dataPower->length + 0.5);
    /* compute the total power in the uncorrupted data */
    dataPower->data[dataPower->length - 1 ] = 2.0 *
      (dataPower->data[endIX] - dataPower->data[startIX]);
    for ( k = cut; k < fcSeg->data->data->length; ++k )
    {
      outputData[k] *= ((REAL4) crealf(wtilde[k]) * amp[k]);
    }

    /* set output frequency series parameters */
    strncpy( fcSeg->data->name, dataSeg->chan->name, LALNameLength );

    fcSeg->data->epoch.gpsSeconds      = dataSeg->chan->epoch.gpsSeconds;
    fcSeg->data->epoch.gpsNanoSeconds  = dataSeg->chan->epoch.gpsNanoSeconds;

    fcSeg->data->f0     = dataSeg->chan->f0;
    fcSeg->data->deltaF = 1.0 /
      ( (REAL8) dataSeg->chan->data->length * dataSeg->chan->deltaT ) ;

    fcSeg->deltaT       = dataSeg->chan->deltaT;
    fcSeg->number       = dataSeg->number;
    fcSeg->analyzeSegment = dataSeg->analyzeSegment;

    /* store low frequency cutoff and invSpecTrunc in segment */
    fcSeg->fLow         = params->fLow;
    fcSeg->invSpecTrunc = params->invSpecTrunc;


  } /* end loop over data segments */


  /* Find the min power from the whitened time series */
  /* For the continuous chisq test */
  fcSeg = &(fcSegVec->data[0]);
  PSDsum = fcSeg->dataPower->data->data[fcSeg->dataPower->data->length - 1 ];

  for ( i = 1; i < dataSegVec->length; ++i )
  {
    fcSeg = &(fcSegVec->data[i]);
    if
    (
    ((fcSeg->dataPower->data->data[fcSeg->dataPower->data->length - 1 ] < PSDsum)    &&
    (fcSeg->dataPower->data->data[fcSeg->dataPower->data->length - 1 ] > 0))
    ||
    PSDsum == 0
    )
    {
      PSDsum = fcSeg->dataPower->data->data[fcSeg->dataPower->data->length - 1 ];
    }

  }
  /* reset each dataPower's last element to the min power */
  for ( i = 0; i < dataSegVec->length; ++i )
  {
    fcSeg = &(fcSegVec->data[i]);
    fcSeg->dataPower->data->data[fcSeg->dataPower->data->length - 1 ] = PSDsum;

  }

  /* clean up the data used for the continous chisq test */
  XLALDestroyCOMPLEX8Vector( fftVec );

  /* normal exit */
  DETATCHSTATUSPTR( status );
  RETURN( status );
}
コード例 #8
0
void
LALCreateTwoIFOCoincListEllipsoid(
    LALStatus                  *status,
    CoincInspiralTable        **coincOutput,
    SnglInspiralTable          *snglInput,
    InspiralAccuracyList       *accuracyParams
    )

{
  INT8                          currentTriggerNS[2];
  CoincInspiralTable           *coincHead = NULL;
  CoincInspiralTable           *thisCoinc = NULL;
  INT4                          numEvents = 0;
  INT8                          maxTimeDiff = 0;
  TriggerErrorList             *errorListHead = NULL;
  TriggerErrorList             UNUSED *thisErrorList = NULL;
  TriggerErrorList             *currentError[2];
  fContactWorkSpace            *workSpace;
  REAL8                        timeError = 0.0;


  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );

  ASSERT( snglInput, status,
      LIGOMETADATAUTILSH_ENULL, LIGOMETADATAUTILSH_MSGENULL );
  ASSERT( coincOutput, status,
      LIGOMETADATAUTILSH_ENULL, LIGOMETADATAUTILSH_MSGENULL );
  ASSERT( ! *coincOutput, status,
      LIGOMETADATAUTILSH_ENNUL, LIGOMETADATAUTILSH_MSGENNUL );

  memset( currentTriggerNS, 0, 2 * sizeof(INT8) );

  /* Loop through triggers and assign each of them an error ellipsoid */
  errorListHead = XLALCreateTriggerErrorList( snglInput, accuracyParams->eMatch, &timeError );
  if ( !errorListHead )
  {
    ABORTXLAL( status );
  }

  /* Initialise the workspace for ellipsoid overlaps */
  workSpace = XLALInitFContactWorkSpace( 3, NULL, NULL, gsl_min_fminimizer_brent, 1.0e-2 );
  if (!workSpace)
  {
    XLALDestroyTriggerErrorList( errorListHead );
    ABORTXLAL( status );
  }

  /* calculate the maximum time delay
   * set it equal to 2 * worst IFO timing accuracy plus
   * light travel time for earths diameter
   * (detectors cant be further apart than this) */

  maxTimeDiff = (INT8) (1e9 * 2.0 * timeError);
  maxTimeDiff += (INT8) ( 1e9 * 2 * LAL_REARTH_SI / LAL_C_SI );

  for ( currentError[0] = errorListHead; currentError[0]->next;
      currentError[0] = currentError[0]->next)
  {

    /* calculate the time of the trigger */
    currentTriggerNS[0] = XLALGPSToINT8NS(
                 &(currentError[0]->trigger->end_time) );

    /* set next trigger for comparison */
    currentError[1] = currentError[0]->next;
    currentTriggerNS[1] = XLALGPSToINT8NS(
                 &(currentError[1]->trigger->end_time) );

    while ( (currentTriggerNS[1] - currentTriggerNS[0]) < maxTimeDiff )
    {

      INT2 match;

      /* test whether we have coincidence */
      match = XLALCompareInspiralsEllipsoid( currentError[0],
                 currentError[1], workSpace, accuracyParams );
      if ( match == XLAL_FAILURE )
      {
        /* Error in the comparison function */
        XLALDestroyTriggerErrorList( errorListHead );
        XLALFreeFContactWorkSpace( workSpace );
        ABORTXLAL( status );
      }

      /* Check whether the event was coincident */
      if ( match )
      {
#if 0
        REAL8 etp = XLALCalculateEThincaParameter( currentError[0]->trigger,  currentError[1]->trigger, accuracyParams );
#endif
        /* create a 2 IFO coinc and store */
        if ( ! coincHead  )
        {
          coincHead = thisCoinc = (CoincInspiralTable *)
            LALCalloc( 1, sizeof(CoincInspiralTable) );
        }
        else
        {
          thisCoinc = thisCoinc->next = (CoincInspiralTable *)
            LALCalloc( 1, sizeof(CoincInspiralTable) );
        }
        if ( !thisCoinc )
        {
          /* Error allocating memory */
          thisCoinc = coincHead;
          while ( thisCoinc )
          {
            coincHead = thisCoinc->next;
            LALFree( thisCoinc );
            thisCoinc = coincHead;
          }
          XLALDestroyTriggerErrorList( errorListHead );
          XLALFreeFContactWorkSpace( workSpace );
          ABORT( status, LAL_NOMEM_ERR, LAL_NOMEM_MSG );
        }

        /* Add the two triggers to the coinc */
        LALAddSnglInspiralToCoinc( status->statusPtr, &thisCoinc,
            currentError[0]->trigger );
        LALAddSnglInspiralToCoinc( status->statusPtr, &thisCoinc,
            currentError[1]->trigger );

        ++numEvents;

      }

      /* scroll on to the next sngl inspiral */

      if ( (currentError[1] = currentError[1]->next) )
      {
        currentTriggerNS[1] = XLALGPSToINT8NS( &(currentError[1]->trigger->end_time) );
      }
      else
      {
        LALInfo(status, "Second trigger has reached end of list");
        break;
      }
    }
  }

  *coincOutput = coincHead;

  /* Free all the memory allocated for the ellipsoid overlap */
  thisErrorList = errorListHead;
  XLALDestroyTriggerErrorList( errorListHead );
  XLALFreeFContactWorkSpace( workSpace );

  DETATCHSTATUSPTR (status);
  RETURN (status);
}
コード例 #9
0
void
LALInspiralEccentricityForInjection(
			     LALStatus        *status,
			     CoherentGW       *waveform,
			     InspiralTemplate *params,
			     PPNParamStruc  *ppnParams
			     )
{

  INT4        count, i;
  REAL8       p, phiC;

  REAL4Vector a;           /* pointers to generated amplitude  data */
  REAL4Vector ff;          /* pointers to generated  frequency data */
  REAL8Vector phi;         /* generated phase data */

  CreateVectorSequenceIn in;

  CHAR message[256];

  InspiralInit paramsInit;

  INITSTATUS(status);
  ATTATCHSTATUSPTR(status);

  /* Make sure parameter and waveform structures exist. */
  ASSERT( params, status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL );
  ASSERT(waveform, status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL);
  ASSERT( !( waveform->a ), status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL );
  ASSERT( !( waveform->f ), status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL );
  ASSERT( !( waveform->phi ), status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL );

  /* Compute some parameters*/
  LALInspiralInit(status->statusPtr, params, &paramsInit);
  CHECKSTATUSPTR(status);

  if (paramsInit.nbins == 0){
      DETATCHSTATUSPTR(status);
      RETURN (status);
  }

  /* Now we can allocate memory and vector for coherentGW structure*/

  ff.length  = paramsInit.nbins;
  a.length   = 2* paramsInit.nbins;
  phi.length = paramsInit.nbins;

  ff.data = (REAL4 *) LALCalloc(paramsInit.nbins, sizeof(REAL4));
  a.data  = (REAL4 *) LALCalloc(2 * paramsInit.nbins, sizeof(REAL4));
  phi.data= (REAL8 *) LALCalloc(paramsInit.nbins, sizeof(REAL8));

  /* Check momory allocation is okay */
  if (!(ff.data) || !(a.data) || !(phi.data))
  {
    if (ff.data)  LALFree(ff.data);
    if (a.data)   LALFree(a.data);
    if (phi.data) LALFree(phi.data);

    ABORT( status, LALINSPIRALH_EMEM, LALINSPIRALH_MSGEMEM );
  }

  count = 0;

  /* Call the engine function */
  LALInspiralEccentricityEngine(status->statusPtr, NULL, NULL, &a, &ff, &phi, &count, params);
  BEGINFAIL( status )
  {
    LALFree(ff.data);
    LALFree(a.data);
    LALFree(phi.data);
  }
  ENDFAIL( status );

  p = phi.data[count-1];

  params->fFinal = ff.data[count-1];
  sprintf(message, "cycles = %f", p/(double)LAL_TWOPI);
  LALInfo(status, message);

  if ( (INT4)(p/LAL_TWOPI) < 2 ){
    sprintf(message, "The waveform has only %f cycles; we don't keep waveform with less than 2 cycles.",
	       p/(double)LAL_TWOPI );
    XLALPrintError("%s", message);
    LALWarning(status, message);
  }

      /*wrap the phase vector*/
      phiC =  phi.data[count-1] ;
      for (i = 0; i < count; i++)
	{
	  phi.data[i] =  phi.data[i] - phiC + ppnParams->phi;
	}

      /* Allocate the waveform structures. */
      if ( ( waveform->a = (REAL4TimeVectorSeries *)
	     LALCalloc(1, sizeof(REAL4TimeVectorSeries) ) ) == NULL ) {
	ABORT( status, LALINSPIRALH_EMEM,
	       LALINSPIRALH_MSGEMEM );
      }
      if ( ( waveform->f = (REAL4TimeSeries *)
	     LALCalloc(1, sizeof(REAL4TimeSeries) ) ) == NULL ) {
	LALFree( waveform->a ); waveform->a = NULL;
	ABORT( status, LALINSPIRALH_EMEM,
	       LALINSPIRALH_MSGEMEM );
      }
      if ( ( waveform->phi = (REAL8TimeSeries *)
	     LALCalloc(1, sizeof(REAL8TimeSeries) ) ) == NULL ) {
	LALFree( waveform->a ); waveform->a = NULL;
	LALFree( waveform->f ); waveform->f = NULL;
	ABORT( status, LALINSPIRALH_EMEM,
	       LALINSPIRALH_MSGEMEM );
      }


      in.length = (UINT4)(count);
      in.vectorLength = 2;

      LALSCreateVectorSequence( status->statusPtr, &( waveform->a->data ), &in );
      CHECKSTATUSPTR(status);

      LALSCreateVector( status->statusPtr, &( waveform->f->data ), count);
      CHECKSTATUSPTR(status);

      LALDCreateVector( status->statusPtr, &( waveform->phi->data ), count );
      CHECKSTATUSPTR(status);

      memcpy(waveform->f->data->data , ff.data, count*(sizeof(REAL4)));
      memcpy(waveform->a->data->data , a.data, 2*count*(sizeof(REAL4)));
      memcpy(waveform->phi->data->data ,phi.data, count*(sizeof(REAL8)));

      waveform->a->deltaT = waveform->f->deltaT = waveform->phi->deltaT
	= ppnParams->deltaT;

      waveform->a->sampleUnits    = lalStrainUnit;
      waveform->f->sampleUnits    = lalHertzUnit;
      waveform->phi->sampleUnits  = lalDimensionlessUnit;
      waveform->position = ppnParams->position;
      waveform->psi = ppnParams->psi;

      snprintf( waveform->a->name, LALNameLength,   "T1 inspiral amplitude" );
      snprintf( waveform->f->name, LALNameLength,   "T1 inspiral frequency" );
      snprintf( waveform->phi->name, LALNameLength, "T1 inspiral phase" );

      /* --- fill some output ---*/
      ppnParams->tc     = (double)(count-1) / params->tSampling ;
      ppnParams->length = count;
      ppnParams->dfdt   = ((REAL4)(waveform->f->data->data[count-1]
				   - waveform->f->data->data[count-2]))
	* ppnParams->deltaT;
      ppnParams->fStop  = params->fFinal;
      ppnParams->termCode        = GENERATEPPNINSPIRALH_EFSTOP;
      ppnParams->termDescription = GENERATEPPNINSPIRALH_MSGEFSTOP;

      ppnParams->fStart   = ppnParams->fStartIn;

  /* --- free memory --- */
  LALFree(ff.data);
  LALFree(a.data);
  LALFree(phi.data);

  DETATCHSTATUSPTR(status);
  RETURN (status);
}
コード例 #10
0
ファイル: DetResponse.c プロジェクト: Solaro/lalsuite
/**
 * Computes REAL4TimeSeries containing time series of response amplitudes.
 * \deprecated Use XLALComputeDetAMResponseSeries() instead.
 */
void LALComputeDetAMResponseSeries(LALStatus * status, LALDetAMResponseSeries * pResponseSeries, const LALDetAndSource * pDetAndSource, const LALTimeIntervalAndNSample * pTimeInfo)
{
	/* Want to loop over the time and call LALComputeDetAMResponse() */
	LALDetAMResponse instResponse;
	unsigned i;

	INITSTATUS(status);
	ATTATCHSTATUSPTR(status);

	/*
	 * Error-checking assertions
	 */
	ASSERT(pResponseSeries != (LALDetAMResponseSeries *) NULL, status, DETRESPONSEH_ENULLOUTPUT, DETRESPONSEH_MSGENULLOUTPUT);

	ASSERT(pDetAndSource != (LALDetAndSource *) NULL, status, DETRESPONSEH_ENULLINPUT, DETRESPONSEH_MSGENULLINPUT);

	ASSERT(pTimeInfo != (LALTimeIntervalAndNSample *) NULL, status, DETRESPONSEH_ENULLINPUT, DETRESPONSEH_MSGENULLINPUT);

	/*
	 * Set names
	 */
	pResponseSeries->pPlus->name[0] = '\0';
	pResponseSeries->pCross->name[0] = '\0';
	pResponseSeries->pScalar->name[0] = '\0';

	strncpy(pResponseSeries->pPlus->name, "plus", LALNameLength);
	strncpy(pResponseSeries->pCross->name, "cross", LALNameLength);
	strncpy(pResponseSeries->pScalar->name, "scalar", LALNameLength);

	/*
	 * Set sampling parameters
	 */
	pResponseSeries->pPlus->epoch = pTimeInfo->epoch;
	pResponseSeries->pPlus->deltaT = pTimeInfo->deltaT;
	pResponseSeries->pPlus->f0 = 0.;
	pResponseSeries->pPlus->sampleUnits = lalDimensionlessUnit;

	pResponseSeries->pCross->epoch = pTimeInfo->epoch;
	pResponseSeries->pCross->deltaT = pTimeInfo->deltaT;
	pResponseSeries->pCross->f0 = 0.;
	pResponseSeries->pCross->sampleUnits = lalDimensionlessUnit;

	pResponseSeries->pScalar->epoch = pTimeInfo->epoch;
	pResponseSeries->pScalar->deltaT = pTimeInfo->deltaT;
	pResponseSeries->pScalar->f0 = 0.;
	pResponseSeries->pScalar->sampleUnits = lalDimensionlessUnit;

	/*
	 * Ensure enough memory for requested vectors
	 */
	if(pResponseSeries->pPlus->data->length < pTimeInfo->nSample) {
		if(lalDebugLevel >= 8)
			LALInfo(status, "plus sequence too short -- reallocating");

		TRY(LALSDestroyVector(status->statusPtr, &(pResponseSeries->pPlus->data)), status);

		TRY(LALSCreateVector(status->statusPtr, &(pResponseSeries->pPlus->data), pTimeInfo->nSample), status);

		if(lalDebugLevel > 0)
			printf("pResponseSeries->pPlus->data->length = %d\n", pResponseSeries->pPlus->data->length);

	}

	if(pResponseSeries->pCross->data->length < pTimeInfo->nSample) {
		if(lalDebugLevel >= 8)
			LALInfo(status, "cross sequence too short -- reallocating");

		TRY(LALSDestroyVector(status->statusPtr, &(pResponseSeries->pCross->data)), status);

		TRY(LALSCreateVector(status->statusPtr, &(pResponseSeries->pCross->data), pTimeInfo->nSample), status);

	}

	if(pResponseSeries->pScalar->data->length < pTimeInfo->nSample) {
		if(lalDebugLevel & 0x08)
			LALInfo(status, "scalar sequence too short -- reallocating");

		TRY(LALSDestroyVector(status->statusPtr, &(pResponseSeries->pScalar->data)), status);

		TRY(LALSCreateVector(status->statusPtr, &(pResponseSeries->pScalar->data), pTimeInfo->nSample), status);
	}


	/*
	 * Loop to compute each element in time series.
	 */

	for(i = 0; i < pTimeInfo->nSample; ++i) {
		LIGOTimeGPS gps = pTimeInfo->epoch;
		XLALGPSAdd(&gps, i * pTimeInfo->deltaT);

		TRY(LALComputeDetAMResponse(status->statusPtr, &instResponse, pDetAndSource, &gps), status);

		pResponseSeries->pPlus->data->data[i] = instResponse.plus;
		pResponseSeries->pCross->data->data[i] = instResponse.cross;
		pResponseSeries->pScalar->data->data[i] = instResponse.scalar;
	}

	DETATCHSTATUSPTR(status);
	RETURN(status);
}
コード例 #11
0
/* LALINSPIRALSPINBANKMETRIC() --------------------------------------------- */
static void
LALInspiralSpinBankMetric(
   LALStatus		*status,
   REAL4Array		*metric,
   InspiralMomentsEtc	*moments,
   InspiralTemplate	*inspiralTemplate,
   REAL4		*f0
   )
{
  INT4 loop = 0;
  REAL8 J1  = 0.0;
  REAL8 J4  = 0.0;
  REAL8 J6  = 0.0;
  REAL8 J9  = 0.0;
  REAL8 J11 = 0.0;
  REAL8 J12 = 0.0;
  REAL8 J14 = 0.0;
  REAL8 J17 = 0.0;

  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );

  if (!metric){
    ABORT(status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL);
    }
  if (!moments){
    ABORT(status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL);
    }


  /* Rescale the moments to F0 = Noise Curve Minimum */
  for(loop = 1; loop <=17; loop++){
    moments->j[loop] *= pow((inspiralTemplate->fLower/(*f0)), ((7.0-(REAL4) loop)/3.0));
    }

/* This just copies the noise moment data from *moments */
  J1  = moments->j[1];
  J4  = moments->j[4];
  J6  = moments->j[6];
  J9  = moments->j[9];
  J11 = moments->j[11];
  J12 = moments->j[12];
  J14 = moments->j[14];
  J17 = moments->j[17];

  /* Set metric components as functions of moments. */

  metric->data[0] = (REAL4) 0.5*(J17-J12*J12-(J9-J4*J12)*(J9-J4*J12)/(J1-J4*J4));
  metric->data[1] = (REAL4) 0.5*(J14-J9*J12-(J6-J4*J9)*(J9-J4*J12)/(J1-J4*J4));
  metric->data[2] = (REAL4) 0;
  metric->data[3] = (REAL4) 0.5*(J14-J9*J12-(J6-J4*J9)*(J9-J4*J12)/(J1-J4*J4));
  metric->data[4] = (REAL4) 0.5*(J11-J9*J9-(J6-J4*J9)*(J6-J4*J9)/(J1-J4*J4));

  metric->data[5] = (REAL4) 0.0;
  metric->data[6] = (REAL4) 0.0;
  metric->data[7] = (REAL4) 0.0;
  metric->data[8] = (REAL4) 0.5*(J11-J9*J9-(J6-J4*J9)*(J6-J4*J9)/(J1-J4*J4));

  /* Say it if we're asked to. */
  if ( lalDebugLevel & LALINFO )
  {
    CHAR msg[256];
    snprintf( msg, XLAL_NUM_ELEM(msg), "metric components:\n"
                 "psi0-psi0 %e\npsi0-psi3 %e psi3-psi3 %e\npsi0-beta %e "
		 "psi3-beta %e beta-beta %e\n", metric->data[0] /
		 pow(*f0,10./3), metric->data[3] / pow(*f0,7./3),
                 metric->data[4] / pow(*f0,4./3), metric->data[6] /
		 pow(*f0,7./3), metric->data[7] / pow(*f0,4./3),
                 metric->data[8] / pow(*f0,4./3) );
    LALInfo( status, msg );
    snprintf( msg, XLAL_NUM_ELEM(msg), "f0 = %f j1=%f j4=%f "
		 "j6=%f j9=%f j11=%f j12=%f j14=%f j17=%f", *f0, J1, J4,
                 J6, J9, J11, J12, J14, J17 );
    LALInfo( status, msg );
  }

  DETATCHSTATUSPTR( status );
  RETURN( status );
} /* LALInspiralSpinBankMetric */
コード例 #12
0
/** UNDOCUMENTED */
void
LALUpdateCalibration(
    LALStatus               *status,
    CalibrationFunctions    *output,
    CalibrationFunctions    *input,
    CalibrationUpdateParams *params
    )
{
  const REAL4 tiny = 1e-6;
  COMPLEX8Vector *save;
  COMPLEX8 *R;
  COMPLEX8 *C;
  COMPLEX8 *R0;
  COMPLEX8 *C0;
  COMPLEX8 a;
  COMPLEX8 ab;
  REAL8 epoch;
  REAL8 first_cal;
  REAL8 duration;
  REAL4 dt;
  REAL4 i_r4;
  UINT4 n;
  UINT4 i;
  UINT4 length = 0;
  CHAR  warnMsg[512];

  INITSTATUS(status);
  ATTATCHSTATUSPTR( status );

  /* check input */
  ASSERT( input, status, CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( input->sensingFunction, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( input->responseFunction, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( input->sensingFunction->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( input->responseFunction->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( input->sensingFunction->data->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( input->responseFunction->data->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  n = input->sensingFunction->data->length;
  ASSERT( (int)n > 0, status, CALIBRATIONH_ESIZE, CALIBRATIONH_MSGESIZE );
  ASSERT( input->responseFunction->data->length == n, status,
      CALIBRATIONH_ESZMM, CALIBRATIONH_MSGESZMM );

  /* check output */
  ASSERT( output, status, CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( output->sensingFunction, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( output->responseFunction, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( output->sensingFunction->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( output->responseFunction->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( output->sensingFunction->data->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( output->responseFunction->data->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( output->sensingFunction->data->length == n, status,
      CALIBRATIONH_ESZMM, CALIBRATIONH_MSGESZMM );
  ASSERT( output->responseFunction->data->length == n, status,
      CALIBRATIONH_ESZMM, CALIBRATIONH_MSGESZMM );

  /* check params */
  ASSERT( params, status, CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( params->sensingFactor, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( params->openLoopFactor, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( params->sensingFactor->deltaT, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( params->sensingFactor->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( params->openLoopFactor->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( params->sensingFactor->data->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( params->openLoopFactor->data->data, status,
      CALIBRATIONH_ENULL, CALIBRATIONH_MSGENULL );
  ASSERT( params->openLoopFactor->data->length ==
      params->sensingFactor->data->length, status,
      CALIBRATIONH_ESZMM, CALIBRATIONH_MSGESZMM );

  R0 = input->responseFunction->data->data;
  C0 = input->sensingFunction->data->data;
  R = output->responseFunction->data->data;
  C = output->sensingFunction->data->data;

  save = output->responseFunction->data;
  output->responseFunction = input->responseFunction;
  output->responseFunction->data = save;
  output->responseFunction->epoch = params->epoch;

  save = output->sensingFunction->data;
  output->sensingFunction = input->sensingFunction;
  output->sensingFunction->data = save;
  output->sensingFunction->epoch = params->epoch;

  /* locate correct values of a and ab */
  epoch = XLALGPSGetREAL8(&(params->epoch));
  first_cal = XLALGPSGetREAL8(&(params->sensingFactor->epoch));
  duration = XLALGPSGetREAL8(&(params->duration));

  dt = epoch - first_cal;

  /* find the first point at or before the requested time */
  if ( (i_r4 = floor( dt / params->sensingFactor->deltaT ) ) < 0 )
  {
    ABORT( status, CALIBRATIONH_ETIME, CALIBRATIONH_MSGETIME );
  }
  else
  {
    i = (UINT4) i_r4;
  }

  /* compute the sum of the calibration factors */
  a = ab = 0;
  length = 0;
  do
  {
    COMPLEX8 this_a;
    COMPLEX8 this_ab;

    if ( i > params->sensingFactor->data->length - 1 )
    {
      ABORT( status, CALIBRATIONH_ETIME, CALIBRATIONH_MSGETIME );
    }

    this_a = params->sensingFactor->data->data[i];
    this_ab = params->openLoopFactor->data->data[i];

    /* JC: I CHANGED THE LOGIC HERE TO WHAT I THOUGHT IT SHOULD BE! */
    if ( ( fabs( creal(this_a) ) < tiny && fabs( cimag(this_a) ) < tiny ) ||
         ( fabs( creal(this_ab) ) < tiny && fabs( cimag(this_ab) ) < tiny ) )
    {
      /* this is a hack for the broken S2 calibration frame data */
      if ( (params->epoch.gpsSeconds >= CAL_S2START) &&
          (params->epoch.gpsSeconds < CAL_S2END ) )
      {
        /* if the zero is during S2 print a warning... */
        snprintf( warnMsg, XLAL_NUM_ELEM(warnMsg),
            "Zero calibration factors found during S2 at GPS %10.9f",
            first_cal + (REAL8) i * params->sensingFactor->deltaT );
        LALWarning( status, warnMsg );
      }
      else
      {
        /* ...or abort if we are outside S2 */
        snprintf( warnMsg, XLAL_NUM_ELEM(warnMsg),
            "Zero calibration factor found at GPS %10.9f",
            first_cal + (REAL8) i * params->sensingFactor->deltaT );
        LALWarning( status, warnMsg );
        ABORT( status, CALIBRATIONH_EZERO, CALIBRATIONH_MSGEZERO );
      }
    }
    else
    {
      /* increment the count of factors if we are adding a non-zero value */
      ++length;
    }

    /* add this value to the sum */
    a += this_a;
    ab += this_ab;

    /* increment the calibration factor index */
    ++i;
  }
  while ( (first_cal + (REAL8) i * params->sensingFactor->deltaT) <
      (epoch + duration) );

  /* if all the calibration factors are zero the abort */
  if ( ! length ||
      (fabs( creal(a) ) < tiny && fabs( cimag(a) ) < tiny) ||
      (fabs( creal(ab) ) < tiny && fabs( cimag(ab) ) < tiny) )
  {
    snprintf( warnMsg, XLAL_NUM_ELEM(warnMsg),
        "Got %d calibration samples\nalpha and/or beta are zero:\n"
        "Re a = %e\tIm a = %e\nRe ab = %e\tIm ab = %e",
        length, creal(a), cimag(a), creal(ab), cimag(ab) );
    LALWarning( status, warnMsg );
    ABORT( status, CALIBRATIONH_EZERO, CALIBRATIONH_MSGEZERO );
  }

  /* compute the mean of the calibration factors from the sum */
  a /= length;
  ab /= length;

  /* return the used values of alpha and alphabeta */
  params->alpha = a;
  params->alphabeta = ab;
  snprintf( warnMsg, XLAL_NUM_ELEM(warnMsg),
      "Got %d calibration samples\n"
      "Re a = %e\tIm a = %e\nRe ab = %e\tIm ab = %e",
      length, creal(a), cimag(a), creal(ab), cimag(ab) );
  LALInfo( status, warnMsg );

  for ( i = 0; i < n; ++i )
  {
    C[i] = a * C0[i];
    R[i] = (ab * (C0[i] * R0[i] - 1.0) + 1.0) / C[i];
  }
  DETATCHSTATUSPTR( status );
  RETURN( status );
}