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 ); }
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 ); }
/** * \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 ); }
/** * \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 ); }
/** * \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, ¶ms ), 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, ¶ms ); 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 {
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 ); }
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 ); }
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); }
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, ¶msInit); 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); }
/** * 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); }
/* 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 */
/** 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 ); }