/* program entry point */ INT4 main(INT4 argc, CHAR *argv[]) { /* lal initialisation variables */ LALStatus status = blank_status; /* xml */ CHAR baseName[FILENAME_MAX]; StochasticTable *stochHead = NULL; StochasticTable *thisStoch = NULL; /* counter */ INT4 i; /* data structures */ REAL4TimeSeries *seriesOne; REAL4TimeSeries *seriesTwo; REAL4FrequencySeries *overlap; REAL4FrequencySeries *mask; REAL4FrequencySeries *omegaGW; REAL4Window *dataWindow; LIGOTimeGPS gpsStartTime; LIGOTimeGPS gpsEndTime; /* variables */ INT4 numSegments; INT4 duration, durationEff, extrasec; INT4 segsInInt; INT4 segmentLength; INT4 padData; REAL8 deltaF; INT4 filterLength; INT4 numFMin; INT4 numFMax; /* error handler */ status.statusPtr = NULL; lal_errhandler = LAL_ERR_EXIT; /* create the process and process params tables */ proctable.processTable = (ProcessTable *) calloc(1, sizeof(ProcessTable)); XLALGPSTimeNow(&proctable.processTable->start_time); XLALPopulateProcessTable(proctable.processTable, prog_name, \ lalAppsVCSIdentInfo.vcsId, lalAppsVCSIdentInfo.vcsStatus, lalAppsVCSIdentInfo.vcsDate, 0); this_proc_param = procparams.processParamsTable = (ProcessParamsTable *) \ calloc(1, sizeof(ProcessParamsTable)); memset(comment, 0, LIGOMETA_COMMENT_MAX * sizeof(CHAR)); /* parse command line options */ parse_options(argc, argv); /* get xml file basename */ if (userTag) { snprintf(baseName, FILENAME_MAX, "%s%s-STOCHASTIC_%s_%d-%d", \ ifoOne, ifoTwo, userTag, startTime, (endTime - startTime)); } else { snprintf(baseName, FILENAME_MAX, "%s%s-STOCHASTIC-%d-%d", \ ifoOne, ifoTwo, startTime, (endTime - startTime)); } /* get number of segments */ duration = endTime - startTime; numSegments = duration / segmentDuration; segsInInt = intervalDuration / segmentDuration; /* recentre */ if (recentre_flag) { if (vrbflg) fprintf(stdout, "Recentring within data stream...\n"); durationEff = numSegments * segmentDuration; extrasec = duration - durationEff; startTime += extrasec / 2; endTime = startTime + durationEff; } /* add a resample buffer, if required */ if ((resampleRate) || (high_pass_flag)) padData = 1; else padData = 0; /* initialise gps time structures */ gpsStartTime.gpsSeconds = startTime; gpsStartTime.gpsNanoSeconds = 0; gpsEndTime.gpsSeconds = endTime; gpsEndTime.gpsNanoSeconds = 0; /* read data */ seriesOne = get_time_series(ifoOne, frameCacheOne, channelOne, \ gpsStartTime, gpsEndTime, resampleRate, highPassOrder, highPassFreq, \ highPassAtten, geoHighPassOrder, geoHighPassFreq, geoHighPassAtten, \ padData); seriesTwo = get_time_series(ifoTwo, frameCacheTwo, channelTwo, \ gpsStartTime, gpsEndTime, resampleRate, highPassOrder, highPassFreq, \ highPassAtten, geoHighPassOrder, geoHighPassFreq, geoHighPassAtten, \ padData); /* check that the two series have the same sample rate */ if (seriesOne->deltaT != seriesTwo->deltaT) { fprintf(stderr, "Series have different sample rates...\n"); exit(1); } else { /* get resample rate, if required */ if (!resampleRate) resampleRate = (INT4)(1./seriesOne->deltaT); } /* get deltaF for optimal filter */ deltaF = 1./(REAL8)PSD_WINDOW_DURATION; /* get bins for min and max frequencies */ numFMin = (INT4)(fMin / deltaF); numFMax = (INT4)(fMax / deltaF); /* get lengths */ filterLength = numFMax - numFMin + 1; segmentLength = segmentDuration * resampleRate; if (vrbflg) fprintf(stdout, "Generating data segment window...\n"); /* for overlapping hann windows, the hann window length is the segment * length */ if (overlap_hann_flag) hannDuration = segmentDuration; /* create window for data */ dataWindow = data_window(seriesOne->deltaT, segmentLength, hannDuration); /* generate overlap reduction function */ if (vrbflg) fprintf(stdout, "Generating the overlap reduction function...\n"); overlap = overlap_reduction_function(&status, filterLength, fMin, deltaF, \ siteOne, siteTwo); /* generate omegaGW */ if (vrbflg) fprintf(stdout, "Generating spectrum for optimal filter...\n"); omegaGW = omega_gw(&status, alpha, fRef, omegaRef, filterLength, \ fMin, deltaF); /* frequency mask */ if (apply_mask_flag) { if (vrbflg) fprintf(stdout, "Applying frequency mask to spectrum..\n"); /* generate frequency mask */ mask = frequency_mask(fMin, deltaF, filterLength, maskBin); /* apply mask to omegaGW */ for (i = 0; i < filterLength; i++) omegaGW->data->data[i] *= mask->data->data[i]; /* destroy frequency mask */ XLALDestroyREAL4FrequencySeries(mask); } /* perform search */ stochHead = stochastic_search(&status, seriesOne, seriesTwo, overlap, \ omegaGW, dataWindow, numSegments, filterLength, segmentDuration, \ segsInInt, segmentLength, PSD_WINDOW_DURATION, ifoOne, ifoTwo, \ channelOne, channelTwo, calCacheOne, calCacheTwo, calibOffset, \ fMin, fMax, fRef); /* save out xml table */ save_xml_file(&status, prog_name, outputPath, baseName, \ stochHead, proctable, procparams, this_proc_param, comment); /* cleanup */ XLALDestroyREAL4FrequencySeries(overlap); XLALDestroyREAL4FrequencySeries(omegaGW); XLALDestroyREAL4Window(dataWindow); XLALDestroyREAL4TimeSeries(seriesOne); XLALDestroyREAL4TimeSeries(seriesTwo); /* free memory used in the stochastic xml table */ while(stochHead) { thisStoch = stochHead; stochHead = stochHead->next; LALFree(thisStoch); } /* free calloc'd memory */ if (strcmp(frameCacheOne, frameCacheTwo)) { free(frameCacheOne); free(frameCacheTwo); } else { free(frameCacheOne); } free(calCacheOne); free(calCacheTwo); free(channelOne); free(channelTwo); free(ifoOne); free(ifoTwo); free(userTag); free(outputPath); /* check for memory leaks and exit */ LALCheckMemoryLeaks(); exit(0); }
/* 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); }