/** * Computes REAL4TimeSeries containing time series of response amplitudes. * \see XLALComputeDetAMResponse() for more details. */ int XLALComputeDetAMResponseSeries(REAL4TimeSeries ** fplus, REAL4TimeSeries ** fcross, const REAL4 D[3][3], const double ra, const double dec, const double psi, const LIGOTimeGPS * start, const double deltaT, const int n) { LIGOTimeGPS t; double gmst; int i; double p, c; *fplus = XLALCreateREAL4TimeSeries("plus", start, 0.0, deltaT, &lalDimensionlessUnit, n); *fcross = XLALCreateREAL4TimeSeries("cross", start, 0.0, deltaT, &lalDimensionlessUnit, n); if(!*fplus || !*fcross) { XLALDestroyREAL4TimeSeries(*fplus); XLALDestroyREAL4TimeSeries(*fcross); *fplus = *fcross = NULL; XLAL_ERROR(XLAL_EFUNC); } for(i = 0; i < n; i++) { t = *start; gmst = XLALGreenwichMeanSiderealTime(XLALGPSAdd(&t, i * deltaT)); if(XLAL_IS_REAL8_FAIL_NAN(gmst)) { XLALDestroyREAL4TimeSeries(*fplus); XLALDestroyREAL4TimeSeries(*fcross); *fplus = *fcross = NULL; XLAL_ERROR(XLAL_EFUNC); } XLALComputeDetAMResponse(&p, &c, D, ra, dec, psi, gmst); (*fplus)->data->data[i] = p; (*fcross)->data->data[i] = c; } return 0; }
/** * Computes REAL4TimeSeries containing time series of the full general * metric theory of gravity response amplitudes. * \see XLALComputeDetAMResponseExtraModes() for more details. */ int XLALComputeDetAMResponseExtraModesSeries(REAL4TimeSeries ** fplus, REAL4TimeSeries ** fcross, REAL4TimeSeries ** fb, REAL4TimeSeries ** fl, REAL4TimeSeries ** fx, REAL4TimeSeries ** fy, const REAL4 D[3][3], const double ra, const double dec, const double psi, const LIGOTimeGPS * start, const double deltaT, const int n) { LIGOTimeGPS t; double gmst; int i; double p, c, b, l, x, y; *fplus = XLALCreateREAL4TimeSeries("plus", start, 0.0, deltaT, &lalDimensionlessUnit, n); *fcross = XLALCreateREAL4TimeSeries("cross", start, 0.0, deltaT, &lalDimensionlessUnit, n); *fb = XLALCreateREAL4TimeSeries("b", start, 0.0, deltaT, &lalDimensionlessUnit, n); *fl = XLALCreateREAL4TimeSeries("l", start, 0.0, deltaT, &lalDimensionlessUnit, n); *fx = XLALCreateREAL4TimeSeries("x", start, 0.0, deltaT, &lalDimensionlessUnit, n); *fy = XLALCreateREAL4TimeSeries("y", start, 0.0, deltaT, &lalDimensionlessUnit, n); if(!*fplus || !*fcross || !*fb || !*fl || !*fx || !*fy) { XLALDestroyREAL4TimeSeries(*fplus); XLALDestroyREAL4TimeSeries(*fcross); XLALDestroyREAL4TimeSeries(*fb); XLALDestroyREAL4TimeSeries(*fl); XLALDestroyREAL4TimeSeries(*fx); XLALDestroyREAL4TimeSeries(*fy); *fplus = *fcross = *fb = *fl = *fx = *fy = NULL; XLAL_ERROR(XLAL_EFUNC); } for(i = 0; i < n; i++) { t = *start; gmst = XLALGreenwichMeanSiderealTime(XLALGPSAdd(&t, i * deltaT)); if(XLAL_IS_REAL8_FAIL_NAN(gmst)) { XLALDestroyREAL4TimeSeries(*fplus); XLALDestroyREAL4TimeSeries(*fcross); XLALDestroyREAL4TimeSeries(*fb); XLALDestroyREAL4TimeSeries(*fl); XLALDestroyREAL4TimeSeries(*fx); XLALDestroyREAL4TimeSeries(*fy); *fplus = *fcross = *fb = *fl = *fx = *fy = NULL; XLAL_ERROR(XLAL_EFUNC); } XLALComputeDetAMResponseExtraModes(&p, &c, &b, &l, &x, &y, D, ra, dec, psi, gmst); (*fplus)->data->data[i] = p; (*fcross)->data->data[i] = c; (*fb)->data->data[i] = b; (*fl)->data->data[i] = l; (*fx)->data->data[i] = x; (*fy)->data->data[i] = y; } return 0; }
/* read a LIGO time series */ REAL4TimeSeries *get_ligo_data(LALFrStream *stream, CHAR *channel, LIGOTimeGPS start, LIGOTimeGPS end) { /* variables */ REAL4TimeSeries *series; size_t length; if (vrbflg) fprintf(stdout, "Allocating memory for \"%s\" series...\n", channel); /* create and initialise time series */ series = XLALCreateREAL4TimeSeries(channel, &start, 0, 0, \ &lalADCCountUnit, 0); if (vrbflg) fprintf(stdout, "Reading \"%s\" series metadata...\n", channel); /* get the series meta data */ XLALFrStreamGetREAL4TimeSeriesMetadata(series, stream); if (vrbflg) fprintf(stdout, "Resizing \"%s\" series...\n", channel); /* resize series to the correct number of samples */ length = floor((XLALGPSDiff(&end, &start) / series->deltaT) + 0.5); XLALResizeREAL4TimeSeries(series, 0, length); if (vrbflg) fprintf(stdout, "Reading channel \"%s\"...\n", channel); /* seek to and read data */ XLALFrStreamSeek(stream, &start); XLALFrStreamGetREAL4TimeSeries(series, stream); return(series); }
/* cut a time series between given start and end times */ REAL4TimeSeries *cut_time_series(REAL4TimeSeries *input, LIGOTimeGPS start, UINT4 duration) { /* variables */ REAL4TimeSeries *series; INT4 length; INT4 first; /* calculate length of segment to cut */ length = floor((duration / input->deltaT) + 0.5); /* get first bin */ first = (INT4)((start.gpsSeconds - input->epoch.gpsSeconds) / input->deltaT); /* allocate memory */ series = XLALCreateREAL4TimeSeries(input->name, &start, input->f0, \ input->deltaT, &input->sampleUnits, length); /* cut time series */ series = XLALCutREAL4TimeSeries(input, first, length); return(series); }
/** * function to generate random time-series with gaps, and corresponding SFTs */ int XLALgenerateRandomData ( REAL4TimeSeries **ts, SFTVector **sfts ) { /* input sanity checks */ XLAL_CHECK ( (ts != NULL) && ( (*ts) == NULL ), XLAL_EINVAL ); XLAL_CHECK ( (sfts != NULL) && ( (*sfts) == NULL ), XLAL_EINVAL ); // test parameters LIGOTimeGPS epoch0 = { 714180733, 0 }; UINT4 numSFTs = 20; REAL8 Tsft = 1000.0; // noise sigma REAL8 sigmaN = 0.1; /* prepare sampling constants */ REAL8 numR4SamplesPerSFT = 2 * 5000; REAL8 dtR4 = (Tsft / numR4SamplesPerSFT); UINT4 numR4SamplesTS = numSFTs * numR4SamplesPerSFT; /* ----- allocate timeseries ----- */ REAL4TimeSeries *outTS; // input timeseries XLAL_CHECK ( (outTS = XLALCreateREAL4TimeSeries ("H1:test timeseries", &epoch0, 0, dtR4, &emptyLALUnit, numR4SamplesTS )) != NULL, XLAL_EFUNC ); REAL4 *TSdata = outTS->data->data; /* initialize timeseries to zero (to allow for gaps) */ memset ( TSdata, 0, outTS->data->length * sizeof (*TSdata) ); /* also set up corresponding SFT timestamps vector */ LIGOTimeGPSVector *timestampsSFT; XLAL_CHECK ( (timestampsSFT = XLALCalloc (1, sizeof(*timestampsSFT)) ) != NULL, XLAL_ENOMEM ); XLAL_CHECK ( (timestampsSFT->data = XLALCalloc (numSFTs, sizeof (*timestampsSFT->data) )) != NULL, XLAL_ENOMEM ); timestampsSFT->length = numSFTs; /* ----- set up random-noise timeseries with gaps ---------- */ for ( UINT4 alpha=0; alpha < numSFTs; alpha ++ ) { /* record this SFT's timestamp */ timestampsSFT->data[alpha] = epoch0; timestampsSFT->data[alpha].gpsSeconds += lround( alpha * Tsft ); /* generate all data-points of this SFT */ for ( UINT4 j=0; j < numR4SamplesPerSFT; j++ ) { UINT4 alpha_j = alpha * numR4SamplesPerSFT + j; REAL8 ti = alpha * Tsft + j * dtR4; /* unit-variance Gaussian noise + sinusoid */ TSdata[alpha_j] = crealf ( testSignal ( ti, sigmaN ) ); } // for js < numR4SamplesPerSFT } /* for alpha < numSFTs */ /* ----- generate SFTs from this timeseries ---------- */ SFTParams XLAL_INIT_DECL(sftParams); sftParams.Tsft = Tsft; sftParams.timestamps = timestampsSFT; sftParams.noiseSFTs = NULL; sftParams.window = NULL; SFTVector *outSFTs; XLAL_CHECK ( (outSFTs = XLALSignalToSFTs ( outTS, &sftParams )) != NULL, XLAL_EFUNC ); /* free memory */ XLALFree ( timestampsSFT->data ); XLALFree ( timestampsSFT ); /* return timeseries and SFTvector */ (*ts) = outTS; (*sfts) = outSFTs; return XLAL_SUCCESS; } // XLALgenerateRandomData()
int test_XLALSincInterpolateSFT ( void ) { REAL8 f0 = 0; // heterodyning frequency REAL8 sigmaN = 0.001; REAL8 dt = 0.1; // sampling frequency = 10Hz LIGOTimeGPS epoch = { 100, 0 }; REAL8 tStart = XLALGPSGetREAL8 ( &epoch ); UINT4 numSamples = 1000; REAL8 Tspan = numSamples * dt; REAL8 df = 1.0 / Tspan; UINT4 numSamples0padded = 3 * numSamples; REAL8 Tspan0padded = numSamples0padded * dt; REAL8 df0padded = 1.0 / Tspan0padded; UINT4 numBins = NhalfPosDC ( numSamples ); UINT4 numBins0padded = NhalfPosDC ( numSamples0padded ); // original timeseries REAL4TimeSeries* ts; XLAL_CHECK ( (ts = XLALCreateREAL4TimeSeries ( "test TS_in", &epoch, f0, dt, &emptyLALUnit, numSamples )) != NULL, XLAL_EFUNC ); for ( UINT4 j = 0; j < numSamples; j ++ ) { ts->data->data[j] = crealf ( testSignal ( tStart + j * dt, sigmaN ) ); } // for j < numSamples // zero-padded to double length REAL4TimeSeries* ts0padded; XLAL_CHECK ( (ts0padded = XLALCreateREAL4TimeSeries ( "test TS_padded", &epoch, f0, dt, &emptyLALUnit, numSamples0padded )) != NULL, XLAL_EFUNC ); memcpy ( ts0padded->data->data, ts->data->data, numSamples * sizeof(ts0padded->data->data[0]) ); memset ( ts0padded->data->data + numSamples, 0, (numSamples0padded - numSamples) * sizeof(ts0padded->data->data[0]) ); // compute FFT on ts and ts0padded REAL4FFTPlan *plan, *plan0padded; XLAL_CHECK ( (plan = XLALCreateForwardREAL4FFTPlan ( numSamples, 0 )) != NULL, XLAL_EFUNC ); XLAL_CHECK ( (plan0padded = XLALCreateForwardREAL4FFTPlan ( numSamples0padded, 0 )) != NULL, XLAL_EFUNC ); COMPLEX8Vector *fft, *fft0padded; XLAL_CHECK ( (fft = XLALCreateCOMPLEX8Vector ( numBins )) != NULL, XLAL_ENOMEM ); XLAL_CHECK ( (fft0padded = XLALCreateCOMPLEX8Vector ( numBins0padded )) != NULL, XLAL_ENOMEM ); XLAL_CHECK ( XLALREAL4ForwardFFT ( fft, ts->data, plan ) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALREAL4ForwardFFT ( fft0padded, ts0padded->data, plan0padded ) == XLAL_SUCCESS, XLAL_EFUNC ); XLALDestroyREAL4TimeSeries ( ts ); XLALDestroyREAL4TimeSeries ( ts0padded ); XLALDestroyREAL4FFTPlan( plan ); XLALDestroyREAL4FFTPlan( plan0padded ); SFTtype XLAL_INIT_DECL(tmp); tmp.f0 = f0; tmp.deltaF = df; tmp.data = fft; REAL8 Band = 0.5/dt - f0; SFTtype *sft = NULL; XLAL_CHECK ( XLALExtractBandFromSFT ( &sft, &tmp, f0, Band ) == XLAL_SUCCESS, XLAL_EFUNC ); XLALDestroyCOMPLEX8Vector ( fft ); tmp.f0 = f0; tmp.deltaF = df0padded; tmp.data = fft0padded; SFTtype *sft0padded = NULL; XLAL_CHECK ( XLALExtractBandFromSFT ( &sft0padded, &tmp, f0, Band ) == XLAL_SUCCESS, XLAL_EFUNC ); XLALDestroyCOMPLEX8Vector ( fft0padded ); // ---------- interpolate input SFT onto frequency bins of padded-ts FFT for comparison UINT4 Dterms = 16; REAL8 safetyBins = (Dterms + 1.0); // avoid truncated interpolation to minimize errors, set to 0 for seeing boundary-effects [they're not so bad...] REAL8 fMin = f0 + safetyBins * df; fMin = round(fMin / df0padded) * df0padded; UINT4 numBinsOut = numBins0padded - 3 * safetyBins; REAL8 BandOut = (numBinsOut-1) * df0padded; SFTtype *sftUpsampled = NULL; XLAL_CHECK ( XLALExtractBandFromSFT ( &sftUpsampled, sft0padded, fMin + 0.5*df0padded, BandOut - df0padded ) == XLAL_SUCCESS, XLAL_EFUNC ); SFTtype *sftInterpolated; XLAL_CHECK ( (sftInterpolated = XLALSincInterpolateSFT ( sft, fMin, df0padded, numBinsOut, Dterms )) != NULL, XLAL_EFUNC ); // ----- out debug info if ( lalDebugLevel & LALINFO ) { XLAL_CHECK ( write_SFTdata ( "SFT_in.dat", sft ) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( write_SFTdata ( "SFT_in0padded.dat", sft0padded ) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( write_SFTdata ( "SFT_upsampled.dat", sftUpsampled ) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( write_SFTdata ( "SFT_interpolated.dat", sftInterpolated ) == XLAL_SUCCESS, XLAL_EFUNC ); } // if LALINFO // ---------- check accuracy of interpolation VectorComparison XLAL_INIT_DECL(tol); tol.relErr_L1 = 8e-2; tol.relErr_L2 = 8e-2; tol.angleV = 8e-2; tol.relErr_atMaxAbsx = 4e-3; tol.relErr_atMaxAbsy = 4e-3; XLALPrintInfo ("Comparing Dirichlet SFT interpolation with upsampled SFT:\n"); XLAL_CHECK ( XLALCompareSFTs ( sftUpsampled, sftInterpolated, &tol ) == XLAL_SUCCESS, XLAL_EFUNC ); // ---------- free memory XLALDestroySFT ( sft ); XLALDestroySFT ( sft0padded ); XLALDestroySFT ( sftUpsampled ); XLALDestroySFT ( sftInterpolated ); return XLAL_SUCCESS; } // test_XLALSincInterpolateSFT()
int main(void) { static LALStatus mystatus; /* variables for timing purposes */ clock_t start, diff; int msec; REAL4TimeSeries *h_plus; REAL4TimeSeries *h_cross; REAL8TimeSeries *hplus; REAL8TimeSeries *hcross; InspiralTemplate params; FILE *outputfile; INT4 i,length; REAL8 dt, m, m1, m2, nu, lambda1, lambda2; LIGOTimeGPS tc = LIGOTIMEGPSZERO; memset( &mystatus, 0, sizeof(LALStatus) ); memset( ¶ms, 0, sizeof(InspiralTemplate) ); m1 = 5.; m2 = 5.; m = m1 + m2; nu = m1 * m2 / m / m; lambda1 = 0.; lambda2 = 0.; LALSimInspiralWaveformFlags *waveFlags; waveFlags = XLALSimInspiralCreateWaveformFlags(); params.approximant = TaylorT4; params.order = LAL_PNORDER_THREE_POINT_FIVE; params.ampOrder = LAL_PNORDER_NEWTONIAN; params.mass1 = m1; params.mass2 = m2; params.totalMass = m; params.eta = nu; params.tSampling = 4096; params.fCutoff = 2047.; params.fLower = 40.; params.distance = 1e6 * LAL_PC_SI; params.ieta = 1; dt = 1. / params.tSampling; start = clock(); length = XLALSimInspiralTaylorT4PNRestricted(&hplus, &hcross, 0., dt, params.mass1*LAL_MSUN_SI, params.mass2*LAL_MSUN_SI, params.fLower, 0., params.distance, lambda1, lambda2, XLALSimInspiralGetTidalOrder(waveFlags), 0, 7); diff = clock() - start; msec = diff * 1000 / CLOCKS_PER_SEC; printf("Time taken %d seconds %d milliseconds\n", msec/1000, msec%1000); fprintf(stderr, "length = %i\n", length); fprintf(stderr, "T = %f\n", (float) length * dt); outputfile = fopen("T4wave1.dat","w"); length = hplus->data->length; for(i = 0; i < length; i++) { fprintf(outputfile,"%e\t%e\t%e\n", i*dt, hplus->data->data[i], hcross->data->data[i]); } fclose(outputfile); fprintf(stdout,"waveform saved in T4wave1.dat\n" ); start = clock(); h_plus = XLALCreateREAL4TimeSeries("", &tc, 0.0, dt, &lalDimensionlessUnit, 4096*3); h_cross = XLALCreateREAL4TimeSeries("", &tc, 0.0, dt, &lalDimensionlessUnit, 4096*3); fprintf(stderr, "Lower cut-off frequency used will be %fHz\n", params.fLower); /* --- now we can call the injection function --- */ LALTaylorT4WaveformTemplates(&mystatus, h_plus->data, h_cross->data, ¶ms); diff = clock() - start; msec = diff * 1000 / CLOCKS_PER_SEC; printf("Time taken %d seconds %d milliseconds\n", msec/1000, msec%1000); if ( mystatus.statusCode ) { fprintf( stderr, "LALInspiralTaylorT4Test: error generating waveform\n" ); exit( 1 ); } /* --- and finally save in a file --- */ outputfile = fopen("T4wave2.dat","w"); length = h_plus->data->length; for(i = 0; i < length; i++) { fprintf(outputfile,"%e\t%e\t%e\n", i*dt, h_plus->data->data[i], h_cross->data->data[i]); } fclose(outputfile); fprintf(stdout,"waveform saved in T4wave2.dat\n" ); return 0; }
void AddNumRelStrainModes( LALStatus *status, /**< pointer to LALStatus structure */ REAL4TimeVectorSeries **outStrain, /**< [out] h+, hx data */ SimInspiralTable *thisinj /**< [in] injection data */) { INT4 modeL, modeM, modeLlo, modeLhi; INT4 len, lenPlus, lenCross, k; CHAR *channel_name_plus; CHAR *channel_name_cross; LALFrStream *frStream = NULL; LALCache frCache; LIGOTimeGPS epoch; REAL4TimeSeries *seriesPlus=NULL; REAL4TimeSeries *seriesCross=NULL; REAL8 massMpc; REAL4TimeVectorSeries *sumStrain=NULL; REAL4TimeVectorSeries *tempStrain=NULL; /* NRWaveMetaData thisMetaData; */ INITSTATUS(status); ATTATCHSTATUSPTR (status); modeLlo = thisinj->numrel_mode_min; modeLhi = thisinj->numrel_mode_max; /* create a frame cache and open the frame stream */ frCache.length = 1; frCache.list = LALCalloc(1, sizeof(frCache.list[0])); frCache.list[0].url = thisinj->numrel_data; frStream = XLALFrStreamCacheOpen( &frCache ); /* the total mass of the binary in Mpc */ massMpc = (thisinj->mass1 + thisinj->mass2) * LAL_MRSUN_SI / ( LAL_PC_SI * 1.0e6); /* start time of waveform -- set it to something */ epoch.gpsSeconds = 0; epoch.gpsNanoSeconds = 0; /* loop over l values */ for ( modeL = modeLlo; modeL <= modeLhi; modeL++ ) { /* loop over m values */ for ( modeM = -modeL; modeM <= modeL; modeM++ ) { /* read numrel waveform */ /* first the plus polarization */ channel_name_plus = XLALGetNinjaChannelName("plus", modeL, modeM); /*get number of data points */ lenPlus = XLALFrStreamGetVectorLength ( channel_name_plus, frStream ); /* now the cross polarization */ channel_name_cross = XLALGetNinjaChannelName("cross", modeL, modeM); /*get number of data points */ lenCross = XLALFrStreamGetVectorLength ( channel_name_cross, frStream ); /* skip on to next mode if mode doesn't exist */ if ( (lenPlus <= 0) || (lenCross <= 0) || (lenPlus != lenCross) ) { XLALClearErrno(); LALFree(channel_name_plus); LALFree(channel_name_cross); continue; } /* note: lenPlus and lenCross must be equal if we got this far*/ /* len = lenPlus; */ len = lenPlus; /* allocate and read the plus/cross time series */ seriesPlus = XLALCreateREAL4TimeSeries ( channel_name_plus, &epoch, 0, 0, &lalDimensionlessUnit, len); memset(seriesPlus->data->data, 0, seriesPlus->data->length*sizeof(REAL4)); XLALFrStreamGetREAL4TimeSeries ( seriesPlus, frStream ); XLALFrStreamRewind( frStream ); LALFree(channel_name_plus); seriesCross = XLALCreateREAL4TimeSeries ( channel_name_cross, &epoch, 0, 0, &lalDimensionlessUnit, len); memset(seriesCross->data->data, 0, seriesCross->data->length*sizeof(REAL4)); XLALFrStreamGetREAL4TimeSeries ( seriesCross, frStream ); XLALFrStreamRewind( frStream ); LALFree(channel_name_cross); /* allocate memory for tempStrain */ tempStrain = LALCalloc(1, sizeof(*tempStrain)); tempStrain->data = XLALCreateREAL4VectorSequence(2, len); tempStrain->deltaT = LAL_MTSUN_SI * (thisinj->mass1 + thisinj->mass2) * seriesPlus->deltaT ; tempStrain->f0 = seriesPlus->f0; tempStrain->sampleUnits = seriesPlus->sampleUnits; memset(tempStrain->data->data, 0, tempStrain->data->length * tempStrain->data->vectorLength*sizeof(REAL4)); /* now copy the data and scale amplitude corresponding to distance of 1Mpc*/ for (k = 0; k < len; k++) { tempStrain->data->data[k] = massMpc * seriesPlus->data->data[k]; tempStrain->data->data[len + k] = massMpc * seriesCross->data->data[k]; } /* we are done with seriesPlus and Cross for this iteration */ XLALDestroyREAL4TimeSeries (seriesPlus); XLALDestroyREAL4TimeSeries (seriesCross); seriesPlus = NULL; seriesCross = NULL; /* compute the h+ and hx for given inclination and coalescence phase*/ XLALOrientNRWave( tempStrain, modeL, modeM, thisinj->inclination, thisinj->coa_phase ); if (sumStrain == NULL) { sumStrain = LALCalloc(1, sizeof(*sumStrain)); sumStrain->data = XLALCreateREAL4VectorSequence(2, tempStrain->data->vectorLength); sumStrain->deltaT = tempStrain->deltaT; sumStrain->f0 = tempStrain->f0; sumStrain->sampleUnits = tempStrain->sampleUnits; memset(sumStrain->data->data,0.0,2*tempStrain->data->vectorLength*sizeof(REAL4)); sumStrain = XLALSumStrain( sumStrain, tempStrain ); } else { sumStrain = XLALSumStrain( sumStrain, tempStrain ); } /* clear memory for strain */ if (tempStrain->data != NULL) { XLALDestroyREAL4VectorSequence ( tempStrain->data ); LALFree( tempStrain ); tempStrain = NULL; } } /* end loop over modeM values */ } /* end loop over modeL values */ XLALFrStreamClose( frStream ); LALFree(frCache.list); *outStrain = sumStrain; DETATCHSTATUSPTR(status); RETURN(status); }
int main( int argc, char *argv[] ) { LALStatus status = blank_status; UINT4 k; UINT4 kLow; UINT4 kHi; INT4 numPoints = 524288; REAL4 fSampling = 2048.; REAL4 fLow = 70.; REAL4 fLowInj = 40.; REAL8 deltaT = 1./fSampling; REAL8 deltaF = fSampling / numPoints; REAL4 statValue; /* vars required to make freq series */ LIGOTimeGPS epoch = { 0, 0 }; LIGOTimeGPS gpsStartTime = {0, 0}; REAL8 f0 = 0.; REAL8 offset = 0.; INT8 waveformStartTime = 0; /* files contain PSD info */ CHAR *injectionFile = NULL; CHAR *outputFile = NULL; CHAR *specFileH1 = NULL; CHAR *specFileH2 = NULL; CHAR *specFileL1 = NULL; COMPLEX8Vector *unity = NULL; const LALUnit strainPerCount = {0,{0,0,0,0,0,1,-1},{0,0,0,0,0,0,0}}; int numInjections = 0; int numTriggers = 0; /* template bank simulation variables */ INT4 injSimCount = 0; SimInspiralTable *injectionHead = NULL; SimInspiralTable *thisInjection = NULL; SnglInspiralTable *snglHead = NULL; SearchSummaryTable *searchSummHead = NULL; /*SummValueTable *summValueHead = NULL; */ /* raw input data storage */ REAL8FrequencySeries *specH1 = NULL; REAL8FrequencySeries *specH2 = NULL; REAL8FrequencySeries *specL1 = NULL; REAL8FrequencySeries *thisSpec = NULL; COMPLEX8FrequencySeries *resp = NULL; COMPLEX8FrequencySeries *detTransDummy = NULL; REAL4TimeSeries *chan = NULL; RealFFTPlan *pfwd = NULL; COMPLEX8FrequencySeries *fftData = NULL; REAL8 thisSnrsq = 0; REAL8 thisSnr = 0; REAL8 thisCombSnr = 0; REAL8 snrVec[3]; REAL8 dynRange = 1./(3.0e-23); /* needed for inj */ CoherentGW waveform; PPNParamStruc ppnParams; DetectorResponse detector; InterferometerNumber ifoNumber = LAL_UNKNOWN_IFO; /* output data */ LIGOLwXMLStream xmlStream; MetadataTable proctable; MetadataTable outputTable; MetadataTable procparams; CHAR fname[256]; CHAR comment[LIGOMETA_COMMENT_MAX]; ProcessParamsTable *this_proc_param = NULL; CHAR chanfilename[FILENAME_MAX]; REAL4 sum = 0; REAL4 bitten_H1 = 0; REAL4 bitten_H2 = 0; REAL4 thisCombSnr_H1H2 = 0; /* create the process and process params tables */ proctable.processTable = (ProcessTable *) calloc( 1, sizeof(ProcessTable) ); XLALGPSTimeNow(&(proctable.processTable->start_time)); XLALPopulateProcessTable(proctable.processTable, PROGRAM_NAME, lalAppsVCSIdentId, lalAppsVCSIdentStatus, lalAppsVCSIdentDate, 0); this_proc_param = procparams.processParamsTable = (ProcessParamsTable *) calloc( 1, sizeof(ProcessParamsTable) ); memset( comment, 0, LIGOMETA_COMMENT_MAX * sizeof(CHAR) ); /* look at input args, write process params where required */ while ( 1 ) { /* getopt arguments */ static struct option long_options[] = { /* these options set a flag */ /* these options do not set a flag */ {"help", no_argument, 0, 'h'}, {"verbose", no_argument, &vrbflg, 1 }, {"version", no_argument, 0, 'V'}, {"spectrum-H1", required_argument, 0, 'a'}, {"spectrum-H2", required_argument, 0, 'b'}, {"spectrum-L1", required_argument, 0, 'c'}, {"inj-file", required_argument, 0, 'd'}, {"comment", required_argument, 0, 'e'}, {"output-file", required_argument, 0, 'f'}, {"coire-flag", no_argument, &coireflg, 1 }, {"ligo-srd", no_argument, &ligosrd, 1 }, {"write-chan", no_argument, &writechan, 1 }, {"inject-overhead", no_argument, &injoverhead, 1 }, {"f-lower", required_argument, 0, 'g'}, {0, 0, 0, 0} }; int c; /* * * parse command line arguments * */ /* getopt_long stores long option here */ int option_index = 0; size_t optarg_len; c = getopt_long_only( argc, argv, "a:b:c:d:e:f:g:hV", long_options, &option_index ); /* detect the end of the options */ if ( c == - 1 ) { break; } switch ( c ) { case 0: /* if this option set a flag, do nothing else now */ if ( long_options[option_index].flag != 0 ) { break; } else { fprintf( stderr, "error parsing option %s with argument %s\n", long_options[option_index].name, optarg ); exit( 1 ); } break; case 'h': fprintf( stderr, USAGE ); exit( 0 ); break; case 'a': /* create storage for the spectrum file name */ optarg_len = strlen( optarg ) + 1; specFileH1 = (CHAR *) calloc( optarg_len, sizeof(CHAR)); memcpy( specFileH1, optarg, optarg_len ); ADD_PROCESS_PARAM( "string", "%s", optarg ); break; case 'b': /* create storage for the spectrum file name */ optarg_len = strlen( optarg ) + 1; specFileH2 = (CHAR *) calloc( optarg_len, sizeof(CHAR)); memcpy( specFileH2, optarg, optarg_len ); ADD_PROCESS_PARAM( "string", "%s", optarg ); break; case 'c': /* create storage for the spectrum file name */ optarg_len = strlen( optarg ) + 1; specFileL1 = (CHAR *) calloc( optarg_len, sizeof(CHAR)); memcpy( specFileL1, optarg, optarg_len ); ADD_PROCESS_PARAM( "string", "%s", optarg ); break; case 'd': /* create storage for the injection file name */ optarg_len = strlen( optarg ) + 1; injectionFile = (CHAR *) calloc( optarg_len, sizeof(CHAR)); memcpy( injectionFile, optarg, optarg_len ); ADD_PROCESS_PARAM( "string", "%s", optarg ); break; case 'f': /* create storage for the output file name */ optarg_len = strlen( optarg ) + 1; outputFile = (CHAR *) calloc( optarg_len, sizeof(CHAR)); memcpy( outputFile, optarg, optarg_len ); ADD_PROCESS_PARAM( "string", "%s", optarg ); break; case 'g': fLow = (INT4) atof( optarg ); if ( fLow < 40 ) { fprintf( stderr, "invalid argument to --%s:\n" "f-lower must be > 40Hz (%e specified)\n", long_options[option_index].name, fLow ); exit( 1 ); } ADD_PROCESS_PARAM( "float", "%e", fLow ); break; case 'e': if ( strlen( optarg ) > LIGOMETA_COMMENT_MAX - 1 ) { fprintf( stderr, "invalid argument to --%s:\n" "comment must be less than %d characters\n", long_options[option_index].name, LIGOMETA_COMMENT_MAX ); exit( 1 ); } else { snprintf( comment, LIGOMETA_COMMENT_MAX, "%s", optarg); } break; case 'V': /* print version information and exit */ fprintf( stdout, "calculation of expected SNR of injections\n" "Gareth Jones\n"); XLALOutputVersionString(stderr, 0); exit( 0 ); break; default: fprintf( stderr, "unknown error while parsing options\n" ); fprintf( stderr, USAGE ); exit( 1 ); } } if ( optind < argc ) { fprintf( stderr, "extraneous command line arguments:\n" ); while ( optind < argc ) { fprintf ( stderr, "%s\n", argv[optind++] ); } exit( 1 ); } /* check the input arguments */ if ( injectionFile == NULL ) { fprintf( stderr, "Must specify the --injection-file\n" ); exit( 1 ); } if ( outputFile == NULL ) { fprintf( stderr, "Must specify the --output-file\n" ); exit( 1 ); } if ( !ligosrd && specFileH1 == NULL ) { fprintf( stderr, "Must specify the --spectrum-H1\n" ); exit( 1 ); } if ( !ligosrd && specFileH2 == NULL ) { fprintf( stderr, "Must specify the --spectrum-H2\n" ); exit( 1 ); } if ( !ligosrd && specFileL1 == NULL ) { fprintf( stderr, "Must specify the --spectrum-L1\n" ); exit( 1 ); } if ( ligosrd && (specFileH1 || specFileH2 || specFileL1 )) { fprintf( stdout, "WARNING: using LIGOI SRD power spectral density \n" ); } if ( vrbflg ){ fprintf( stdout, "injection file is %s\n", injectionFile ); fprintf( stdout, "output file is %s\n", outputFile ); fprintf( stdout, "H1 spec file is %s\n", specFileH1 ); fprintf( stdout, "H2 spec file is %s\n", specFileH2 ); fprintf( stdout, "L1 spec file is %s\n", specFileL1 ); } /* create vector for H1, H2 and L1 spectrums */ specH1 = XLALCreateREAL8FrequencySeries ( "",&epoch, f0, deltaF, &lalADCCountUnit, (numPoints / 2 + 1) ); specH2 = XLALCreateREAL8FrequencySeries ( "",&epoch, f0, deltaF, &lalADCCountUnit, (numPoints / 2 + 1) ); specL1 = XLALCreateREAL8FrequencySeries ( "",&epoch, f0, deltaF, &lalADCCountUnit, (numPoints / 2 + 1) ); if (!specH1 || !specH2 || !specL1){ XLALDestroyREAL8FrequencySeries ( specH1 ); XLALDestroyREAL8FrequencySeries ( specH2 ); XLALDestroyREAL8FrequencySeries ( specL1 ); XLALPrintError("failure allocating H1, H2 and L1 spectra"); exit(1); } if (!ligosrd){ /* read in H1 spectrum */ LAL_CALL( LALDReadFrequencySeries(&status, specH1, specFileH1), &status ); if ( vrbflg ){ fprintf( stdout, "read in H1 spec file\n" ); fflush( stdout ); } /* read in H2 spectrum */ LAL_CALL( LALDReadFrequencySeries(&status, specH2, specFileH2), &status ); if ( vrbflg ){ fprintf( stdout, "read in H2 spec file\n" ); fflush( stdout ); } /* read in L1 spectrum */ LAL_CALL( LALDReadFrequencySeries(&status, specL1, specFileL1), &status ); if ( vrbflg ){ fprintf( stdout, "read in L1 spec file\n" ); fflush( stdout ); } } chan = XLALCreateREAL4TimeSeries( "", &epoch, f0, deltaT, &lalADCCountUnit, numPoints ); if ( !chan ){ XLALPrintError("failure allocating chan"); exit(1); } /* * * set up the response function * */ resp = XLALCreateCOMPLEX8FrequencySeries( chan->name, &chan->epoch, f0, deltaF, &strainPerCount, (numPoints / 2 + 1) ); if ( !resp ){ XLALPrintError("failure allocating response function"); exit(1); } /* create vector that will contain detector.transfer info, since this * is constant I calculate it once outside of all the loops and pass it * in to detector.transfer when required */ detTransDummy = XLALCreateCOMPLEX8FrequencySeries( chan->name, &chan->epoch, f0, deltaF, &strainPerCount, (numPoints / 2 + 1) ); if ( !detTransDummy ){ XLALPrintError("failure allocating detector.transfer info"); exit(1); } /* invert the response function to get the transfer function */ unity = XLALCreateCOMPLEX8Vector( resp->data->length ); for ( k = 0; k < unity->length; ++k ) { unity->data[k] = 1.0; } /* set response */ for ( k = 0; k < resp->data->length; ++k ) { resp->data->data[k] = 1.0; } XLALCCVectorDivide( detTransDummy->data, unity, resp->data ); XLALDestroyCOMPLEX8Vector( unity ); /* read in injections from injection file */ /* set endtime to 0 so that we read in all events */ if ( vrbflg ) fprintf( stdout, "Reading sim_inspiral table of %s\n", injectionFile ); LAL_CALL(numInjections = SimInspiralTableFromLIGOLw( &injectionHead, injectionFile, 0, 0), &status); if ( vrbflg ) fprintf( stdout, "Read %d injections from sim_inspiral table of %s\n", numInjections, injectionFile ); if (coireflg){ if ( vrbflg ) fprintf( stdout, "Reading sngl_inspiral table of %s\n", injectionFile ); LAL_CALL(numTriggers = LALSnglInspiralTableFromLIGOLw(&snglHead, injectionFile, 0, -1), &status); if ( vrbflg ) fprintf( stdout, "Read %d triggers from sngl_inspiral table of %s\n", numTriggers, injectionFile ); if ( vrbflg ) { fprintf( stdout, "Reading search_summary table of %s ...", injectionFile ); fflush( stdout ); } searchSummHead = XLALSearchSummaryTableFromLIGOLw (injectionFile); if ( vrbflg ) fprintf( stdout, " done\n"); } /* make sure we start at head of linked list */ thisInjection = injectionHead; /* setting fixed waveform injection parameters */ memset( &ppnParams, 0, sizeof(PPNParamStruc) ); ppnParams.deltaT = deltaT; ppnParams.lengthIn = 0; ppnParams.ppn = NULL; /* loop over injections */ injSimCount = 0; do { fprintf( stdout, "injection %d/%d\n", injSimCount+1, numInjections ); /* reset waveform structure */ memset( &waveform, 0, sizeof(CoherentGW) ); /* reset chan structure */ memset( chan->data->data, 0, chan->data->length * sizeof(REAL4) ); if (thisInjection->f_lower == 0){ fprintf( stdout, "WARNING: f_lower in sim_inpiral = 0, "); fprintf( stdout, "changing this to %e\n ", fLowInj); thisInjection->f_lower = fLowInj; } /* create the waveform, amp, freq phase etc */ LAL_CALL( LALGenerateInspiral(&status, &waveform, thisInjection, &ppnParams), &status); if (vrbflg) fprintf( stdout, "ppnParams.tc %e\n ", ppnParams.tc); statValue = 0.; /* calc lower index for integration */ kLow = ceil(fLow / deltaF); if ( vrbflg ) { fprintf( stdout, "starting integration to find SNR at frequency %e ", fLow); fprintf( stdout, "at index %d \n", kLow); } /* calc upper index for integration */ kHi = floor(fSampling / (2. * deltaF)); if ( vrbflg ) { fprintf( stdout, "ending integration to find SNR at frequency %e ", fSampling / 2.); fprintf( stdout, "at index %d \n", kHi); } /* loop over ifo */ for ( ifoNumber = 1; ifoNumber < 4; ifoNumber++ ) { /* allocate memory and copy the parameters describing the freq series */ memset( &detector, 0, sizeof( DetectorResponse ) ); detector.site = (LALDetector *) LALMalloc( sizeof(LALDetector) ); if (injoverhead){ if ( vrbflg ) fprintf( stdout, "WARNING: perform overhead injections\n"); /* setting detector.site to NULL causes SimulateCoherentGW to * perform overhead injections */ detector.site = NULL; } else { /* if not overhead, set detector.site using ifonumber */ XLALReturnDetector( detector.site, ifoNumber ); } switch ( ifoNumber ) { case 1: if ( vrbflg ) fprintf( stdout, "looking at H1 \n"); thisSpec = specH1; break; case 2: if ( vrbflg ) fprintf( stdout, "looking at H2 \n"); thisSpec = specH2; break; case 3: if ( vrbflg ) fprintf( stdout, "looking at L1 \n"); thisSpec = specL1; break; default: fprintf( stderr, "Error: ifoNumber %d does not correspond to H1, H2 or L1: \n", ifoNumber ); exit( 1 ); } /* get the gps start time of the signal to inject */ waveformStartTime = XLALGPSToINT8NS( &(thisInjection->geocent_end_time) ); waveformStartTime -= (INT8) ( 1000000000.0 * ppnParams.tc ); offset = (chan->data->length / 2.0) * chan->deltaT; gpsStartTime.gpsSeconds = thisInjection->geocent_end_time.gpsSeconds - offset; gpsStartTime.gpsNanoSeconds = thisInjection->geocent_end_time.gpsNanoSeconds; chan->epoch = gpsStartTime; if (vrbflg) fprintf(stdout, "offset start time of injection by %f seconds \n", offset ); /* is this okay? copying in detector transfer which so far only contains response info */ detector.transfer = detTransDummy; XLALUnitInvert( &(detector.transfer->sampleUnits), &(resp->sampleUnits) ); /* 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) ); /* perform the injection */ LAL_CALL( LALSimulateCoherentGW(&status, chan, &waveform, &detector ), &status); if (writechan){ /* write out channel data */ if (vrbflg) fprintf(stdout, "writing channel data to file... \n" ); switch ( ifoNumber ) { case 1: snprintf( chanfilename, FILENAME_MAX, "chanTest_H1_inj%d.dat", injSimCount+1); if (vrbflg) fprintf( stdout, "writing H1 channel time series out to %s\n", chanfilename ); LALSPrintTimeSeries(chan, chanfilename ); break; case 2: snprintf( chanfilename, FILENAME_MAX, "chanTest_H2_inj%d.dat", injSimCount+1); if (vrbflg) fprintf( stdout, "writing H2 channel time series out to %s\n", chanfilename ); LALSPrintTimeSeries(chan, chanfilename ); break; case 3: snprintf( chanfilename, FILENAME_MAX, "chanTest_L1_inj%d.dat", injSimCount+1); if (vrbflg) fprintf( stdout, "writing L1 channel time series out to %s\n", chanfilename ); LALSPrintTimeSeries(chan, chanfilename ); break; default: fprintf( stderr, "Error: ifoNumber %d does not correspond to H1, H2 or L1: \n", ifoNumber ); exit( 1 ); } } LAL_CALL( LALCreateForwardRealFFTPlan( &status, &pfwd, chan->data->length, 0), &status); fftData = XLALCreateCOMPLEX8FrequencySeries( chan->name, &chan->epoch, f0, deltaF, &lalDimensionlessUnit, (numPoints / 2 + 1) ); if ( !fftData ){ XLALPrintError("failure allocating fftData"); exit(1); } LAL_CALL( LALTimeFreqRealFFT( &status, fftData, chan, pfwd ), &status); LAL_CALL( LALDestroyRealFFTPlan( &status, &pfwd ), &status); pfwd = NULL; /* compute the SNR */ thisSnrsq = 0; /* avoid f=0 part of psd */ if (ligosrd){ if (vrbflg) fprintf( stdout, "using LIGOI PSD \n"); for ( k = kLow; k < kHi; k++ ) { REAL8 freq; REAL8 sim_psd_value; freq = fftData->deltaF * k; LALLIGOIPsd( NULL, &sim_psd_value, freq ); thisSnrsq += ((crealf(fftData->data->data[k]) * dynRange) * (crealf(fftData->data->data[k]) * dynRange)) / sim_psd_value; thisSnrsq += ((cimagf(fftData->data->data[k]) * dynRange) * (cimagf(fftData->data->data[k]) * dynRange)) / sim_psd_value; } } else { if (vrbflg) fprintf( stdout, "using input spectra \n"); for ( k = kLow; k < kHi; k++ ) { thisSnrsq += ((crealf(fftData->data->data[k]) * dynRange) * (crealf(fftData->data->data[k]) * dynRange)) / (thisSpec->data->data[k] * dynRange * dynRange); thisSnrsq += ((cimagf(fftData->data->data[k]) * dynRange) * (cimagf(fftData->data->data[k]) * dynRange)) / (thisSpec->data->data[k] * dynRange * dynRange); } } thisSnrsq *= 4*fftData->deltaF; thisSnr = pow(thisSnrsq, 0.5); /* Note indexing on snrVec, ifoNumber runs from 1..3 to get source correct, * we must index snrVec 0..2 */ snrVec[ifoNumber-1] = thisSnr; XLALDestroyCOMPLEX8FrequencySeries(fftData); if ( vrbflg ){ fprintf( stdout, "thisSnrsq %e\n", thisSnrsq ); fprintf( stdout, "snrVec %e\n", snrVec[ifoNumber-1] ); fflush( stdout ); } /* sum thisSnrsq to eventually get combined snr*/ statValue += thisSnrsq; /* free some memory */ if (detector.transfer) detector.transfer = NULL; if ( detector.site ) {LALFree( detector.site); detector.site = NULL;} } /* end loop over ifo */ destroyCoherentGW( &waveform ); /* store inverse eff snrs in eff_dist columns */ thisInjection->eff_dist_h = 1./snrVec[0]; thisInjection->eff_dist_g = 1./snrVec[1]; thisInjection->eff_dist_l = 1./snrVec[2]; /* store inverse sum of squares snr in eff_dist_t */ thisCombSnr = pow(statValue, 0.5); if ( vrbflg ) fprintf( stdout, "thisCombSnr %e\n", thisCombSnr); thisInjection->eff_dist_t = 1./thisCombSnr; /* calc inverse bittenL snr for H1H2 and store in eff_dist_v */ thisCombSnr_H1H2 = 0.; sum = snrVec[0] * snrVec[0] + snrVec[1] * snrVec[1]; bitten_H1 = 3 * snrVec[0] -3; bitten_H2 = 3 * snrVec[1] -3; if (sum < bitten_H1){ thisCombSnr_H1H2 = sum; } else { thisCombSnr_H1H2 = bitten_H1; } if (bitten_H2 < thisCombSnr_H1H2){ thisCombSnr_H1H2 = bitten_H2; } thisInjection->eff_dist_v = 1./thisCombSnr_H1H2; /* increment the bank sim sim_inspiral table if necessary */ if ( injectionHead ) { thisInjection = thisInjection->next; } } while ( ++injSimCount < numInjections ); /* end loop over injections */ /* try opening, writing and closing an xml file */ /* open the output xml file */ memset( &xmlStream, 0, sizeof(LIGOLwXMLStream) ); snprintf( fname, sizeof(fname), "%s", outputFile); LAL_CALL( LALOpenLIGOLwXMLFile ( &status, &xmlStream, fname), &status); /* write out the process and process params tables */ if ( vrbflg ) fprintf( stdout, "process... " ); XLALGPSTimeNow(&(proctable.processTable->end_time)); LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, process_table ), &status ); LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, proctable, process_table ), &status ); LAL_CALL( LALEndLIGOLwXMLTable ( &status, &xmlStream ), &status ); free( proctable.processTable ); /* Just being pedantic here ... */ proctable.processTable = NULL; /* free the unused process param entry */ this_proc_param = procparams.processParamsTable; procparams.processParamsTable = procparams.processParamsTable->next; free( this_proc_param ); this_proc_param = NULL; /* write the process params table */ if ( vrbflg ) fprintf( stdout, "process_params... " ); LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, process_params_table ), &status ); LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, procparams, process_params_table ), &status ); LAL_CALL( LALEndLIGOLwXMLTable ( &status, &xmlStream ), &status ); /* write the search summary table */ if ( coireflg ){ if ( vrbflg ) fprintf( stdout, "search_summary... " ); outputTable.searchSummaryTable = searchSummHead; LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, search_summary_table), &status); LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, outputTable, search_summary_table), &status); LAL_CALL( LALEndLIGOLwXMLTable ( &status, &xmlStream), &status); } /* write the sim inspiral table */ if ( vrbflg ) fprintf( stdout, "sim_inspiral... " ); outputTable.simInspiralTable = injectionHead; LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, sim_inspiral_table), &status); LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, outputTable, sim_inspiral_table), &status); LAL_CALL( LALEndLIGOLwXMLTable ( &status, &xmlStream), &status); /* write the sngl inspiral table */ if ( coireflg ){ if ( vrbflg ) fprintf( stdout, "sngl_inspiral... " ); outputTable.snglInspiralTable = snglHead; LAL_CALL( LALBeginLIGOLwXMLTable( &status, &xmlStream, sngl_inspiral_table), &status); LAL_CALL( LALWriteLIGOLwXMLTable( &status, &xmlStream, outputTable, sngl_inspiral_table), &status); LAL_CALL( LALEndLIGOLwXMLTable ( &status, &xmlStream), &status); } /* close the xml file */ LAL_CALL( LALCloseLIGOLwXMLFile ( &status, &xmlStream), &status); /* Freeing memory */ XLALDestroyREAL4TimeSeries(chan); XLALDestroyCOMPLEX8FrequencySeries(resp); XLALDestroyCOMPLEX8FrequencySeries(detTransDummy); XLALDestroyREAL8FrequencySeries ( specH1 ); XLALDestroyREAL8FrequencySeries ( specH2 ); XLALDestroyREAL8FrequencySeries ( specL1 ); free( specFileH1 ); specFileH1 = NULL; free( specFileH2 ); specFileH2 = NULL; free( specFileL1 ); specFileL1 = NULL; free( injectionFile ); injectionFile = NULL; /* free the process params */ while( procparams.processParamsTable ) { this_proc_param = procparams.processParamsTable; procparams.processParamsTable = this_proc_param->next; free( this_proc_param ); this_proc_param = NULL; } /* free the sim inspiral tables */ while ( injectionHead ) { thisInjection = injectionHead; injectionHead = injectionHead->next; LALFree( thisInjection ); } /*check for memory leaks */ LALCheckMemoryLeaks(); exit( 0 ); }
int XLALASCIIFileReadCalFac( REAL4TimeSeries **alpha, REAL4TimeSeries **lal_gamma, const char *fname ) { const REAL8 fuzzfactor = 1e-3; /* fraction of a sample of fuzziness */ REAL8 fuzz; /* possible discrepancies in times */ char alphaName[] = "Xn:CAL-CAV_FAC"; char gammaName[] = "Xn:CAL-OLOOP_FAC"; LALDataFileNameFields fileFields; LALCalFacFileNameDescriptionFields descFields; REAL8VectorSequence *data; LIGOTimeGPS epoch; REAL8 tstart; REAL8 tend; REAL4 deltaT; int ndat; int nrow; int row; int dat; if ( ! alpha || ! lal_gamma ) XLAL_ERROR( XLAL_EFAULT ); if ( *alpha || *lal_gamma ) XLAL_ERROR( XLAL_EINVAL ); if ( XLALDataFileNameParse( &fileFields, fname ) < 0 ) { XLALPrintError( "XLAL Error - %s: invalid file name %s\n", __func__, fname ); XLAL_ERROR( XLAL_EINVAL ); } if ( XLALCalFacFileNameDescriptionParse( &descFields, fileFields.description ) < 0 ) { XLALPrintError( "XLAL Error - %s: invalid description part of file name %s\n", __func__, fname ); XLAL_ERROR( XLAL_EINVAL ); } XLALPrintInfo( "XLAL Info - %s: Reading calibration factors from file %s\n", __func__, fname ); /* setup channel names */ memcpy( alphaName, descFields.ifo, 2 ); memcpy( gammaName, descFields.ifo, 2 ); deltaT = XLALASCIIFileReadCalFacHeader( fname ); if ( XLAL_IS_REAL4_FAIL_NAN( deltaT ) ) XLAL_ERROR( XLAL_EFUNC ); if ( deltaT <= 0 ) /* bad time step */ XLAL_ERROR( XLAL_EDATA ); /* check consistency of time steps */ if ( fabs( descFields.deltaT - deltaT ) > 1 ) /* step in file name might only be accurate to one second */ XLAL_ERROR( XLAL_EDATA ); /* read three columns */ data = XLALASCIIFileReadColumns( 3, fname ); if ( ! data ) XLAL_ERROR( XLAL_EFUNC ); if ( ! data->length ) { XLALPrintError( "XLAL Error - %s: no rows of data\n", __func__ ); XLAL_ERROR( XLAL_EFAILED ); } nrow = data->length; /* sanity checks on time stamps */ /* check for mismatch in start or end times compared to file name */ tstart = ELEM(data,0,1); tend = ELEM(data,nrow-1,1); ndat = 1 + (int)floor( (tend - tstart)/deltaT + 0.5 ); if ( ( fileFields.tstart != (int)floor( tstart ) ) || ( fileFields.tstart + fileFields.duration != (int)ceil( tend + deltaT ) ) ) { XLALPrintError( "XLAL Error - %s: filename start time and duration not consistent with contents\n", __func__ ); XLALDestroyREAL8VectorSequence( data ); XLAL_ERROR( XLAL_EDATA ); } if ( nrow > ndat ) /* this should be impossible */ { XLALDestroyREAL8VectorSequence( data ); XLAL_ERROR( XLAL_EDATA ); } XLALGPSSetREAL8( &epoch, tstart ); *alpha = XLALCreateREAL4TimeSeries( alphaName, &epoch, 0.0, deltaT, &lalDimensionlessUnit, ndat ); *lal_gamma = XLALCreateREAL4TimeSeries( gammaName, &epoch, 0.0, deltaT, &lalDimensionlessUnit, ndat ); if ( ! *alpha || ! *lal_gamma ) { XLALDestroyREAL4TimeSeries( *lal_gamma ); XLALDestroyREAL4TimeSeries( *alpha ); XLALDestroyREAL8VectorSequence( data ); XLAL_ERROR( XLAL_EFUNC ); } /* clear the data memory */ memset( (*alpha)->data->data, 0, (*alpha)->data->length * sizeof( *(*alpha)->data->data ) ); memset( (*lal_gamma)->data->data, 0, (*lal_gamma)->data->length * sizeof( *(*lal_gamma)->data->data ) ); /* IMPORTANT: SPECIFICATION SAYS THAT ALPHA IS COL 2 AND GAMMA IS COL 3 */ fuzz = fuzzfactor * deltaT; dat = -1; for ( row = 0; row < nrow; ++row ) { int line = ELEM(data,row,0); REAL8 trow = ELEM(data,row,1); REAL4 alphaval = ELEM(data,row,2); REAL4 gammaval = ELEM(data,row,3); int thisdat = (int)floor( (trow - tstart) / deltaT + 0.5 ); if ( thisdat <= dat ) /* rows must be monotonically increasing in time */ { XLALPrintError( "XLAL Error - %s: error on line %d of file %s\n\trows must be monotonically increasing in time\n", __func__, line, fname ); XLALDestroyREAL4TimeSeries( *lal_gamma ); XLALDestroyREAL4TimeSeries( *alpha ); XLALDestroyREAL8VectorSequence( data ); XLAL_ERROR( XLAL_EDATA ); } dat = thisdat; if ( fabs( (tstart + dat * deltaT) - trow ) > fuzz ) /* time between rows must be an integral multiple of deltaT */ { XLALPrintError( "XLAL Error - %s: error on line %d of file %s\n\ttimes must be integral multiples of deltaT\n", __func__, line, fname ); XLALDestroyREAL4TimeSeries( *lal_gamma ); XLALDestroyREAL4TimeSeries( *alpha ); XLALDestroyREAL8VectorSequence( data ); XLAL_ERROR( XLAL_EDATA ); } if ( dat >= ndat ) /* beyond length of array */ { printf( "%d\t%d\n", dat, ndat ); XLALPrintError( "XLAL Error - %s: error on line %d of file %s\n\ttime beyond end time\n", __func__, line, fname ); XLALDestroyREAL4TimeSeries( *lal_gamma ); XLALDestroyREAL4TimeSeries( *alpha ); XLALDestroyREAL8VectorSequence( data ); XLAL_ERROR( XLAL_EDATA ); } (*alpha)->data->data[dat] = alphaval; (*lal_gamma)->data->data[dat] = gammaval; } XLALDestroyREAL8VectorSequence( data ); return 0; }
/** * Single-IFO version of XLALCWMakeFakeMultiData(), handling the actual * work, but same input API. The 'detectorIndex' has the index of the detector * to be used from the multi-IFO arrays. */ int XLALCWMakeFakeData ( SFTVector **SFTvect, REAL8TimeSeries **Tseries, const PulsarParamsVector *injectionSources, const CWMFDataParams *dataParams, UINT4 detectorIndex, /* index for current detector in dataParams */ const EphemerisData *edat ) { XLAL_CHECK ( (SFTvect == NULL) || ((*SFTvect) == NULL ), XLAL_EINVAL ); XLAL_CHECK ( (Tseries == NULL) || ((*Tseries) == NULL ), XLAL_EINVAL ); XLAL_CHECK ( (SFTvect != NULL) || (Tseries != NULL), XLAL_EINVAL ); XLAL_CHECK ( edat != NULL, XLAL_EINVAL ); XLAL_CHECK ( dataParams != NULL, XLAL_EINVAL ); XLAL_CHECK ( detectorIndex < dataParams->multiIFO.length, XLAL_EINVAL ); XLAL_CHECK ( detectorIndex < dataParams->multiNoiseFloor.length, XLAL_EINVAL ); XLAL_CHECK ( detectorIndex < dataParams->multiTimestamps.length, XLAL_EINVAL ); XLAL_CHECK ( (dataParams->inputMultiTS == NULL) || (detectorIndex < dataParams->inputMultiTS->length), XLAL_EINVAL ); XLAL_CHECK ( (dataParams->inputMultiTS == NULL) || (dataParams->fMin == 0 && dataParams->Band == 0), XLAL_EINVAL, "If given time-series, must have fMin=Band=0\n"); // initial default values fMin, sampling rate from caller input or timeseries REAL8 fMin = dataParams->fMin; REAL8 fBand = dataParams->Band; REAL8 fSamp = 2.0 * fBand; if ( dataParams->inputMultiTS != NULL ) { XLAL_CHECK ( (fMin == 0) && (fBand == 0), XLAL_EINVAL, "fMin and fBand must be 0 if input timeseries is given\n"); const REAL8TimeSeries *ts = dataParams->inputMultiTS->data[detectorIndex]; XLAL_CHECK ( ts != NULL, XLAL_EINVAL ); REAL8 dt = ts->deltaT; fMin = ts->f0; fSamp = 1.0 / dt; fBand = 0.5 * fSamp; } const LIGOTimeGPSVector *timestamps = dataParams->multiTimestamps.data[detectorIndex]; const LALDetector *site = &dataParams->multiIFO.sites[detectorIndex]; REAL8 Tsft = timestamps->deltaT; // if SFT output requested: need *effective* fMin and Band consistent with SFT bins if ( SFTvect ) { UINT4 firstBinEff, numBinsEff; XLAL_CHECK ( XLALFindCoveringSFTBins ( &firstBinEff, &numBinsEff, fMin, fBand, Tsft ) == XLAL_SUCCESS, XLAL_EFUNC ); REAL8 fBand_eff = (numBinsEff - 1.0) / Tsft; REAL8 fMin_eff = firstBinEff / Tsft; REAL8 fMax = fMin + dataParams->Band; REAL8 fMax_eff = fMin_eff + fBand_eff; if ( (fMin_eff != fMin) || (fBand_eff != fBand ) ) { XLALPrintWarning("Caller asked for Band [%.16g, %.16g] Hz, effective SFT-Band produced is [%.16g, %.16g] Hz\n", fMin, fMax, fMin_eff, fMax_eff ); XLAL_CHECK ( dataParams->inputMultiTS == NULL, XLAL_EINVAL, "Cannot expand effective frequency band with input timeseries given. Timeseries seems inconsistent with SFTs\n"); fMin = fMin_eff; // (potentially) lower minimal frequency to fit SFT bins fBand = fBand_eff; fSamp = 2.0 * fBand_eff; // (potentially) higher sampling rate required to fit SFT bins } // if (fMin_eff != fMin) || (fBand_eff != fBand) } // if SFT-output requested // characterize the output time-series UINT4 n0_fSamp = (UINT4) round ( Tsft * fSamp ); // by construction, fSamp * Tsft = integer, but if there are gaps between SFTs, // then we might have to sample at higher rates in order for all SFT-boundaries to // fall on exact timesteps of the timeseries. // ie we start from fsamp0 = n0_fSamp/Tsft, and then try to find the smallest // n1_fSamp >= n0_fSamp, such that for fsamp1 = n1_fSamp/Tsft, for all gaps i: Dt_i * fsamp1 = int UINT4 n1_fSamp; XLAL_CHECK ( XLALFindSmallestValidSamplingRate ( &n1_fSamp, n0_fSamp, timestamps ) == XLAL_SUCCESS, XLAL_EFUNC ); if ( n1_fSamp != n0_fSamp ) { REAL8 fSamp1 = n1_fSamp / Tsft; // increased sampling rate to fit all gaps XLALPrintWarning ( "GAPS: Initial SFT sampling frequency fSamp0= %d/%.0f = %g had to be increased to fSamp1 = %d/%.0f = %g\n", n0_fSamp, Tsft, fSamp, n1_fSamp, Tsft, fSamp1 ); XLAL_CHECK ( dataParams->inputMultiTS == NULL, XLAL_EINVAL, "Cannot expand effective frequency band with input timeseries given. Timeseries seems inconsistent with SFT timestamps\n"); fSamp = fSamp1; } // if higher effective sampling rate required // ----- start-time and duration ----- LIGOTimeGPS firstGPS = timestamps->data[0]; REAL8 firstGPS_REAL8 = XLALGPSGetREAL8 ( &firstGPS ); LIGOTimeGPS lastGPS = timestamps->data [ timestamps->length - 1 ]; REAL8 lastGPS_REAL8 = XLALGPSGetREAL8 ( &lastGPS ); XLALGPSAdd( &lastGPS, Tsft ); REAL8 duration = XLALGPSDiff ( &lastGPS, &firstGPS ); // start with an empty output time-series REAL4TimeSeries *Tseries_sum; { REAL8 numSteps = ceil ( fSamp * duration ); XLAL_CHECK ( numSteps < (REAL8)LAL_UINT4_MAX, XLAL_EDOM, "Sorry, time-series of %g samples too long to fit into REAL4TimeSeries (maxLen = %g)\n", numSteps, (REAL8)LAL_UINT4_MAX ); REAL8 dt = 1.0 / fSamp; REAL8 fHeterodyne = fMin; // heterodyne signals at lower end of frequency-band CHAR *detPrefix = XLALGetChannelPrefix ( site->frDetector.name ); XLAL_CHECK ( (Tseries_sum = XLALCreateREAL4TimeSeries ( detPrefix, &firstGPS, fHeterodyne, dt, &lalStrainUnit, (UINT4)numSteps )) != NULL, XLAL_EFUNC ); memset ( Tseries_sum->data->data, 0, Tseries_sum->data->length * sizeof(Tseries_sum->data->data[0]) ); XLALFree ( detPrefix ); } // generate empty timeseries // add CW signals, if any UINT4 numPulsars = injectionSources ? injectionSources->length : 0; for ( UINT4 iInj = 0; iInj < numPulsars; iInj ++ ) { // truncate any transient-CW timeseries to the actual support of the transient signal, // in order to make the generation more efficient, these 'partial timeseries' // will then be added to the full timeseries const PulsarParams *pulsarParams = &( injectionSources->data[iInj] ); UINT4 t0, t1; XLAL_CHECK ( XLALGetTransientWindowTimespan ( &t0, &t1, pulsarParams->Transient ) == XLAL_SUCCESS, XLAL_EFUNC ); // use latest possible start-time: max(t0,firstGPS), but not later than than lastGPS LIGOTimeGPS XLAL_INIT_DECL(signalStartGPS); if ( t0 <= firstGPS_REAL8 ) { signalStartGPS = firstGPS; } else if ( t0 >= lastGPS_REAL8 ) { signalStartGPS = lastGPS; } else { signalStartGPS.gpsSeconds = t0; } // use earliest possible end-time: min(t1,lastGPS), but not earlier than firstGPS LIGOTimeGPS XLAL_INIT_DECL(signalEndGPS); if ( t1 >= lastGPS_REAL8 ) { signalEndGPS = lastGPS; } else if ( t1 <= firstGPS_REAL8 ) { signalEndGPS = firstGPS; } else { signalEndGPS.gpsSeconds = t1; } REAL8 signalDuration = XLALGPSDiff ( &signalEndGPS, &signalStartGPS ); XLAL_CHECK ( signalDuration >= 0, XLAL_EFAILED, "Something went wrong, got negative signal duration = %g\n", signalDuration ); if ( signalDuration > 0 ) // only need to do sth if transient-window had finite overlap with output TS { REAL4TimeSeries *Tseries_i = NULL; XLAL_CHECK ( (Tseries_i = XLALGenerateCWSignalTS ( pulsarParams, site, signalStartGPS, signalDuration, fSamp, fMin, edat )) != NULL, XLAL_EFUNC ); XLAL_CHECK ( (Tseries_sum = XLALAddREAL4TimeSeries ( Tseries_sum, Tseries_i )) != NULL, XLAL_EFUNC ); XLALDestroyREAL4TimeSeries ( Tseries_i ); } } // for iInj < numSources /* add Gaussian noise if requested */ REAL8 sqrtSn = dataParams->multiNoiseFloor.sqrtSn[detectorIndex]; if ( sqrtSn > 0) { REAL8 noiseSigma = sqrtSn * sqrt ( 0.5 * fSamp ); INT4 randSeed = (dataParams->randSeed == 0) ? 0 : (dataParams->randSeed + detectorIndex); // seed=0 means to use /dev/urandom, so don't touch it XLAL_CHECK ( XLALAddGaussianNoise ( Tseries_sum, noiseSigma, randSeed ) == XLAL_SUCCESS, XLAL_EFUNC ); } // convert final signal+Gaussian-noise timeseries into REAL8 precision: REAL8TimeSeries *outTS; XLAL_CHECK ( (outTS = XLALConvertREAL4TimeSeriesToREAL8 ( Tseries_sum )) != NULL, XLAL_EFUNC ); XLALDestroyREAL4TimeSeries ( Tseries_sum ); // add input noise time-series here if given if ( dataParams->inputMultiTS != NULL ) { XLAL_CHECK ( (outTS = XLALAddREAL8TimeSeries ( outTS, dataParams->inputMultiTS->data[detectorIndex] )) != NULL, XLAL_EFUNC ); } // turn final timeseries into SFTs, if requested if ( SFTvect != NULL ) { // compute SFTs from timeseries SFTVector *sftVect; XLAL_CHECK ( (sftVect = XLALMakeSFTsFromREAL8TimeSeries ( outTS, timestamps, dataParams->SFTWindowType, dataParams->SFTWindowBeta)) != NULL, XLAL_EFUNC ); // extract effective band from this, if neccessary (ie if faster-sampled output SFTs) if ( n1_fSamp != n0_fSamp ) { XLAL_CHECK ( ((*SFTvect) = XLALExtractBandFromSFTVector ( sftVect, fMin, fBand )) != NULL, XLAL_EFUNC ); XLALDestroySFTVector ( sftVect ); } else { (*SFTvect) = sftVect; } } // if SFTvect // return timeseries if requested if ( Tseries != NULL ) { (*Tseries) = outTS; } else { XLALDestroyREAL8TimeSeries ( outTS ); } return XLAL_SUCCESS; } // XLALCWMakeFakeData()
/* * main program entry point */ INT4 main(INT4 argc, CHAR **argv) { /* status */ LALStatus status = blank_status; /* counters */ int c; UINT4 i; /* mode counters */ UINT4 l, m; /* metadata file/directory */ CHAR *nrMetaFile = NULL; CHAR *nrDataDir = NULL; CHAR file_path[FILENAME_MAX]; /* metadata format */ CHAR *metadata_format = NULL; /* metadata parsing variables */ LALParsedDataFile *meta_file = NULL; BOOLEAN wasRead = 0; CHAR field[HISTORY_COMMENT]; CHAR *wf_name[MAX_L+1][(2*MAX_L) + 1]; /* common metadata */ CHAR *md_mass_ratio = NULL; CHAR *md_spin1x = NULL; CHAR *md_spin1y = NULL; CHAR *md_spin1z = NULL; CHAR *md_spin2x = NULL; CHAR *md_spin2y = NULL; CHAR *md_spin2z = NULL; CHAR *md_freq_start_22 = NULL; /* NINJA1 metadata */ CHAR *md_simulation_details = NULL; CHAR *md_nr_group = NULL; CHAR *md_email = NULL; /* NINJA2 metadata */ CHAR *md_waveform_name = NULL; CHAR *md_initial_separation = NULL; CHAR *md_eccentricity = NULL; CHAR *md_number_of_cycles_22 = NULL; CHAR *md_code = NULL; CHAR *md_submitter_email = NULL; CHAR *md_authors_emails = NULL; /* common metadata strings */ CHAR str_mass_ratio[HISTORY_COMMENT]; CHAR str_spin1x[HISTORY_COMMENT]; CHAR str_spin1y[HISTORY_COMMENT]; CHAR str_spin1z[HISTORY_COMMENT]; CHAR str_spin2x[HISTORY_COMMENT]; CHAR str_spin2y[HISTORY_COMMENT]; CHAR str_spin2z[HISTORY_COMMENT]; CHAR str_freq_start_22[HISTORY_COMMENT]; CHAR str_creator[HISTORY_COMMENT]; /* NINJA1 metadata strings */ CHAR str_simulation_details[HISTORY_COMMENT]; CHAR str_nr_group[HISTORY_COMMENT]; CHAR str_email[HISTORY_COMMENT]; /* NINJA2 metadata strings */ CHAR str_waveform_name[HISTORY_COMMENT]; CHAR str_initial_separation[HISTORY_COMMENT]; CHAR str_eccentricity[HISTORY_COMMENT]; CHAR str_number_of_cycles_22[HISTORY_COMMENT]; CHAR str_code[HISTORY_COMMENT]; CHAR str_submitter_email[HISTORY_COMMENT]; CHAR str_authors_emails[HISTORY_COMMENT]; /* channel names */ CHAR *plus_channel[MAX_L+1][(2*MAX_L) + 1]; CHAR *cross_channel[MAX_L+1][(2*MAX_L) + 1]; /* waveforms */ UINT4 wf_length; REAL4TimeVectorSeries *waveforms[MAX_L][(2*MAX_L) + 1]; REAL4TimeSeries *hplus[MAX_L+1][(2*MAX_L) + 1]; REAL4TimeSeries *hcross[MAX_L+1][(2*MAX_L) + 1]; REAL8TimeVectorSeries *waveformsREAL8[MAX_L][(2*MAX_L) + 1]; REAL8TimeSeries *hplusREAL8[MAX_L+1][(2*MAX_L) + 1]; REAL8TimeSeries *hcrossREAL8[MAX_L+1][(2*MAX_L) + 1]; /* frame variables */ LALFrameH *frame; CHAR *frame_name = NULL; LIGOTimeGPS epoch; INT4 duration; INT4 detector_flags; INT4 generatingREAL8 = 0; /* LALgetopt arguments */ struct LALoption long_options[] = { /* options that set a flag */ {"verbose", no_argument, &vrbflg, 1}, /* options that don't set a flag */ {"format", required_argument, 0, 'f'}, {"nr-meta-file", required_argument, 0, 'm'}, {"nr-data-dir", required_argument, 0, 'd'}, {"output", required_argument, 0, 'o'}, {"double-precision", no_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {0, 0, 0, 0} }; /* default debug level */ lal_errhandler = LAL_ERR_EXIT; /* parse the arguments */ while(1) { /* LALgetopt_long stores long option here */ int option_index = 0; size_t LALoptarg_len; c = LALgetopt_long_only(argc, argv, "f:m:d:o:phV", long_options, &option_index); /* detect the end of the options */ if (c == -1) break; switch(c) { case 0: /* if this option sets a flag, do nothing else for now */ if (long_options[option_index].flag != 0) break; else { fprintf(stderr, "Error parsing option %s with argument %s\n", long_options[option_index].name, LALoptarg); exit(1); } break; case 'h': /* help message */ print_usage(stdout, argv[0]); exit(0); break; case 'V': /* print version information and exit */ fprintf(stdout, "Numerical Relativity Frame Generation\n"); XLALOutputVersionString(stderr, 0); exit(0); break; case 'f': /* create storage for the metadata format */ LALoptarg_len = strlen(LALoptarg) + 1; metadata_format = (CHAR *)calloc(LALoptarg_len, sizeof(CHAR)); memcpy(metadata_format, LALoptarg, LALoptarg_len); break; case 'm': /* create storage for the meta file name */ LALoptarg_len = strlen(LALoptarg) + 1; nrMetaFile = (CHAR *)calloc(LALoptarg_len, sizeof(CHAR)); memcpy(nrMetaFile, LALoptarg, LALoptarg_len); break; case 'd': /* create storage for the meta data directory name */ LALoptarg_len = strlen(LALoptarg) + 1; nrDataDir = (CHAR *)calloc(LALoptarg_len, sizeof(CHAR)); memcpy(nrDataDir, LALoptarg, LALoptarg_len); break; case 'o': /* create storage for the output frame file name */ LALoptarg_len = strlen(LALoptarg) + 1; frame_name = (CHAR *)calloc(LALoptarg_len, sizeof(CHAR)); memcpy(frame_name, LALoptarg, LALoptarg_len); break; case 'p': /* We're generating a double-precision frame */ generatingREAL8 = 1; break; case '?': print_usage(stderr, argv[0]); exit(1); break; default: fprintf(stderr, "Unknown error while parsing arguments\n"); print_usage(stderr, argv[0]); exit(1); break; } } /* check for extraneous command line arguments */ if (LALoptind < argc) { fprintf(stderr, "Extraneous command line arguments:\n"); while(LALoptind < argc) fprintf(stderr, "%s\n", argv[LALoptind++]); exit(1); } /* * check validity of arguments */ /* metadata format specified */ if (metadata_format == NULL) { fprintf(stderr, "warning: --format not specified, assuming NINJA1\n"); metadata_format = (CHAR *)calloc(7, sizeof(CHAR)); memcpy(metadata_format, "NINJA1", 7); } /* check for supported metadata format */ if (strcmp(metadata_format, "NINJA1") == 0); else if (strcmp(metadata_format, "NINJA2") == 0); else { fprintf(stderr, "Supported metadata formats are NINJA1 and NINJA2 (%s specified)\n", metadata_format); exit(1); } /* meta file specified */ if (nrMetaFile == NULL) { fprintf(stderr, "--nr-meta-file must be specified\n"); exit(1); } /* data directory specified */ if (nrDataDir == NULL) { fprintf(stderr, "--nr-data-dir must be specified\n"); exit(1); } /* output frame filename specified */ if (frame_name == NULL) { fprintf(stderr, "--output must be specified\n"); exit(1); } /* * main code */ /* frame metadata */ /* TODO: set these to something sensible */ duration = 0; epoch.gpsSeconds = 0; epoch.gpsNanoSeconds = 0; detector_flags = 0; if (vrbflg) fprintf(stdout, "reading metadata: %s\n", nrMetaFile); /* open metadata file */ XLAL_CHECK ( XLALParseDataFile(&meta_file, nrMetaFile) == XLAL_SUCCESS, XLAL_EFUNC ); /* * get metadata */ /* common metadata */ XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_mass_ratio, meta_file, NULL, "mass-ratio", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_spin1x, meta_file, NULL, "spin1x", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_spin1y, meta_file, NULL, "spin1y", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_spin1z, meta_file, NULL, "spin1z", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_spin2x, meta_file, NULL, "spin2x", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_spin2y, meta_file, NULL, "spin2y", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_spin2z, meta_file, NULL, "spin2z", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); /* format specific metadata */ if (strcmp(metadata_format, "NINJA1") == 0) { /* NINJA1 */ XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_simulation_details, meta_file, NULL, "simulation-details", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_nr_group, meta_file, NULL, "nr-group", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_email, meta_file, NULL, "email", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_freq_start_22, meta_file, NULL, "freqStart22", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); } else if (strcmp(metadata_format, "NINJA2") == 0) { /* NINJA2 */ XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_waveform_name, meta_file, NULL, "waveform-name", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_initial_separation, meta_file, NULL, "initial-separation", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_eccentricity, meta_file, NULL, "eccentricity", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_number_of_cycles_22, meta_file, NULL, "number-of-cycles-22", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_code, meta_file, NULL, "code", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_submitter_email, meta_file, NULL, "submitter-email", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_authors_emails, meta_file, NULL, "authors-emails", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &md_freq_start_22, meta_file, NULL, "freq-start-22", &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); } else { /* unknown metadata format - should not be executed */ fprintf(stderr, "error: unsupported metadata format: %s\n", metadata_format); exit(1); } /* * set metadata strings */ /* common waveform */ snprintf(str_mass_ratio, HISTORY_COMMENT, "mass-ratio:%s", md_mass_ratio); snprintf(str_spin1x, HISTORY_COMMENT, "spin1x:%s", md_spin1x); snprintf(str_spin1y, HISTORY_COMMENT, "spin1y:%s", md_spin1y); snprintf(str_spin1z, HISTORY_COMMENT, "spin1z:%s", md_spin1z); snprintf(str_spin2x, HISTORY_COMMENT, "spin2x:%s", md_spin2x); snprintf(str_spin2y, HISTORY_COMMENT, "spin2y:%s", md_spin2y); snprintf(str_spin2z, HISTORY_COMMENT, "spin2z:%s", md_spin2z); snprintf(str_creator, HISTORY_COMMENT, "creator:%s(git:%s)", PROGRAM_NAME, lalAppsVCSId); /* format specific metadata */ if (strcmp(metadata_format, "NINJA1") == 0) { /* NINJA1 */ snprintf(str_freq_start_22, HISTORY_COMMENT, "freqStart22:%s", md_freq_start_22); snprintf(str_simulation_details, HISTORY_COMMENT, "simulation-details:%s", md_simulation_details); snprintf(str_nr_group, HISTORY_COMMENT, "nr-group:%s", md_nr_group); snprintf(str_email, HISTORY_COMMENT, "email:%s", md_email); } else if (strcmp(metadata_format, "NINJA2") == 0) { /* NINJA2 */ snprintf(str_waveform_name, HISTORY_COMMENT, "waveform-name:%s", md_waveform_name); snprintf(str_initial_separation, HISTORY_COMMENT, "inital-separation:%s", md_initial_separation); snprintf(str_eccentricity, HISTORY_COMMENT, "eccentricity:%s", md_eccentricity); snprintf(str_freq_start_22, HISTORY_COMMENT, "freq_start_22:%s", md_freq_start_22); snprintf(str_number_of_cycles_22, HISTORY_COMMENT, "number-of-cycles-22:%s", md_number_of_cycles_22); snprintf(str_code, HISTORY_COMMENT, "code:%s", md_code); snprintf(str_submitter_email, HISTORY_COMMENT, "submitter-email:%s", md_submitter_email); snprintf(str_authors_emails, HISTORY_COMMENT, "authors-emails:%s", md_authors_emails); } else { /* unknown metadata format - should not be executed */ fprintf(stderr, "error: unsupported metadata format: %s\n", metadata_format); exit(1); } /* define frame */ frame = XLALFrameNew(&epoch, duration, "NR", 0, 1, detector_flags); /* * add metadata as FrHistory structures */ /* common metadata */ XLALFrameAddFrHistory(frame, "creator", str_creator); XLALFrameAddFrHistory(frame, "mass-ratio", str_mass_ratio); XLALFrameAddFrHistory(frame, "spin1x", str_spin1x); XLALFrameAddFrHistory(frame, "spin1y", str_spin1y); XLALFrameAddFrHistory(frame, "spin1z", str_spin1z); XLALFrameAddFrHistory(frame, "spin2x", str_spin2x); XLALFrameAddFrHistory(frame, "spin2y", str_spin2y); XLALFrameAddFrHistory(frame, "spin2z", str_spin2z); /* format specific metadata */ if (strcmp(metadata_format, "NINJA1") == 0) { /* NINJA1 */ XLALFrameAddFrHistory(frame, "simulation-details", str_simulation_details); XLALFrameAddFrHistory(frame, "nr-group", str_nr_group); XLALFrameAddFrHistory(frame, "email", str_email); XLALFrameAddFrHistory(frame, "freqStart22", str_freq_start_22); } else if (strcmp(metadata_format, "NINJA2") == 0) { /* NINJA2 */ XLALFrameAddFrHistory(frame, "waveform-name", str_waveform_name); XLALFrameAddFrHistory(frame, "initial-separation", str_initial_separation); XLALFrameAddFrHistory(frame, "eccentricity", str_eccentricity); XLALFrameAddFrHistory(frame, "freq_start_22", str_freq_start_22); XLALFrameAddFrHistory(frame, "number-of-cycles-22", str_number_of_cycles_22); XLALFrameAddFrHistory(frame, "code", str_code); XLALFrameAddFrHistory(frame, "submitter-email", str_code); XLALFrameAddFrHistory(frame, "authors-emails", str_authors_emails); } else { /* unknown metadata format - should not be executed */ fprintf(stderr, "error: unsupported metadata format: %s\n", metadata_format); exit(1); } /* loop over l & m values */ for (l = MIN_L; l <= MAX_L; l++) { for (m = (MAX_L - l); m <= MAX_L + l; m++) { /* ensure pointers are NULL */ wf_name[l][m] = NULL; plus_channel[l][m] = NULL; cross_channel[l][m] = NULL; /* generate channel names */ plus_channel[l][m] = XLALGetNinjaChannelName("plus", l, m - MAX_L); cross_channel[l][m] = XLALGetNinjaChannelName("cross", l, m - MAX_L); if (generatingREAL8) { hplusREAL8[l][m] = NULL; hcrossREAL8[l][m] = NULL; waveformsREAL8[l][m] = NULL; /* initilise waveform time series */ hplusREAL8[l][m] = XLALCreateREAL8TimeSeries(plus_channel[l][m], &epoch, 0, 0, &lalDimensionlessUnit, 0); hcrossREAL8[l][m] = XLALCreateREAL8TimeSeries(cross_channel[l][m], &epoch, 0, 0, &lalDimensionlessUnit, 0); } else { hplus[l][m] = NULL; hcross[l][m] = NULL; waveforms[l][m] = NULL; /* initilise waveform time series */ hplus[l][m] = XLALCreateREAL4TimeSeries(plus_channel[l][m], &epoch, 0, 0, &lalDimensionlessUnit, 0); hcross[l][m] = XLALCreateREAL4TimeSeries(cross_channel[l][m], &epoch, 0, 0, &lalDimensionlessUnit, 0); } /* read ht-data section of metadata file */ snprintf(field, HISTORY_COMMENT, "%d,%d", l, m - MAX_L); XLAL_CHECK ( XLALReadConfigSTRINGVariable( &wf_name[l][m], meta_file, NULL, field, &wasRead) == XLAL_SUCCESS, XLAL_EFUNC ); /* read waveform */ if (wf_name[l][m] != NULL) { /* get full path to waveform data file */ snprintf(file_path, FILENAME_MAX, "%s/%s", nrDataDir, wf_name[l][m]); if (vrbflg) fprintf(stdout, "reading waveform: %s\n", file_path); /* read waveforms */ if (generatingREAL8) { LAL_CALL(LALReadNRWave_raw_real8(&status, &waveformsREAL8[l][m], file_path), &status); } else { LAL_CALL(LALReadNRWave_raw(&status, &waveforms[l][m], file_path), &status); } } /* generate waveform time series from vector series */ /* TODO: should use pointer arithmetic here and update the data * pointer in the REAL4TimeSeries to point to the appropriate * location within the REAL4TimeVector Series */ if (generatingREAL8) { if (waveformsREAL8[l][m]) { /* get length of waveform */ wf_length = waveformsREAL8[l][m]->data->vectorLength; /* allocate memory for waveform */ XLALResizeREAL8TimeSeries(hplusREAL8[l][m], 0, wf_length); XLALResizeREAL8TimeSeries(hcrossREAL8[l][m], 0, wf_length); /* set time spacing */ hplusREAL8[l][m]->deltaT = waveformsREAL8[l][m]->deltaT; hcrossREAL8[l][m]->deltaT = waveformsREAL8[l][m]->deltaT; /* copy waveforms into appropriate series */ for (i = 0; i < wf_length; i ++) { hplusREAL8[l][m]->data->data[i] = waveformsREAL8[l][m]->data->data[i]; hcrossREAL8[l][m]->data->data[i] = waveformsREAL8[l][m]->data->data[wf_length + i]; } /* Done with waveformsREAL8, clean up here to limit memory usage */ LALFree(waveformsREAL8[l][m]->data->data); LALFree(waveformsREAL8[l][m]->data); LALFree(waveformsREAL8[l][m]); } } else /* REAL4 */ { if (waveforms[l][m]) { /* get length of waveform */ wf_length = waveforms[l][m]->data->vectorLength; /* allocate memory for waveform */ XLALResizeREAL4TimeSeries(hplus[l][m], 0, wf_length); XLALResizeREAL4TimeSeries(hcross[l][m], 0, wf_length); /* set time spacing */ hplus[l][m]->deltaT = waveforms[l][m]->deltaT; hcross[l][m]->deltaT = waveforms[l][m]->deltaT; /* copy waveforms into appropriate series */ for (i = 0; i < wf_length; i ++) { hplus[l][m]->data->data[i] = waveforms[l][m]->data->data[i]; hcross[l][m]->data->data[i] = waveforms[l][m]->data->data[wf_length + i]; } } } /* add channels to frame */ if (generatingREAL8) { if ((hplusREAL8[l][m]->data->length) && (hcrossREAL8[l][m]->data->length)) { XLALFrameAddREAL8TimeSeriesSimData(frame, hplusREAL8[l][m]); XLALFrameAddREAL8TimeSeriesSimData(frame, hcrossREAL8[l][m]); } } else { if ((hplus[l][m]->data->length) && (hcross[l][m]->data->length)) { XLALFrameAddREAL4TimeSeriesSimData(frame, hplus[l][m]); XLALFrameAddREAL4TimeSeriesSimData(frame, hcross[l][m]); } } } } if (vrbflg) fprintf(stdout, "writing frame: %s\n", frame_name); /* write frame */ if (XLALFrameWrite(frame, frame_name) != 0 ) { fprintf(stderr, "Error: Cannot save frame file '%s'\n", frame_name); exit(1); } /* * clear memory */ /* strings */ if(nrMetaFile) free(nrMetaFile); if(nrDataDir) free(nrDataDir); if(frame_name) free(frame_name); if(metadata_format) free(metadata_format); /* common metadata */ if(md_mass_ratio) LALFree(md_mass_ratio); if(md_spin1x) LALFree(md_spin1x); if(md_spin1y) LALFree(md_spin1y); if(md_spin1z) LALFree(md_spin1z); if(md_spin2x) LALFree(md_spin2x); if(md_spin2y) LALFree(md_spin2y); if(md_spin2z) LALFree(md_spin2z); if(md_freq_start_22) LALFree(md_freq_start_22); /* NINJA1 metadata */ if(md_simulation_details) LALFree(md_simulation_details); if(md_nr_group) LALFree(md_nr_group); if(md_email) LALFree(md_email); /* NINJA2 metadata */ if(md_waveform_name) LALFree(md_waveform_name); if(md_initial_separation) LALFree(md_initial_separation); if(md_eccentricity) LALFree(md_eccentricity); if(md_number_of_cycles_22) LALFree(md_number_of_cycles_22); if(md_code) LALFree(md_code); if(md_submitter_email) LALFree(md_submitter_email); if(md_authors_emails) LALFree(md_authors_emails); /* config file */ if(meta_file->lines->list->data) LALFree(meta_file->lines->list->data); if(meta_file->lines->list) LALFree(meta_file->lines->list); if(meta_file->lines->tokens) LALFree(meta_file->lines->tokens); if(meta_file->lines) LALFree(meta_file->lines); if(meta_file->wasRead) LALFree(meta_file->wasRead); if(meta_file) LALFree(meta_file); /* waveforms */ if (generatingREAL8) { for (l = MIN_L; l <= MAX_L; l++) { for (m = (MAX_L - l); m <= MAX_L + l; m++) { /* channel names */ if (plus_channel[l][m]) LALFree(plus_channel[l][m]); if (cross_channel[l][m]) LALFree(cross_channel[l][m]); if (wf_name[l][m]) LALFree(wf_name[l][m]); /* hplus */ if (hplusREAL8[l][m]) XLALDestroyREAL8TimeSeries(hplusREAL8[l][m]); /* hcross */ if (hcrossREAL8[l][m]) XLALDestroyREAL8TimeSeries(hcrossREAL8[l][m]); } } } else { for (l = MIN_L; l <= MAX_L; l++) { for (m = (MAX_L - l); m <= MAX_L + l; m++) { /* channel names */ if (plus_channel[l][m]) LALFree(plus_channel[l][m]); if (cross_channel[l][m]) LALFree(cross_channel[l][m]); if (wf_name[l][m]) LALFree(wf_name[l][m]); /* raw waveforms */ if (waveforms[l][m]) { LALFree(waveforms[l][m]->data->data); LALFree(waveforms[l][m]->data); LALFree(waveforms[l][m]); } /* hplus */ if (hplus[l][m]) XLALDestroyREAL4TimeSeries(hplus[l][m]); /* hcross */ if (hcross[l][m]) XLALDestroyREAL4TimeSeries(hcross[l][m]); } } } /* clear frame */ XLALFrameFree(frame); /* check for memory leaks */ LALCheckMemoryLeaks(); exit(0); }
/* read and high pass filter a GEO time series */ REAL4TimeSeries *get_geo_data(LALFrStream *stream, CHAR *channel, LIGOTimeGPS start, LIGOTimeGPS end, INT4 hpf_order, REAL8 hpf_frequency, REAL8 hpf_attenuation) { /* variables */ PassBandParamStruc high_pass_params; REAL4TimeSeries *series; REAL8TimeSeries *geo; size_t length; size_t i; if (vrbflg) fprintf(stdout, "Allocating memory for \"%s\" series...\n", channel); /* create and initialise time series */ geo = XLALCreateREAL8TimeSeries(channel, &start, 0, 0, \ &lalADCCountUnit, 0); if (vrbflg) fprintf(stdout, "Reading \"%s\" series metadata...\n", channel); /* get the series meta data */ XLALFrStreamGetREAL8TimeSeriesMetadata(geo, stream); if (vrbflg) fprintf(stdout, "Resizing \"%s\" series...\n", channel); /* resize series to the correct number of samples */ length = floor((XLALGPSDiff(&end, &start) / geo->deltaT) + 0.5); XLALResizeREAL8TimeSeries(geo, 0, length); if (vrbflg) fprintf(stdout, "Reading channel \"%s\"...\n", channel); /* seek to and read data */ XLALFrStreamSeek(stream, &start); XLALFrStreamGetREAL8TimeSeries(geo, stream); if (vrbflg) fprintf(stdout, "High pass filtering \"%s\"...\n", channel); /* high pass filter before casting to a REAL4 */ high_pass_params.nMax = hpf_order; high_pass_params.f1 = -1; high_pass_params.f2 = hpf_frequency; high_pass_params.a1 = -1; high_pass_params.a2 = hpf_attenuation; XLALButterworthREAL8TimeSeries(geo, &high_pass_params); if (vrbflg) fprintf(stdout, "Casting \"%s\" as a REAL4...\n", channel); /* cast as a REAL4 */ series = XLALCreateREAL4TimeSeries(geo->name, &geo->epoch, geo->f0, \ geo->deltaT, &geo->sampleUnits, geo->data->length); for (i = 0; i < series->data->length; i++) series->data->data[i] = (REAL4)geo->data->data[i]; /* destroy geo series */ XLALDestroyREAL8TimeSeries(geo); return(series); }
/** * Simulate a pulsar signal to best accuracy possible. * \author Reinhard Prix * \date 2005 * * The motivation for this function is to provide functions to * simulate pulsar signals <em>with the best possible accuracy</em>, * i.e. using no approximations, contrary to LALGeneratePulsarSignal(). * * Obviously this is not meant as a fast code to be used in a Monte-Carlo * simulation, but rather as a <em>reference</em> to compare other (faster) * functions agains, in order to be able to gauge the quality of a given * signal-generation routine. * * We want to calculate \f$h(t)\f$, given by * \f[ * h(t) = F_+(t)\, h_+(t) + F_\times(t) \,h_\times(t)\,, * \f] * where \f$F_+\f$ and \f$F_x\f$ are called the <em>beam-pattern</em> functions, * which depend of the wave polarization \f$\psi\f$, * the source position \f$\alpha\f$, \f$\delta\f$ and the detector position and * orientation (\f$\gamma\f$, \f$\lambda\f$, \f$L\f$ and \f$\xi\f$). The expressions for * the beam-pattern functions are given in \cite JKS98 , which we write as * \f{eqnarray}{ * F_+(t) = \sin \zeta \cos 2\psi \, a(t) + \sin \zeta \sin 2\psi \, b(t)\,,\\ * F_\times(t) = \sin\zeta \cos 2\psi \,b(t) - \sin\zeta \sin 2\psi \, a(t) \,, * \f} * where \f$\zeta\f$ is the angle between the interferometer arms, and * \f{eqnarray}{ * a(t) &=& a_1 \cos[ 2 (\alpha - T)) ] + a_2 \sin[ 2(\alpha - T)] * + a_3 \cos[ \alpha - T ] + a_4 \sin [ \alpha - T ] + a_5\,,\\ * b(t) &=& b_1 \cos[ 2(\alpha - T)] + b_2 \sin[ 2(\alpha - T) ] * + b_3 \cos[ \alpha - T ] + b_4 \sin[ \alpha - T]\,, * \f} * where \f$T\f$ is the local (mean) sidereal time of the detector, and the * time-independent coefficients \f$a_i\f$ and \f$b_i\f$ are given by * \f{eqnarray}{ * a_1 &=& \frac{1}{16} \sin 2\gamma \,(3- \cos 2\lambda)\,(3 - \cos 2\delta)\,,\\ * a_2 &=& -\frac{1}{4}\cos 2\gamma \,\sin \lambda \,(3 - \cos 2\delta) \,,\\ * a_3 &=& \frac{1}{4} \sin 2\gamma \,\sin 2\lambda \,\sin 2\delta \,\\ * a_4 &=& -\frac{1}{2} \cos 2\gamma \,\cos \lambda \,\sin 2 \delta\,,\\ * a_5 &=& \frac{3}{4} \sin 2\gamma \, \cos^2 \lambda \,\cos^2 \delta\,, * \f} * and * \f{eqnarray}{ * b_1 &=& \cos 2\gamma \,\sin \lambda \,\sin \delta\,,\\ * b_2 &=& \frac{1}{4} \sin 2\gamma \,(3-\cos 2\lambda)\, \sin \delta\,,\\ * b_3 &=& \cos 2\gamma \,\cos \lambda \,\cos\delta \,, \\ * b_4 &=& \frac{1}{2} \sin2\gamma \,\sin 2\lambda \,\cos\delta\,, * \f} * * The source model considered is a plane-wave * \f{eqnarray}{ * h_+(t) &=& A_+\, \cos \Psi(t)\,,\\ * h_\times(t) &=& A_\times \, \sin \Psi(t)\,, * \f} * where the wave-phase is \f$\Psi(t) = \Phi_0 + \Phi(t)\f$, and for an * isolated pulsar we have * \f{equation}{ * \Phi(t) = 2\pi \left[\sum_{s=0} \frac{f^{(s)}(\tau_\mathrm{ref})}{ * (s+1)!} \left( \tau(t) - \tau_\mathrm{ref} \right)^{s+1} \right]\,, * \f} * where \f$\tau_\mathrm{ref}\f$ is the "reference time" for the definition * of the pulsar-parameters \f$f^{(s)}\f$ in the solar-system barycenter * (SSB), and \f$\tau(t)\f$ is the SSB-time of the phase arriving at the * detector at UTC-time \f$t\f$, which depends on the source-position * (\f$\alpha\f$, \f$\delta\f$) and the detector-position, namely * \f{equation}{ * \tau (t) = t + \frac{ \vec{r}(t)\cdot\vec{n}}{c}\,, * \f} * where \f$\vec{r}(t)\f$ is the vector from SSB to the detector, and \f$\vec{n}\f$ * is the unit-vector pointing <em>to</em> the source. * * This is a standalone "clean-room" implementation using no other * outside-functions <em>except</em> for LALGPStoLMST1() to calculate * the local (mean) sidereal time at the detector for given GPS-time, * (which I double-checked with an independent Mathematica script), * and and XLALBarycenter() to calculate \f$\tau(t)\f$. * * NOTE: currently only isolated pulsars are supported * * NOTE2: we don't really use the highest possible accuracy right now, * as we blatently neglect all relativistic timing effects (i.e. using dT=v.n/c) * * NOTE3: no heterodyning is performed here, the time-series is generated and sampled * at the given rate, that's all! ==\> the caller needs to make sure about the * right sampling rate to use (-\>aliasing) and do the proper post-treatment... * */ REAL4TimeSeries * XLALSimulateExactPulsarSignal ( const PulsarSignalParams *params ) { XLAL_CHECK_NULL ( params != NULL, XLAL_EINVAL, "Invalid NULL input 'params'\n"); XLAL_CHECK_NULL ( params->samplingRate > 0, XLAL_EDOM, "Sampling rate must be positive, got samplingRate = %g\n", params->samplingRate ); /* don't accept heterodyning frequency */ XLAL_CHECK_NULL ( params->fHeterodyne == 0, XLAL_EINVAL, "Heterodyning frequency must be set to 0, got params->fHeterodyne = %g\n", params->fHeterodyne ); UINT4 numSpins = 3; /* get timestamps of timeseries plus detector-states */ REAL8 dt = 1.0 / params->samplingRate; LIGOTimeGPSVector *timestamps; XLAL_CHECK_NULL ( (timestamps = XLALMakeTimestamps ( params->startTimeGPS, params->duration, dt, 0 )) != NULL, XLAL_EFUNC ); UINT4 numSteps = timestamps->length; DetectorStateSeries *detStates = XLALGetDetectorStates ( timestamps, params->site, params->ephemerides, 0 ); XLAL_CHECK_NULL ( detStates != NULL, XLAL_EFUNC, "XLALGetDetectorStates() failed.\n"); XLALDestroyTimestampVector ( timestamps ); timestamps = NULL; AMCoeffs *amcoe = XLALComputeAMCoeffs ( detStates, params->pulsar.position ); XLAL_CHECK_NULL ( amcoe != NULL, XLAL_EFUNC, "XLALComputeAMCoeffs() failed.\n"); /* create output timeseries (FIXME: should really know *detector* here, not just site!!) */ const LALFrDetector *site = &(params->site->frDetector); CHAR *channel = XLALGetChannelPrefix ( site->name ); XLAL_CHECK_NULL ( channel != NULL, XLAL_EFUNC, "XLALGetChannelPrefix( %s ) failed.\n", site->name ); REAL4TimeSeries *ts = XLALCreateREAL4TimeSeries ( channel, &(detStates->data[0].tGPS), 0, dt, &emptyUnit, numSteps ); XLAL_CHECK_NULL ( ts != NULL, XLAL_EFUNC, "XLALCreateREAL4TimeSeries() failed.\n"); XLALFree ( channel ); channel = NULL; /* orientation of detector arms */ REAL8 xAzi = site->xArmAzimuthRadians; REAL8 yAzi = site->yArmAzimuthRadians; REAL8 Zeta = xAzi - yAzi; if (Zeta < 0) { Zeta = -Zeta; } if ( params->site->type == LALDETECTORTYPE_CYLBAR ) { Zeta = LAL_PI_2; } REAL8 sinZeta = sin(Zeta); /* get source skyposition */ REAL8 Alpha = params->pulsar.position.longitude; REAL8 Delta = params->pulsar.position.latitude; REAL8 vn[3]; vn[0] = cos(Delta) * cos(Alpha); vn[1] = cos(Delta) * sin(Alpha); vn[2] = sin(Delta); /* get spin-parameters (restricted to maximally 3 spindowns right now) */ REAL8 phi0 = params->pulsar.phi0; REAL8 f0 = params->pulsar.f0; REAL8 f1dot = 0, f2dot = 0, f3dot = 0; if ( params->pulsar.spindown && (params->pulsar.spindown->length > numSpins) ) { XLAL_ERROR_NULL ( XLAL_EDOM, "Currently only supports up to %d spindowns!\n", numSpins ); } if ( params->pulsar.spindown && (params->pulsar.spindown->length >= 3 ) ) { f3dot = params->pulsar.spindown->data[2]; } if ( params->pulsar.spindown && (params->pulsar.spindown->length >= 2 ) ) { f2dot = params->pulsar.spindown->data[1]; } if ( params->pulsar.spindown && (params->pulsar.spindown->length >= 1 ) ) { f1dot = params->pulsar.spindown->data[0]; } /* internally we always work with refTime = startTime->SSB, therefore * we need to translate the pulsar spin-params and initial phase to the * startTime */ REAL8 startTimeSSB = XLALGPSGetREAL8 ( &(detStates->data[0].tGPS) ) + SCALAR ( vn, detStates->data[0].rDetector ); REAL8 refTime; if ( params->pulsar.refTime.gpsSeconds != 0 ) { REAL8 refTime0 = XLALGPSGetREAL8 ( &(params->pulsar.refTime) ); REAL8 deltaRef = startTimeSSB - refTime0; LIGOTimeGPS newEpoch; PulsarSpins fkdotNew; XLALGPSSetREAL8( &newEpoch, startTimeSSB ); PulsarSpins XLAL_INIT_DECL(fkdotOld); fkdotOld[0] = f0; fkdotOld[1] = f1dot; fkdotOld[2] = f2dot; fkdotOld[3] = f3dot; REAL8 DeltaTau = XLALGPSDiff ( &newEpoch, &(params->pulsar.refTime) ); int ret = XLALExtrapolatePulsarSpins ( fkdotNew, fkdotOld, DeltaTau ); XLAL_CHECK_NULL ( ret == XLAL_SUCCESS, XLAL_EFUNC, "XLALExtrapolatePulsarSpins() failed.\n"); /* Finally, need to propagate phase */ phi0 += LAL_TWOPI * ( f0 * deltaRef + (1.0/2.0) * f1dot * deltaRef * deltaRef + (1.0/6.0) * f2dot * deltaRef * deltaRef * deltaRef + (1.0/24.0)* f3dot * deltaRef * deltaRef * deltaRef * deltaRef ); f0 = fkdotNew[0]; f1dot = fkdotNew[1]; f2dot = fkdotNew[2]; f3dot = fkdotNew[3]; refTime = startTimeSSB; } /* if refTime given */ else { /* if not given: use startTime -> SSB */ refTime = startTimeSSB; } /* get 4 amplitudes A_\mu */ REAL8 aPlus = sinZeta * params->pulsar.aPlus; REAL8 aCross = sinZeta * params->pulsar.aCross; REAL8 twopsi = 2.0 * params->pulsar.psi; REAL8 A1 = aPlus * cos(phi0) * cos(twopsi) - aCross * sin(phi0) * sin(twopsi); REAL8 A2 = aPlus * cos(phi0) * sin(twopsi) + aCross * sin(phi0) * cos(twopsi); REAL8 A3 = -aPlus * sin(phi0) * cos(twopsi) - aCross * cos(phi0) * sin(twopsi); REAL8 A4 = -aPlus * sin(phi0) * sin(twopsi) + aCross * cos(phi0) * cos(twopsi); /* main loop: generate time-series */ for ( UINT4 i = 0; i < numSteps; i++) { LIGOTimeGPS *tiGPS = &(detStates->data[i].tGPS); REAL8 ti = XLALGPSGetREAL8 ( tiGPS ); REAL8 deltati = ti - refTime; REAL8 dT = SCALAR(vn, detStates->data[i].rDetector ); REAL8 taui = deltati + dT; REAL8 phi_i = LAL_TWOPI * ( f0 * taui + (1.0/2.0) * f1dot * taui*taui + (1.0/6.0) * f2dot * taui*taui*taui + (1.0/24.0)* f3dot * taui*taui*taui*taui ); REAL8 cosphi_i = cos(phi_i); REAL8 sinphi_i = sin(phi_i); REAL8 ai = amcoe->a->data[i]; REAL8 bi = amcoe->b->data[i]; REAL8 hi = A1 * ai * cosphi_i + A2 * bi * cosphi_i + A3 * ai * sinphi_i + A4 * bi * sinphi_i; ts->data->data[i] = (REAL4)hi; } /* for i < numSteps */ XLALDestroyDetectorStateSeries( detStates ); XLALDestroyAMCoeffs ( amcoe ); return ts; } /* XLALSimulateExactPulsarSignal() */
REAL4TimeSeries * XLALCutAtFreq( REAL4TimeSeries *h, REAL4Vector *freq, REAL8 cutFreq) { REAL8 dt; UINT4 k, k0, kMid, len; REAL4 currentFreq; UINT4 newLen; REAL4TimeSeries *newH = NULL; LIGOTimeGPS epoch; len = freq->length; dt = h->deltaT; /* Since the boundaries of this freq vector are likely to have */ /* FFT crap, let's scan the freq values starting from the middle */ kMid = len/2; currentFreq = freq->data[kMid]; k = kMid; /* freq is an increasing function of time */ /* If we are above the cutFreq we move to the left; else to the right */ if (currentFreq > cutFreq && k > 0) { while(currentFreq > cutFreq) { currentFreq = freq->data[k]; k--; } k0 = k; } else { while(currentFreq < cutFreq && k < len) { currentFreq = freq->data[k]; k++; } k0 = k; } newLen = len - k0; /* Allocate memory for the frequency series */ epoch.gpsSeconds = 0; epoch.gpsNanoSeconds = 0; newH = XLALCreateREAL4TimeSeries("", &epoch, 0, dt, &lalDimensionlessUnit, newLen); for(k = 0; k < newLen; k++) { newH->data->data[k] = h->data->data[k0 + k]; } return newH; }
/* Main Program */ INT4 main ( INT4 argc, CHAR *argv[] ) { static LALStatus status; INT4 c; UINT4 i; REAL8 dt, totTime; REAL8 sampleRate = -1; REAL8 totalMass = -1, massRatio = -1; REAL8 lowFreq = -1, df, fLow; CHAR *outFile = NULL, *outFileLong = NULL, tail[50]; size_t optarg_len; REAL8 eta; REAL8 newtonianChirpTime, PN1ChirpTime, mergTime; UINT4 numPts; LIGOTimeGPS epoch; REAL8 offset; PhenomCoeffs coeffs; PhenomParams params; REAL4FrequencySeries *Aeff = NULL, *Phieff = NULL; COMPLEX8Vector *uFPlus = NULL, *uFCross = NULL; COMPLEX8 num; REAL4Vector *hPlus = NULL, *hCross = NULL; REAL4TimeSeries *hP = NULL, *hC = NULL; /* REAL4TimeSeries *hP = NULL, *hC = NULL;*/ REAL4FFTPlan *prevPlus = NULL, *prevCross = NULL; /*REAL4Vector *Freq = NULL;*/ UINT4 windowLength; INT4 hPLength; REAL8 linearWindow; /* getopt arguments */ struct option long_options[] = { {"mass-ratio", required_argument, 0, 'q'}, {"low-freq (Hz)", required_argument, 0, 'f'}, {"total-mass (M_sun)", required_argument, 0, 'm'}, {"sample-rate", required_argument, 0, 's'}, {"output-file", required_argument, 0, 'o'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {0, 0, 0, 0} }; /* parse the arguments */ while ( 1 ) { /* getopt_long stores long option here */ int option_index = 0; /* parse command line arguments */ c = getopt_long_only( argc, argv, "q:t:d:hV", long_options, &option_index ); /* detect the end of the options */ if ( c == -1 ) { break; } switch ( c ) { case 0: fprintf( stderr, "Error parsing option '%s' with argument '%s'\n", long_options[option_index].name, optarg ); exit( 1 ); break; case 'h': /* help message */ print_usage( argv[0] ); exit( 0 ); break; case 'V': /* print version information and exit */ fprintf( stdout, "%s - Compute Ajith's Phenomenological Waveforms " \ "(arXiv:0710.2335) and output them to a plain text file\n" \ "CVS Version: %s\nCVS Tag: %s\n", PROGRAM_NAME, CVS_ID_STRING, \ CVS_NAME_STRING ); exit( 0 ); break; case 'q': /* set mass ratio */ massRatio = atof( optarg ); break; case 'f': /* set low freq */ lowFreq = atof( optarg ); break; case 'm': /* set total mass */ totalMass = atof( optarg ); break; case 's': /* set sample rate */ sampleRate = atof( optarg ); break; case 'o': /* set name of output file */ optarg_len = strlen(optarg) + 1; outFile = (CHAR *)calloc(optarg_len, sizeof(CHAR)); memcpy(outFile, optarg, optarg_len); break; case '?': print_usage( argv[0] ); exit( 1 ); break; default: fprintf( stderr, "ERROR: Unknown error while parsing options\n" ); print_usage( argv[0] ); exit( 1 ); } } if ( optind < argc ) { fprintf( stderr, "ERROR: Extraneous command line arguments:\n" ); while ( optind < argc ) { fprintf ( stderr, "%s\n", argv[optind++] ); } exit( 1 ); } /* * * * * * * * */ /* Main Program */ /* * * * * * * * */ eta = massRatio / pow(1. + massRatio, 2.); /* This freq low is the one used for the FFT */ /* fLow = 2.E-3/(totalMass*LAL_MTSUN_SI); */ fLow = lowFreq; /* Changed by Ajith. 5 May 2008 */ /* Phenomenological coefficients as in Ajith et. al */ GetPhenomCoeffsLongJena( &coeffs ); /* Compute phenomenologial parameters */ ComputeParamsFromCoeffs( ¶ms, &coeffs, eta, totalMass ); /* Check validity of arguments */ /* check we have freqs */ if ( totalMass < 0 ) { fprintf( stderr, "ERROR: --total-mass must be specified\n" ); exit( 1 ); } /* check we have mass ratio and delta t*/ if ( massRatio < 0 ) { fprintf( stderr, "ERROR: --mass-ratio must be specified\n" ); exit( 1 ); } if ( lowFreq < 0 ) { fprintf( stderr, "ERROR: --low-freq must be specified\n" ); exit( 1 ); } if ( sampleRate < 0 ) { fprintf( stderr, "ERROR: --sample-rate must be specified\n" ); exit( 1 ); } if ( lowFreq > params.fCut ) { fprintf( stderr, "\nERROR in --low-freq\n"\ "The value chosen for the low frequency is larger "\ "than the frequency at the merger.\n" "Frequency at the merger: %4.2f Hz\nPick either a lower value"\ " for --low-freq or a lower total mass\n\n", params.fCut); exit(1); } if ( lowFreq < fLow ) { fprintf( stderr, "\nERROR in --low-freq\n"\ "The value chosen for the low frequency is lower "\ "than the lowest frequency computed\nby the implemented FFT.\n" "Lowest frequency allowed: %4.2f Hz\nPick either a higher value"\ " for --low-freq or a higher total mass\n\n", fLow); exit(1); } if ( outFile == NULL ) { fprintf( stderr, "ERROR: --output-file must be specified\n" ); exit( 1 ); } /* Complete file name with details of the input variables */ sprintf(tail, "%s-Phenom_M%3.1f_R%2.1f.dat", outFile, totalMass, massRatio); optarg_len = strlen(tail) + strlen(outFile) + 1; outFileLong = (CHAR *)calloc(optarg_len, sizeof(CHAR)); strcpy(outFileLong, tail); /* check sample rate is enough */ if (sampleRate > 4.*params.fCut) /* Changed by Ajith. 5 May 2008 */ { dt = 1./sampleRate; } else { sampleRate = 4.*params.fCut; dt = 1./sampleRate; } /* Estimation of the time duration of the binary */ /* See Sathya (1994) for the Newtonian and PN1 chirp times */ /* The merger time is overestimated */ newtonianChirpTime = (5./(256.*eta))*pow(totalMass*LAL_MTSUN_SI,-5./3.)*pow(LAL_PI*fLow,-8./3.); PN1ChirpTime = 5.*(743.+924.*eta)/(64512.*eta*totalMass*LAL_MTSUN_SI*pow(LAL_PI*fLow,2.)); mergTime = 2000.*totalMass*LAL_MTSUN_SI; totTime = 1.2 * (newtonianChirpTime + PN1ChirpTime + mergTime); numPts = (UINT4) ceil(totTime/dt); df = 1/(numPts * dt); /* Compute Amplitude and Phase from the paper (Eq. 4.19) */ Aeff = XLALHybridP1Amplitude(¶ms, fLow, df, eta, totalMass, numPts/2+1); Phieff = XLALHybridP1Phase(¶ms, fLow, df, eta, totalMass, numPts/2 +1); /* Construct u(f) = Aeff*e^(i*Phieff) */ XLALComputeComplexVector(&uFPlus, &uFCross, Aeff, Phieff); /* Scale this to units of M */ for (i = 0; i < numPts/2 + 1; i++) { num = uFPlus->data[i]; num.re *= 1./(dt*totalMass*LAL_MTSUN_SI); num.im *= 1./(dt*totalMass*LAL_MTSUN_SI); uFPlus->data[i] = num; num = uFCross->data[i]; num.re *= 1./(dt*totalMass*LAL_MTSUN_SI); num.im *= 1./(dt*totalMass*LAL_MTSUN_SI); uFCross->data[i] = num; } /* Inverse Fourier transform */ LALCreateReverseREAL4FFTPlan( &status, &prevPlus, numPts, 0 ); LALCreateReverseREAL4FFTPlan( &status, &prevCross, numPts, 0 ); hPlus = XLALCreateREAL4Vector(numPts); hCross = XLALCreateREAL4Vector(numPts); LALReverseREAL4FFT( &status, hPlus, uFPlus, prevPlus ); LALReverseREAL4FFT( &status, hCross, uFCross, prevCross ); /* The LAL implementation of the FFT omits the factor 1/n */ for (i = 0; i < numPts; i++) { hPlus->data[i] /= numPts; hCross->data[i] /= numPts; } /* Create TimeSeries to store more info about the waveforms */ /* Note: it could be done easier using LALFreqTimeFFT instead of ReverseFFT */ epoch.gpsSeconds = 0; epoch.gpsNanoSeconds = 0; hP = XLALCreateREAL4TimeSeries("", &epoch, 0, dt, &lalDimensionlessUnit, numPts); hP->data = hPlus; hC = XLALCreateREAL4TimeSeries("", &epoch, 0, dt, &lalDimensionlessUnit, numPts); hC->data = hCross; /* Cutting off the part of the waveform with f < fLow */ /* Freq = XLALComputeFreq( hP, hC); hP = XLALCutAtFreq( hP, Freq, lowFreq); hC = XLALCutAtFreq( hC, Freq, lowFreq); */ /* multiply the last few samples of the time-series by a linearly * dropping window function in order to avid edges in the data * Added by Ajith 6 May 2008 */ hPLength = hP->data->length; windowLength = (UINT4) (20.*totalMass * LAL_MTSUN_SI/dt); for (i=1; i<= windowLength; i++){ linearWindow = (i-1.)/windowLength; hP->data->data[hPLength-i] *= linearWindow; hC->data->data[hPLength-i] *= linearWindow; } /* Convert t column to units of (1/M) */ /* offset *= (1./(totalMass * LAL_MTSUN_SI)); hP->deltaT *= (1./(totalMass * LAL_MTSUN_SI)); */ /* Set t = 0 at the merger (defined as the max of the NR wave) */ XLALFindNRCoalescenceTimeFromhoft( &offset, hP); XLALGPSAdd( &(hP->epoch), -offset); XLALGPSAdd( &(hC->epoch), -offset); /* Print waveforms to file */ LALPrintHPlusCross( hP, hC, outFileLong ); /* Free Memory */ XLALDestroyREAL4FrequencySeries(Aeff); XLALDestroyREAL4FrequencySeries(Phieff); XLALDestroyREAL4FFTPlan(prevPlus); XLALDestroyREAL4FFTPlan(prevCross); XLALDestroyCOMPLEX8Vector(uFPlus); XLALDestroyCOMPLEX8Vector(uFCross); XLALDestroyREAL4TimeSeries(hP); XLALDestroyREAL4TimeSeries(hC); /* XLALDestroyREAL4TimeSeries(hP); */ /* XLALDestroyREAL4TimeSeries(hC); */ return(0); }