LALDemodTest.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton, Maria Alessandra Papa, Reinhard Prix, Steve Berukoff, Teviet Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /* <lalVerbatim file="LALDemodTestCV">
00021 Author: Berukoff, S.J., Papa, M.A., $Id: LALDemodTest.c,v 1.27 2007/06/08 14:41:52 bema Exp $
00022  </lalVerbatim> */
00023 
00024 #if 0
00025  <lalLaTeX>
00026    
00027    \subsection{Program \texttt{LALDemodTest.c}}
00028    \label{ss:LALDemodTest.c}
00029    
00030    Performs required tests of \verb@LALDemod()@.
00031    
00032    \subsubsection*{Usage}
00033    \begin{verbatim}
00034    LALDemodTest -i <input data file> [-d <gap>] [-n] [-o]
00035    \end{verbatim}
00036    
00037    \subsubsection*{Description}
00038    
00039    \noindent This routine performs tests on the routine \verb@LALDemod()@.  
00040    Options: 
00041    \begin{itemize}
00042    \item \verb@-i@ -- the input data file (default is 'in.data'; an example is included, format below)
00043    \item \verb@-n@ -- add zero-mean Gaussian noise to the signal
00044    \item \verb@-d <gap>@ -- simulate gaps in the data.  The number \verb@<gaps>@ refers to the integral number of SFT timescales between adjacent timestamps.
00045    \item \verb@-o@ -- print out result data files
00046    \end{itemize}
00047    
00048    Structure:
00049    In more detail, let us begin with a discussion of the structure of the test
00050    code, which is composed of several modules.  
00051    \begin{itemize}
00052    \item The first module reads in data from an input parameter data file.  
00053    The parameters must be listed in the input file in the following order, 
00054    with the corresponding format:
00055    \begin{verbatim}
00056    total observation time -- float
00057    coherent search time -- float
00058    factor by which to modify SFT timescale -- float
00059    Cross amplitude -- float
00060    Plus amplitude -- float
00061    DeFT frequency band (centered by default around f0) -- float
00062    f0, intrinsic frequency of the signal at the beginning of the 
00063    observation -- float
00064    maximum order of signal spindown parameters -- int
00065    signal spindown parameter 1 --  scientific notation
00066    signal spindown parameter 2 --  scientific notation
00067    signal spindown parameter 3 --  scientific notation
00068    signal spindown parameter 4 --  scientific notation
00069    signal spindown parameter 5 --  scientific notation
00070    signal source right ascension (alpha) -- float (value in DEGREES)
00071    signal source declination (delta) -- float (value in DEGREES)
00072    maximum order of template spindown parameters -- int
00073    template spindown parameter 1 --  scientific notation (NOT 
00074    template spindown parameter 2 --  scientific notation (NOT scaled by f0)
00075    template spindown parameter 3 --  scientific notation (NOT scaled by f0)
00076    template spindown parameter 4 --  scientific notation (NOT scaled by f0)
00077    template spindown parameter 5 --  scientific notation (NOT scaled by f0)
00078    template source right ascension (alpha) -- float (value in DEGREES)
00079    template source declination (delta) -- float (value in DEGREES)
00080    \end{verbatim}
00081    Note: Above, the *signal* spindown parameters are scaled by the intrinsic frequency, while the *template* spindown parameters are not.  This is due to the difference in definitions between the SimulateCoherentGW() package, which generates the signal, and this package.
00082    
00083    \item The next module in the test code, which is optionally executed with 
00084    the '\verb@-n@' switch, creates noise using LALs
00085    \verb@LALNormalDeviates()@ routine.  By design, the noise is created in 
00086    single
00087    precision, and is zero-mean and Gaussian.  This noise is added, 
00088    datum-by-datum, to the time series created in
00089    the next module, after the amplitude of the time series has been 
00090    changed by a
00091    factor of \verb@SNR@, which is specified in the input data file.
00092    
00093    \item The next module to be invoked creates a time series, according to 
00094    the standard model for pulsars with spindown.  This is done by using the \verb@LALGenerateTaylorCW()@ and \verb@LALSimulateCoherentGW()@ functions.  This time series undergoes 
00095    an FFT, and this transformed data then constitutes the SFT data to be 
00096    input to the demodulation code.  The fake signal data is characterized 
00097    by an intrinsic frequency at the beginning of the observation plus some 
00098    other source parameters.  The DeFT is produced in a band \verb@f0Band@ 
00099    (as specified as an input parameter) and centered at this frequency.   
00100    The width of the band (plus some extra width of $2\cdot 10^{-4}f0 $ Hz) determines the
00101    sampling frequency of the time series (Nyquist theorem).  In practice this
00102    would be the inverse FFT of a data set that has been band-passed around
00103    \verb@f0@ and then appropriately down-sampled (e.g. with a lock-in).  The
00104    normalization rule for FFT data is the following: if sinusoidal data over a
00105    time $T$ and with amplitude $A$ is FFT-ed, the sum of the square amplitude of
00106    the output of the FFT (power) is equal to ${A^2 T}$.  Thus, the power peak at
00107    the sinusoids frequency should be expected to be $\sim$ $\frac{A^2}{2} T$,
00108    within a factor of 2.  The same normalization rule applies to the DeFT data.
00109    Thus by piecing together $N$ SFTs we expect a DeFT power peak $\sim N$ higher
00110    than that of the SFTs - at least in the case of perfect signal-template match.
00111    
00112    
00113    Let us now spend a few words on the choice of the SFT time baseline.  Given an
00114    intrinsic search frequency one can compute the longest time baseline which is
00115    still compatible with the requirement that the instantaneous signal frequency
00116    during such time baseline does not shift by more than a frequency bin.  This
00117    is the default choice for the SFT length, having assumed that the modulation
00118    is due to the spin of the Earth and having taken a simple epicyclic model to
00119    evaluate the magnitude of this effect.  It is possible to choose a different 
00120    time baseline by specifying a value for
00121    the variable \verb@gap@ other than 1.  Note that the SFT time baseline is
00122    approximated to the nearest value such that the number of SFT samples is a
00123    power of two.  This is also well documented in the code.  
00124    
00125    
00126    The set of SFTs does not necessarily come from contiguous data sets: a set of
00127    time stamps is created that defines the time of the first sample of each SFT
00128    data chunk.  The timestamps which are required in many parts of the code are
00129    generated in a small subroutine \verb@times2()@.  This routine takes as input
00130    the SFT timescale \verb@tSFT@, the number of SFTs which will be created,
00131    \verb@mObsSFT@, and a switch which lets the code know whether to make even
00132    timestamps, or timestamps with gaps (see below for more on this).  The
00133    subroutine then writes the times to the \verb@LIGOTimeGPS@ vector containing
00134    the timestamps for the entire test code, and returns this vector.  Note that
00135    each datum of the  \verb@LIGOTimeGPS@ vector is comprised of two fields; if
00136    accessing the $i^{th}$ datum, the seconds part of the timestamp vector
00137    \verb@ts@ is \verb@ts[i].gpsSeconds@ and the nanoseconds part is
00138    \verb@ts[i].gpsNanoSeconds@.  These are the fields which are written in this
00139    \verb@times()@.
00140    
00141    
00142    As an important side note, let us discuss the effect that a vector of
00143    timestamps with gaps has on the resulting transformed data.  Since each of the
00144    timestamps refers to the first datum of each SFT, the existence of the gaps
00145    means that instead of transforming a continuous set of data, we are reduced to
00146    transforming a piecewise continuous set.  Since we can envision these gaps as
00147    simply replacing real data with zeros, we correspondingly should see a power
00148    loss in the resulting FFTs signal bins and a broadening of the power spectrum.
00149    Since real detectors will clearly have gaps in the data, this effect is
00150    obviously something we seek to minimize or eliminate if possible.  This work
00151    continues to be under development.
00152    
00153    
00154    The total observation time determines how many SFTs and how many DeFTs are
00155    created.  The actual time baseline for both the DeFTs and the total
00156    observation time might differ from the ones defined in the input file, the
00157    reason being that they are rounded to the nearest multiple of the SFT time
00158    baseline.
00159    
00160    Note that use is made of the \verb@LALBarycenter()@ routine (see section 
00161    \ref{s:LALBarycenter.h}), which (among other things) provides,  at any given 
00162    time, the actual instantaneous position and velocity of a  detector at any 
00163    specified location of the Earth with respect to the SSB.  
00164    
00165    \item Following the creation of a short chunk of time series data, an FFT is
00166    performed with the internal FFTW routines.  This outputs a frequency domain
00167    chunk which is placed into the \verb@SFTData@ array of structures.  This will
00168    contain all of the SFT data we need to demodulate, and in the future, will be
00169    the storage area for the real data.
00170    
00171    \item The next module begins the demodulation process.  First, the parameters
00172    for the demodulation routine are assigned from values previously calculated in
00173    the test code.  Similarly, parameters for the \verb@LALComputeSky()@ routine are
00174    assigned.  This routine computes the coefficients $A_{s\alpha}$ and
00175    $B_{s\alpha}$ (see section \ref{s:ComputeSky.h}) of the spindown parameters
00176    for the phase model weve assumed.  These coefficients are used within the
00177    \verb@LALDemod()@ routine itself. Since they only depend on the template sky
00178    position, in a search over many different spin-down parameters they are
00179    reused, thus one needs compute them only once.  Then, the \verb@LALComputeAM()@ 
00180    routine is called, to calculate the amplitude modulation filter information.  Finally, at last, the
00181    demodulation routine itself is called, and, if the command line option
00182    '\verb@-o@' is used,  output are several data files containing demodulated
00183    data (these are by default named '\verb@xhat_#@').  These output files have two columns, one for the value of the periodogram and one for the frequency.
00184    
00185    \end{itemize}
00186    
00187    
00188    \subsubsection*{Exit codes}
00189    
00190    \subsubsection*{Uses}
00191    \begin{verbatim}
00192    lalDebugLevel
00193    LALMalloc()
00194    LALFopen()
00195    LALFclose()
00196    LALSCreateVector()
00197    LALCreateRandomParams()
00198    LALNormalDeviates()
00199    LALDestroyRandomParams()
00200    LALSDestroyVector()
00201    LALCCreateVector()
00202    LALCreateForwardRealFFTPlan()
00203    LALREAL4VectorFFT()
00204    LALCDestroyVector()
00205    LALDestroyRealFFTPlan()
00206    LALGenerateTaylorCW()
00207    LALSimulateCoherentGW()
00208    LALComputeSky()
00209    LALFree()
00210    LALDemod()
00211    LALBarycenter()
00212    LALComputeAM()
00213    \end{verbatim}
00214    
00215    \subsubsection*{Notes}
00216    The implementation of the code here is intended to give a general outline of 
00217    what the demodulation code needs to work.  Most of this test function performs 
00218    steps (e.g., noise, time- and frequency-series generation) that will be already 
00219    present in the data.  
00220    
00221    \vfill{\footnotesize\input{LALDemodTestCV}}
00222    
00223    </lalLaTeX>
00224 #endif /* autodoc block */
00225  
00226 #ifndef LALDEMODTEST_C
00227 #define LALDEMODTEST_C
00228 #endif
00229 
00230 /* Usage */
00231 #define USAGE "Usage: %s [-i basicInputsFile] [-n] [-d] [-o]\n"
00232 
00233 
00234 /* Error macro, taken from ResampleTest.c in LAL's pulsar/test package */
00235 #define ERROR( code, msg, statement )                                \
00236 if ( lalDebugLevel & LALERROR )                                      \
00237 {                                                                    \
00238   LALPrintError( "Error[0] %d: program %s, file %s, line %d, %s\n"   \
00239                  "        %s %s\n", (code), *argv, __FILE__,            \
00240                  __LINE__, LALDEMODTESTC, statement ? statement : "",\
00241                  (msg) );                                            \
00242 }                                                                    \
00243 else (void)(0)
00244 
00245 #include <lal/LALDemod.h>
00246 #include <lal/LALInitBarycenter.h>
00247 #include <lal/SeqFactories.h>
00248 #include <lal/FileIO.h>
00249 #include <unistd.h>
00250 #include <sys/types.h>
00251 
00252 
00253 static void TimeToFloat(REAL8 *f, LIGOTimeGPS *tgps);
00254 
00255 static void FloatToTime(LIGOTimeGPS *tgps, REAL8 *f);
00256 
00257 static void times(REAL8 , INT4, LIGOTimeGPS *, INT4 );
00258 
00259 static void times2(REAL8 tSFT, INT4 howMany, LIGOTimeGPS **ts, INT4 **sftPerCoh, INT4 sw, INT4 mCohSFT);
00260 
00261 NRCSID(LALDEMODTESTC, "$Id: LALDemodTest.c,v 1.27 2007/06/08 14:41:52 bema Exp $");
00262 
00263 int lalDebugLevel = 3;
00264 
00265 int main(int argc, char **argv)
00266 {
00267   static LALStatus status;
00268         
00269   /***** VARIABLE DECLARATION *****/
00270 
00271   ParameterSet *signalParams;
00272   ParameterSet *templateParams;
00273   char *basicInputsFile;
00274   FILE *bif;
00275   REAL8 tObs, tCoh, tSFT;
00276   REAL8 oneOverSqrtTSFT;
00277   REAL8 aCross, aPlus, SNR;
00278   REAL8 f0;
00279         
00280   INT4 mCohSFT, mObsCoh, mObsSFT;
00281   REAL8 dfSFT, dt;
00282   INT4 if0Min, if0Max, ifMin, ifMax;
00283   REAL8 f0Min, f0Max, fMin, f0Band, fWing;
00284   INT4 nDeltaF,ntermsdivbytwo;
00285   LALFstat Fstat;
00286 
00287   LIGOTimeGPS *timeStamps;
00288 
00289   REAL4Vector *temp = NULL;
00290   REAL4Vector *noise = NULL;
00291   static RandomParams *params;
00292   INT4 seed=0;
00293         
00294   INT4 a,i,k;
00295         
00296   FFT **SFTData;
00297   RealFFTPlan *pfwd = NULL;
00298   COMPLEX8Vector *fvec = NULL;
00299         
00300   DemodPar *demParams;
00301   CSParams *csParams;
00302   INT4 iSkyCoh;
00303         
00304   DeFTPeriodogram **xHat;
00305         
00306   const CHAR *noi=NULL;
00307   INT4 deletions=0;
00308   const CHAR *output=NULL;
00309         
00310   REAL8 factor;
00311   INT2 arg;
00312 
00313   /* file name if needed for SFT output files */
00314   CHAR *sftoutname=NULL;
00315 
00316   /* Quantities for use in LALBarycenter package */
00317   BarycenterInput baryinput;
00318   EmissionTime emit;
00319   EarthState earth;
00320   LALDetector cachedDetector;
00321           
00322   EphemerisData *edat=NULL;
00323   char earthEphemeris[]="earth98.dat";
00324   char sunEphemeris[]="sun98.dat";
00325 
00326   REAL4TimeSeries *timeSeries = NULL;
00327 
00328   /*
00329    *  Variables for AM correction
00330    */
00331   CoherentGW cgwOutput;
00332   TaylorCWParamStruc genTayParams;
00333   DetectorResponse cwDetector;
00334   AMCoeffsParams *amParams;
00335   AMCoeffs amc;
00336   INT4 *sftPerCoh;
00337   INT4 totalSFT=0;
00338   
00339 #define DEBUG 1
00340 #if (0)
00341      
00342   INT2 tmp=0;           
00343   REAL8 dtSFT, dfCoh;   
00344   REAL8 fMax;           
00345   INT4 nSFT;            
00346 
00347 #endif
00348         
00349   /***** END VARIABLE DECLARATION *****/
00350   
00351    
00352   /***** PARSE COMMAND LINE OPTIONS *****/      
00353   basicInputsFile=(char *)LALMalloc(50*sizeof(char));
00354   LALSnprintf(basicInputsFile, 9, "in.data\0");
00355   arg=1;
00356   while(arg<argc) {
00357                 
00358     /* the input file */
00359     if(!strcmp(argv[arg],"-i"))
00360       {
00361         strcpy(basicInputsFile, argv[++arg]);
00362         arg++;
00363         if(LALOpenDataFile(basicInputsFile)==NULL)
00364           {
00365             ERROR(LALDEMODH_ENOFILE, LALDEMODH_MSGENOFILE, 0);
00366             LALPrintError(USAGE, *argv);
00367             return LALDEMODH_ENOFILE;
00368           }
00369       }
00370                 
00371     /* turn noise on? if string is not NULL, it will be */
00372     else if(!strcmp(argv[arg],"-n"))
00373       {
00374         noi="n";
00375         arg++;
00376       }
00377 
00378     /* make SFT file output (such that the driver code can read in as input data) */
00379     else if (!strcmp(argv[arg],"-m")) 
00380       {
00381       sftoutname=argv[++arg];
00382       arg++;
00383       } 
00384     /* turn timestamp deletions on? if string is not NULL, it will be */
00385     else if(!strcmp(argv[arg],"-d"))
00386       {
00387         deletions=1;
00388         arg++;
00389       }
00390     
00391     /* turn on output? if string is not NULL, it will be */
00392     else if(!strcmp(argv[arg],"-o"))
00393       {
00394         output="o";
00395         arg++;
00396       }
00397                 
00398     /* default: no input file specified */
00399     else if(basicInputsFile==NULL)
00400       {
00401         bif=LALOpenDataFile("in.data");
00402       }
00403                 
00404     /* erroneous command line argument */
00405     else if(basicInputsFile!=NULL && arg<argc)
00406       {
00407         ERROR(LALDEMODH_EBADARG, LALDEMODH_MSGEBADARG, 0);              
00408         LALPrintError(USAGE, *argv);
00409         arg=argc;
00410         return LALDEMODH_EBADARG;
00411       }
00412   }
00413         
00414   /***** END COMMAND LINE PARSING *****/
00415 
00416         
00417   /***** INITIALIZATION OF SIGNAL AND TEMPLATE *****/
00418 
00419   /* Allocate space for signal parameters */
00420   signalParams=LALMalloc(sizeof(ParameterSet));
00421   signalParams->spind=LALMalloc(sizeof(Spindown));
00422   signalParams->skyP=LALMalloc(2*sizeof(SkyPos));
00423   signalParams->spind->spParams=LALMalloc(5*sizeof(REAL8));
00424 
00425   /* Allocate space for template parameters */
00426   templateParams=LALMalloc(sizeof(ParameterSet));
00427   templateParams->spind=LALMalloc(sizeof(Spindown));
00428   templateParams->skyP=LALMalloc(2*sizeof(SkyPos));
00429   templateParams->spind->spParams=LALMalloc(5*sizeof(REAL8));
00430 
00431   /***** END INITIALIZATION *****/
00432         
00433         
00434   /***** GET INPUTS FROM FILES *****/
00435 
00436   bif=LALOpenDataFile(basicInputsFile);
00437         
00438   fscanf(bif, "%lf\n%lf\n%lf\n%lf\n%lf\n%lf\n%lf\n%lf\n%d\n%le\n%le\n%le\n%le\n%le\n%lf\n"
00439          " %lf\n%d\n%le\n%le\n%le\n%le\n%le\n%lf\n%lf\n",
00440          &tObs, &tCoh, &factor, &aCross, &aPlus, &SNR, &f0Band, &f0,
00441          &signalParams->spind->m, 
00442          &signalParams->spind->spParams[0], &signalParams->spind->spParams[1],  
00443          &signalParams->spind->spParams[2], &signalParams->spind->spParams[3],
00444          &signalParams->spind->spParams[4], 
00445          &signalParams->skyP->alpha, &signalParams->skyP->delta, 
00446          &templateParams->spind->m,
00447          &templateParams->spind->spParams[0], &templateParams->spind->spParams[1],
00448          &templateParams->spind->spParams[2], &templateParams->spind->spParams[3],
00449          &templateParams->spind->spParams[4], 
00450          &templateParams->skyP->alpha, &templateParams->skyP->delta);
00451         
00452   LALFclose(bif);
00453 
00454   /***** END FILE INPUT *****/
00455         
00456 
00457   /***** CALCULATE USEFUL QUANTITIES *****/
00458 
00459   /*    2^n gives the number of samples of the SFT. This will be a signal in a  */      
00460   /*    band fSample/2 with fSample=2*(2.e-4 f0+f0Band). This makes sure that   */ 
00461   /*    that the sampling frequency enables us to produce the DeFT frequency    */ 
00462   /*    band that we want (f0Band) and that there's enought wings of SFT data   */ 
00463   /*    (4.e-4*f0) to produce such DeFT band.                                   */
00464   /*    The main formula used here is that the gives the maximum allowed        */ 
00465   /*    time-baseline (Tmax) such that a signal of frequency f0 Doppler         */ 
00466   /*    modulated due to Earth spin is seen as monochromatic during such        */ 
00467   /*    observation time:                                                       */
00468   /*            Tmax < 9.6e4/sqrt(f0).                                          */
00469   /*    We have thus taken Tmax=9.4e4/sqrt(f0). A different criterion can be    */ 
00470   /*    chosen by setting the variable "factor" to a suitable value. We have    */ 
00471   /*    rounded the resulting number of samples to the nearest smallest power   */ 
00472   /*    of two.                                                                 */
00473 
00474   {
00475     REAL8 tempf0Band;
00476 
00477     ntermsdivbytwo=64;
00478     /* compute size of SFT wings */
00479     fWing = 2.0e-4 * f0;
00480     /* Adjust search band to include wings */
00481     f0Band += 2.0*fWing;
00482     tempf0Band = f0Band;
00483     tSFT=1.0e3;/*9.6e4/sqrt(f0);*/
00484     nDeltaF = 2*ntermsdivbytwo+(INT4)(ceil(f0Band*tSFT));
00485       /* tSFT = (REAL8)nDeltaF/f0Band;*/
00486     oneOverSqrtTSFT = 1.0/sqrt(tSFT);
00487     /* Number of data in time series for 1 SFT */
00488     dfSFT=1.0/tSFT;
00489     /* Get rid of the wings */
00490     f0Band -= 2.0*fWing;
00491     /* the index of the right side of the band, NO WINGS */
00492     if0Max=ceil((f0+f0Band/2.0)/dfSFT);
00493     /* the index of the left side of the band, NO WINGS */
00494     if0Min=floor((f0-f0Band/2.0)/dfSFT);
00495     /* frequency of the right side of the band, NO WINGS */
00496     f0Max=dfSFT*if0Max;
00497     /* frequency of the left side of the band, NO WINGS */
00498     f0Min=dfSFT*if0Min;   
00499     
00500     f0Band = tempf0Band;
00501   }
00502   /* the hard-wired 64 is for the necessary NTERMS_COH_DIV_TWO*/
00503   /* index of the left side of the band, WITH WINGS */
00504 
00505   ifMin=floor(f0/dfSFT)-nDeltaF/2;
00506   /* indexof the right side of the band, WITH WINGS */
00507   ifMax=ifMin+nDeltaF;
00508   /* frequency of the left side of the band, WITH WINGS */
00509   fMin=dfSFT*ifMin;  
00510   nDeltaF=2*ntermsdivbytwo+(INT4)(ceil(f0Band/dfSFT));
00511   /* Number of SFTs which make one DeFT */ 
00512   mCohSFT=ceil(tCoh/tSFT);
00513   if (mCohSFT==0) mCohSFT=1;
00514   /* Coherent search time baseline */
00515   tCoh=tSFT*mCohSFT;
00516   /* Number of coherent timescales in total obs. time */
00517   mObsCoh=floor(tObs/tCoh);
00518   if (mObsCoh ==0) mObsCoh=1;
00519   /* Total observation time */
00520   tObs=tCoh*mObsCoh;
00521   /* Number of SFTs needed during observation time */
00522   mObsSFT=mCohSFT*mObsCoh;      
00523 
00524   printf("%d %d %d\n",mObsSFT,mObsCoh,mCohSFT);
00525 
00526   /* convert input angles from degrees to radians */
00527   signalParams->skyP->alpha=signalParams->skyP->alpha*LAL_TWOPI/360.0;
00528   signalParams->skyP->delta=signalParams->skyP->delta*LAL_TWOPI/360.0;
00529   templateParams->skyP->alpha=templateParams->skyP->alpha*LAL_TWOPI/360.0;
00530   templateParams->skyP->delta=templateParams->skyP->delta*LAL_TWOPI/360.0;
00531 
00532   /* Convert signal spindown to conform with GenerateTaylorCW() definition */
00533   for(i=0;i<signalParams->spind->m;i++){signalParams->spind->spParams[i] /= f0;}
00534 
00535   /***** END USEFUL QUANTITIES *****/   
00536 
00537 
00538   /***** CALL ROUTINE TO GENERATE TIMESTAMPS *****/
00539         
00540   /*times(tSFT, mObsSFT, timeStamps, deletions);*/
00541   i=0;
00542   times2(tSFT, mObsCoh, &timeStamps, &sftPerCoh, deletions, mCohSFT);
00543   /*
00544     In order to tell many of the loops in this code how many times to iterate,
00545      we set a variable which is equal to the last entry in the sftPerCoh array.
00546      Note, that for no gaps, this number is simply mObsSFT; with gaps, it's 
00547      something else.  Regardless, this is the value that the subroutines know 
00548      as mObsSFT.
00549   */
00550   totalSFT = sftPerCoh[mObsCoh];
00551     /***** END TIMESTAMPS *****/
00552 
00553 
00554   /***** CREATE NOISE *****/
00555 
00556   if(noi!=NULL)
00557     {
00558       LALCreateVector(&status, &noise, (UINT4)nDeltaF*mObsSFT);
00559       LALCreateVector(&status, &temp, (UINT4)nDeltaF*mObsSFT);
00560       LALCreateRandomParams(&status, &params, seed);
00561         
00562       /* fill temp vector with normal deviates*/ 
00563       LALNormalDeviates(&status, temp, params); 
00564         
00565       /* rewrite into COMPLEX8 VECTOR *noise */
00566       i=0;
00567       while(i<nDeltaF*mObsSFT)
00568         {
00569           noise->data[i]=temp->data[i];
00570           i++;
00571         } 
00572 
00573       /* Destroy structures that were used here, if we can */
00574       LALDestroyRandomParams(&status, &params);
00575       LALSDestroyVector(&status, &temp);
00576     }
00577 
00578   /***** END CREATE NOISE *****/
00579 
00580   /* Quantities computed for barycentering */
00581   edat=(EphemerisData *)LALMalloc(sizeof(EphemerisData));
00582   (*edat).ephiles.earthEphemeris = earthEphemeris;
00583   (*edat).ephiles.sunEphemeris = sunEphemeris;
00584 
00585   /* Read in ephemerides */  
00586   LALInitBarycenter(&status, edat);
00587   /*Getting detector coords from DetectorSite module of tools package */   
00588   
00589   /* Cached options are:
00590      LALDetectorIndexLHODIFF, LALDetectorIndexLLODIFF,
00591      LALDetectorIndexVIRGODIFF, LALDetectorIndexGEO600DIFF,
00592      LALDetectorIndexTAMA300DIFF,LALDetectorIndexCIT40DIFF 
00593   */
00594   cachedDetector = lalCachedDetectors[LALDetectorIndexGEO600DIFF];
00595   baryinput.site.location[0]=cachedDetector.location[0]/LAL_C_SI;
00596   baryinput.site.location[1]=cachedDetector.location[1]/LAL_C_SI;
00597   baryinput.site.location[2]=cachedDetector.location[2]/LAL_C_SI;
00598   baryinput.alpha=signalParams->skyP->alpha;
00599   baryinput.delta=signalParams->skyP->delta;
00600   baryinput.dInv=0.e0;
00601 
00602   /***** CREATE SIGNAL *****/
00603   
00604   /* Set up parameter structure */  
00605   /* Source position */
00606   genTayParams.position.latitude  = signalParams->skyP->alpha;
00607   genTayParams.position.longitude = signalParams->skyP->delta;
00608   genTayParams.position.system = COORDINATESYSTEM_EQUATORIAL;
00609   /* Source polarization angle */
00610   /* Note, that the way we compute the statistic, we don't care what this value is. */
00611   genTayParams.psi = 0.0;
00612   /* Source initial phase */
00613   genTayParams.phi0 = 0.0; 
00614   /* Source polarization amplitudes */
00615   genTayParams.aPlus = aPlus;
00616   genTayParams.aCross = aCross;
00617   /* Source intrinsic frequency */
00618   genTayParams.f0 = f0;
00619   /* Source spindown parameters: create vector and assign values */
00620   genTayParams.f = NULL;
00621   LALDCreateVector(&status, &(genTayParams.f), signalParams->spind->m); 
00622   for(i=0;i<signalParams->spind->m;i++){genTayParams.f->data[i] = signalParams->spind->spParams[i];} 
00623   /* Time resolution for source */
00624   /* Note, that this needs to be sampled only very coarsely! */
00625   genTayParams.deltaT = 100.0;
00626   /* Length should include fudge factor to allow for barycentring */
00627   genTayParams.length = (tObs+1200.0)/genTayParams.deltaT;
00628   memset(&cwDetector, 0, sizeof(DetectorResponse));
00629   /* The ephemerides */
00630   cwDetector.ephemerides = edat;
00631   /* Specifying the detector site (set above) */
00632   cwDetector.site = &cachedDetector;  
00633   /* The transfer function.  
00634    * Note, this xfer function has only two points */
00635   cwDetector.transfer = (COMPLEX8FrequencySeries *)LALMalloc(sizeof(COMPLEX8FrequencySeries));
00636   memset(cwDetector.transfer, 0, sizeof(COMPLEX8FrequencySeries));
00637   cwDetector.transfer->epoch = timeStamps[0];
00638   cwDetector.transfer->f0 = 0.0;
00639   cwDetector.transfer->deltaF = 16384.0;
00640   cwDetector.transfer->data = NULL;
00641   LALCCreateVector(&status, &(cwDetector.transfer->data), 2);
00642   /* Allocating space for the eventual time series */
00643   timeSeries = (REAL4TimeSeries *)LALMalloc(sizeof(REAL4TimeSeries));
00644   timeSeries->data = (REAL4Vector *)LALMalloc(sizeof(REAL4Vector));
00645   
00646   /* The length of the TS will be plenty long; below, we have it set so that
00647    * it is sampled at just better than twice the Nyquist frequency, then 
00648    * increased that to make it a power of two (to facilitate a quick FFT)  
00649    */
00650   {
00651     INT4 lenPwr;
00652     lenPwr = ceil(log(tSFT*2.01*f0)/log(2.0));
00653     timeSeries->data->length = pow(2.0,lenPwr);
00654   }
00655   
00656   timeSeries->data->data = (REAL4 *)LALMalloc(timeSeries->data->length*sizeof(REAL4));
00657   dt = timeSeries->deltaT = tSFT/timeSeries->data->length;
00658 
00659   /* unit response function */
00660   cwDetector.transfer->data->data[0].re = 1.0;
00661   cwDetector.transfer->data->data[1].re = 1.0;
00662   cwDetector.transfer->data->data[0].im = 0.0;
00663   cwDetector.transfer->data->data[1].im = 0.0;
00664   /* again, the note about the barycentring */
00665   genTayParams.epoch.gpsSeconds = timeStamps[0].gpsSeconds - 600; 
00666   genTayParams.epoch.gpsNanoSeconds = timeStamps[0].gpsNanoSeconds; 
00667   memset(&cgwOutput, 0, sizeof(CoherentGW));
00668 
00669   /* 
00670    *
00671    * OKAY, GENERATE THE SIGNAL @ THE SOURCE 
00672    *
00673    */
00674   LALGenerateTaylorCW(&status, &cgwOutput, &genTayParams);      
00675 
00676   {
00677     INT4 len,len2;
00678     
00679     len=timeSeries->data->length;
00680     len2=len/2+1;
00681     
00682     /* Create vector to hold frequency series */
00683     LALCCreateVector(&status, &fvec, (UINT4)len2);
00684     
00685     /* Compute measured plan for FFTW */
00686     LALCreateForwardRealFFTPlan(&status, &pfwd, (UINT4)len, 0);
00687     
00688     /* Allocate memory for the SFTData structure */
00689     /* 
00690      * Note that the length allocated for the data
00691      * array is the width of the band we're interested in,
00692      * plus f0*4E-4 for the 'wings', plus a bit of wiggle room.
00693      */
00694     SFTData=(FFT **)LALMalloc(totalSFT*sizeof(FFT *));
00695     for(i=0;i<totalSFT;i++){
00696       SFTData[i]=(FFT *)LALMalloc(sizeof(FFT));
00697       SFTData[i]->fft=(COMPLEX8FrequencySeries *)
00698         LALMalloc(sizeof(COMPLEX8FrequencySeries));
00699       SFTData[i]->fft->data=(COMPLEX8Vector *)
00700         LALMalloc(sizeof(COMPLEX8Vector));
00701       SFTData[i]->fft->data->data=(COMPLEX8 *)
00702         LALMalloc((nDeltaF+1)*sizeof(COMPLEX8));
00703     }
00704 
00705     /* Lots of debugging stuff.  If you want to use these, go ahead, but
00706      * be warned that these files may be HUGE (10s-100s of GB).
00707      */
00708 
00709     {
00710       REAL4Vector *tempTS = NULL; 
00711       
00712       LALSCreateVector(&status, &tempTS, (UINT4)len); 
00713       
00714       for(a=0;a<totalSFT;a++)
00715         {
00716           REAL4Vector *ts = timeSeries->data;
00717           /*  
00718            *  Note that this epoch is different from the epoch of GenTay.
00719            *  The difference is seconds, a little bit more than the 
00720            *  maximum propagation delay of a signal between the Earth
00721            *  and the solar system barycentre.
00722            */
00723           timeSeries->epoch = timeStamps[a];
00724           /* 
00725            *
00726            *  OKAY, CONVERT SOURCE SIGNAL TO WHAT SOMEBODY SEES AT THE DETECTOR OUTPUT
00727            *
00728            */
00729           LALSimulateCoherentGW(&status, timeSeries, &cgwOutput, &cwDetector);
00730             
00731           /* Write time series of correct size to temp Array, for FFT */
00732           for(i=0;i<len;i++)
00733             {
00734               tempTS->data[i] = ts->data[i];
00735             }
00736           
00737           /* Perform FFTW-LAL Fast Fourier Transform */
00738           LALForwardRealFFT(&status, fvec, tempTS, pfwd);
00739           
00740           {     
00741             INT4 fL = ifMin;
00742             INT4 cnt = 0; 
00743             while(fL < ifMin+nDeltaF+1)
00744               {
00745                 COMPLEX8 *tempSFT=SFTData[a]->fft->data->data;
00746                 COMPLEX8 *fTemp=fvec->data;
00747                 
00748                 /* Also normalise */
00749                 tempSFT[cnt].re = fTemp[fL].re * oneOverSqrtTSFT;
00750                 tempSFT[cnt].im = fTemp[fL].im * oneOverSqrtTSFT;
00751 
00752                 cnt++; fL++;
00753                 
00754               }
00755 
00756           }
00757           /* assign particulars to each SFT */
00758           SFTData[a]->fft->data->length = nDeltaF+1;  
00759           SFTData[a]->fft->epoch = timeStamps[a];
00760           SFTData[a]->fft->f0 = f0Min; /* this is the frequency of the first freq in the band */
00761           SFTData[a]->fft->deltaF = dfSFT;
00762           printf("Created SFT number %d of %d\n.",a, mObsSFT);
00763           
00764         }
00765       LALSDestroyVector(&status, &tempTS);
00766     }
00767     
00768     /*
00769      * Note, we have to destroy the memory that GenTay allocates.
00770      * This is currently (04.02) not documented! 
00771      */
00772     
00773     if(&(cgwOutput.a) !=NULL) {
00774       LALSDestroyVectorSequence(&status, &(cgwOutput.a->data));
00775       LALFree(cgwOutput.a); 
00776     }
00777     if(&(cgwOutput.f) !=NULL) {
00778       LALSDestroyVector(&status, &(cgwOutput.f->data));
00779       LALFree(cgwOutput.f);
00780     }
00781     if(&(cgwOutput.phi) !=NULL) {
00782       LALDDestroyVector(&status, &(cgwOutput.phi->data));
00783       LALFree(cgwOutput.phi);
00784     }
00785 
00786     if(noi!=NULL) {LALDestroyVector(&status, &noise);} 
00787     LALCDestroyVector(&status, &fvec);
00788     LALFree(timeSeries->data->data);
00789     LALFree(timeSeries->data);
00790     LALFree(timeSeries);
00791     LALDestroyRealFFTPlan(&status, &pfwd);
00792   }
00793   LALDDestroyVector(&status,&(genTayParams.f));
00794   LALCDestroyVector(&status, &(cwDetector.transfer->data));
00795   LALFree(cwDetector.transfer);
00796 
00797   /***** END CREATE SIGNAL *****/
00798 
00799 
00800  /* BEGIN AMPLITUDE MODULATION */
00801 
00802   /* Allocate space for amParams stucture */
00803   /* Here, amParams->das is the Detector and Source info */
00804   amParams = (AMCoeffsParams *)LALMalloc(sizeof(AMCoeffsParams));
00805   amParams->das = (LALDetAndSource *)LALMalloc(sizeof(LALDetAndSource));
00806   amParams->das->pSource = (LALSource *)LALMalloc(sizeof(LALSource));
00807   /* Fill up AMCoeffsParams structure */
00808   amParams->baryinput = &baryinput;
00809   amParams->earth = &earth;
00810   amParams->edat = edat;
00811   amParams->das->pDetector = &cachedDetector; 
00812   amParams->das->pSource->equatorialCoords.latitude = signalParams->skyP->alpha;
00813   amParams->das->pSource->equatorialCoords.longitude = signalParams->skyP->delta;
00814   amParams->das->pSource->orientation = 0.0;
00815   amParams->das->pSource->equatorialCoords.system = COORDINATESYSTEM_EQUATORIAL;
00816   amParams->polAngle = genTayParams.psi;
00817   amParams->mObsSFT = totalSFT;
00818  /* Allocate space for AMCoeffs */
00819   amc.a = NULL;
00820   amc.b =