Exemplo n.º 1
0
int GetSSBTime(LIGOTimeGPS *tdet, LIGOTimeGPS *tssb)
{
static LALStatus status;  
printf("start function GetSSBTime\n");
         baryinput.tgps.gpsSeconds=tdet->gpsSeconds;
	 baryinput.tgps.gpsNanoSeconds=tdet->gpsNanoSeconds;


	/*Get coords for detector LHO*/
       
         cachedDetector=lalCachedDetectors[LALDetectorIndexLHODIFF];
         baryinput.site.location[0]=cachedDetector.location[0]/LAL_C_SI;
         baryinput.site.location[1]=cachedDetector.location[1]/LAL_C_SI;
         baryinput.site.location[2]=cachedDetector.location[2]/LAL_C_SI;
         baryinput.alpha=0;
	 baryinput.delta=0;
	 baryinput.dInv=0.e0;
	 
	 LALBarycenterEarth(&status, &earth, tdet, edat);

	 REPORTSTATUS(&status);
LALBarycenter(&status, &emit, &baryinput, &earth);

tssb->gpsSeconds=emit.te.gpsSeconds;
tssb->gpsNanoSeconds=emit.te.gpsNanoSeconds;
printf("time at the SSB is : %d\n",tssb->gpsSeconds);
printf("end function GetSSBTime");
return 4;
}
Exemplo n.º 2
0
/**
 * Given an input index which refers to the sky patch under consideration, this
 * routine returns the phase model coefficients \f$A_{s\alpha}\f$ and \f$B_{s\alpha}\f$
 * which are needed to correctly account for the phase variance of a signal over
 * time.  The \c CSParams parameter structure contains relevant information
 * for this routine to properly run.  In particular, it contains an array of
 * timestamps in \c LIGOTimeGPS format, which are the GPS times of the first
 * data from each SFT.  The \c input is an \c INT4 variable
 * \c iSkyCoh, which is the index of the sky patch under consideration.  For
 * each sky patch, this code needs to be run once; the necessary phase model
 * coefficients are calculated, and can then be applied to the relevant spindown
 * parameter sets one is using in their search.
 *
 * ### Algorithm ###
 *
 * The routine uses a simplistic nested for-loop structure.  The outer loop is
 * over the number of SFTs in the observation timescale; this accounts for the
 * temporal variability of the phase model coefficients.  The inner loop is over
 * the number of spindown parameters in one set.  Inside the inner loop, the
 * values are calculated using the analytical formulae given in the
 * \ref ComputeSky.h documentation.
 *
 * ### Notes ###
 *
 * The reference-time, at which the pulsar spin-parameters are defined, is
 * taken to be the start-time *INTERPRETED* as an SSB time (i.e. no translation
 * is done, the times are numerically equal!).
 */
void
LALComputeSky (LALStatus *status,
	       REAL8 *skyConst,
	       INT8 iSkyCoh,
	       CSParams	*params)
{

  INT4	m, n;
  REAL8	t;
  REAL8	basedTbary;

  REAL8	dTbary;
  REAL8	tBary;
  REAL8	tB0;
  INITSTATUS(status);
  ATTATCHSTATUSPTR(status);

  /* Check for non-negativity of sky positions in SkyCoh[] */
  ASSERT(iSkyCoh>=0, status, COMPUTESKYH_ENEGA, COMPUTESKYH_MSGENEGA);

  /* Check to make sure sky positions are loaded */
  ASSERT(params->skyPos!=NULL, status, COMPUTESKYH_ENULL, COMPUTESKYH_MSGENULL);
  ASSERT(params->skyPos!=NULL, status, COMPUTESKYH_ENULL, COMPUTESKYH_MSGENULL);

  /* Check to make sure parameters are loaded and reasonable */
  ASSERT(params->spinDwnOrder>=0, status, COMPUTESKYH_ENEGA, COMPUTESKYH_MSGENEGA);
  ASSERT(params->mObsSFT>=0, status, COMPUTESKYH_ENEGA, COMPUTESKYH_MSGENEGA);
  ASSERT(params->tSFT>=0, status, COMPUTESKYH_ENEGA, COMPUTESKYH_MSGENEGA);

  for(n=0;n<params->mObsSFT;n++)
    {
      ASSERT(params->tGPS[n].gpsSeconds>=0, status, COMPUTESKYH_ENEGA, 	COMPUTESKYH_MSGENEGA);
    }

  /* Check to make sure pointer to output is not NULL */
  ASSERT(skyConst!=NULL, status, COMPUTESKYH_ENNUL, COMPUTESKYH_MSGENNUL);

  params->baryinput->alpha=params->skyPos[iSkyCoh];
  params->baryinput->delta=params->skyPos[iSkyCoh+1];

  /* NOTE: we DO NOT translate the start-time into the SSB frame,
   * as this would result in a source-position dependent reference-time.
   * Instead we simply take the GPS start-time and interpret it as the
   * SSB reference-time
   */
  /*
    params->baryinput->tgps.gpsSeconds=params->tGPS[0].gpsSeconds;
    params->baryinput->tgps.gpsNanoSeconds=params->tGPS[0].gpsNanoSeconds;

    LALBarycenterEarth(status->statusPtr, params->earth, &(params->baryinput->tgps), params->edat);
    LALBarycenter(status->statusPtr, params->emit, params->baryinput, params->earth);
    TimeToFloat(&tB0, &(params->emit->te));
  */
  TimeToFloat(&tB0, &(params->tGPS[0]));


  for (n=0; n<params->mObsSFT; n++)
   {
     t=(REAL8)(params->tGPS[n].gpsSeconds)+(REAL8)(params->tGPS[n].gpsNanoSeconds)*1.0E-9+0.5*params->tSFT;

     FloatToTime(&(params->baryinput->tgps), &t);

     TRY( LALBarycenterEarth(status->statusPtr, params->earth, &(params->baryinput->tgps), params->edat),
	  status);
     TRY( LALBarycenter(status->statusPtr, params->emit, params->baryinput, params->earth), status);

     TimeToFloat(&tBary, &(params->emit->te));

     dTbary = tBary-tB0;

     for (m=0; m<params->spinDwnOrder+1; m++)
       {
	 basedTbary = pow(dTbary, (REAL8)m);
	 skyConst[2*n*(params->spinDwnOrder+1)+2*(INT4)m]=1.0/((REAL8)m+1.0)*basedTbary*dTbary-0.5*params->tSFT*params->emit->tDot*basedTbary;
	 skyConst[2*n*(params->spinDwnOrder+1)+2*(INT4)m+1]= params->tSFT*params->emit->tDot*basedTbary;
       }
   }
  /* Normal Exit */
  DETATCHSTATUSPTR(status);
  RETURN(status);
}
Exemplo n.º 3
0
void StackSlideComputeSkyBinary( LALStatus 			*status, 
				 TdotsAndDeltaTs 		*pTdotsAndDeltaTs, 
				 INT8 				iSkyCoh,
				 /*StackSlideBinarySkyParams 	*params*/
				 StackSlideSkyParams 		*params
			        )

{
  INT4 m, n, nP;
  REAL8 dTbary;
  LALTimeInterval dTBaryInterval;
  LALTimeInterval HalfSFT;
  REAL8 HalfSFTfloat;
  REAL8   dTbarySP;
  REAL8   dTperi;
  REAL8   dTcoord;
  REAL8   Tdotbin;
  REAL8   basedTperi;
  DFindRootIn input;
  REAL8 tr0;
  REAL8 acc;

  #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
    fprintf(stdout,"start function ComputeSkyBinary\n");
    fflush(stdout);   
  #endif

  INITSTATUS(status);
  ATTATCHSTATUSPTR(status);

  /*for (i=0;i< SSparams->numSTKs; i++)
        	{
  			tGPS[i].gpsSeconds=SSparams->gpsStartTimeSec +(UINT4)(i*(SSparams->tSTK));
  	        	tGPS[i].gpsNanoSeconds=SSparams->gpsStartTimeNan;
  	                       
       	        }*/
  /*is this SSparams or params?*/

  /*#ifdef 0 */
  /* Check for non-negativity of sky positions in SkyCoh[] */
  ASSERT(iSkyCoh>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);

  /* Check to make sure sky positions are loaded */
  ASSERT(params->skyPos!=NULL, status, COMPUTESKYBINARYH_ENULL, COMPUTESKYBINARYH_MSGENULL);
  ASSERT(params->skyPos!=NULL, status, COMPUTESKYBINARYH_ENULL, COMPUTESKYBINARYH_MSGENULL);
  /* Check to make sure parameters are loaded and reasonable */
  ASSERT(params->spinDwnOrder>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
  ASSERT(params->mObsSFT>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
  ASSERT(params->tSFT>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);

  /* Check to make sure orbital parameters are loaded and reasonable */
  ASSERT(params->SemiMajorAxis>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
  ASSERT(params->OrbitalPeriod>0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
  ASSERT(params->OrbitalEccentricity>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
  ASSERT((params->ArgPeriapse>=0)&&(params->ArgPeriapse<=LAL_TWOPI), status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
  ASSERT(params->TperiapseSSB.gpsSeconds>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA); 
  ASSERT((params->TperiapseSSB.gpsNanoSeconds>=0)&&(params->TperiapseSSB.gpsNanoSeconds<1e9), status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
  /*#endif*/ 

  /* Here we redefine the orbital variables for ease of use */
  #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
    fprintf(stdout,"leap %d\n",params->edat->leap); 
    fflush(stdout);   
  #endif

  a=params->SemiMajorAxis;  /* This is the projected semi-major axis of the orbit normalised by the speed of light */
  Period=params->OrbitalPeriod;  /* This is the period of the orbit in seconds */
  ecc=params->OrbitalEccentricity;  /* This is the eccentricity of the orbit */
  parg=params->ArgPeriapse;  /* This is the argument of periapse defining the angular location of the source at periapsis */
                            /* measured relative to the ascending node */
  Tperi.gpsSeconds=params->TperiapseSSB.gpsSeconds;  /* This is the GPS time as measured in the SSB of the observed */
  Tperi.gpsNanoSeconds=params->TperiapseSSB.gpsNanoSeconds;  /* periapse passage of the source */

  /* Convert half the SFT length to a LALTimeInterval for later use */
  HalfSFTfloat=params->tSFT/2.0;
  #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
    fprintf(stdout,"HalfSFTfl %f\n",HalfSFTfloat);
    fflush(stdout);   
  #endif 

  LALFloatToInterval(status->statusPtr,&HalfSFT,&HalfSFTfloat);

  /* Here we check that the GPS timestamps are greater than zero */
  for(n=0;n<params->mObsSFT;n++)
  {
     ASSERT(params->tGPS[n].gpsSeconds>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
     /*ASSERT(tGPS[n].gpsSeconds>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);*/
  }
  
  /* Check to make sure pointer to output is not NULL */
  /*ASSERT(skyConst!=NULL, status, COMPUTESKYBINARYH_ENNUL, COMPUTESKYBINARYH_MSGENNUL);*/
  
  ASSERT(pTdotsAndDeltaTs!=NULL, status, COMPUTESKYBINARYH_ENNUL, COMPUTESKYBINARYH_MSGENNUL);

  /* prepare params input sky position structure */
  /* params->baryinput->alpha=params->skyPos[iSkyCoh];
  params->baryinput->delta=params->skyPos[iSkyCoh+1];*/
  /* params->baryinput->alpha=SSparams->skyPosData[iSky][iSkyCoh];
  params->baryinput->delta=SSparams->skyPosData[iSky][iSkyCoh+1]; maybe put it back*/

  /* calculate phase model coefficients p and q which are defined in the ComputeSkyBinary header LAL documentation  */
 
  p=((LAL_TWOPI/(Period*1.0))*a*sqrt(1-(ecc*ecc))*cos(parg))-ecc;
  q=(LAL_TWOPI/(Period*1.0))*a*sin(parg);

  /* Calculate the required accuracy for the root finding procedure in the main loop */
  acc=LAL_TWOPI*(REAL8)ACC/Period;   /* ACC is defined in ComputeSkyBinary.h and represents the required */
                                    /* timing precision in seconds (roughly)*/

  /* begin loop over SFT's */
  for (n=0; n<params->mObsSFT; n++)
  {
     /* Calculate the detector time at the mid point of current SFT ( T(i)+(tsft/2) ) using LAL functions */
     /*!*/ /* LALIncrementGPS(status->statusPtr,&(params->baryinput->tgps),&params->tGPS[n],&HalfSFT);*/
     /*  LALIncrementGPS(status->statusPtr,&(params->baryinput->tgps),&tGPS[n],&HalfSFT);*/

     LALIncrementGPS(status->statusPtr, &(params->baryinput->tgps),&params->tGPS[n],&HalfSFT);
 
     #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
       fprintf(stdout,"tgps %d\n",params->baryinput->tgps.gpsSeconds);
       fprintf(stdout,"leap %d\n",params->edat->leap);
       fflush(stdout);   
     #endif

     /* Convert this mid point detector time into barycentric time (SSB) */

     /* GetSSBTime(&(baryinput.tgps), &TmidSSB) ;*/

     LALBarycenterEarth(status->statusPtr, params->earth, &(params->baryinput->tgps), params->edat);    
     LALBarycenter(status->statusPtr, params->emit, params->baryinput, params->earth);   

     CHECKSTATUSPTR(status);
     #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
       fprintf(stdout,"status %d\n",status->statusCode); 
       fflush(stdout);   
     #endif

     /* LALBarycenterEarth(status->statusPtr, csParams->earth, &(csParams->baryinput->tgps), csParams->edat);    
        LALBarycenter(status->statusPtr, csParams->emit, csParams->baryinput, csParams->earth);*/       

     /* Calculate the time difference since the observed periapse passage in barycentric time (SSB). */ 
     /* This time difference, when converted to REAL8, should lose no precision unless we are dealing */
     /* with periods >~ 1 Year */
     
     LALDeltaGPS(status->statusPtr,&dTBaryInterval,&(params->emit->te),&Tperi); 
               
     LALIntervalToFloat(status->statusPtr,&dTbary,&dTBaryInterval);

     /* LALDeltaGPS(status->statusPtr,&dTBaryInterval,&(csParams->emit->te),&Tperi); 
        LALIntervalToFloat(status->statusPtr,&dTbary,&dTBaryInterval);*/

     /* Calculate the time since the last periapse passage ( < Single Period (SP) ) */
     dTbarySP=Period*((dTbary/(1.0*Period))-(REAL8)floor(dTbary/(1.0*Period)));
     
     /* Calculate number of full orbits completed since the input observed periapse passage */
     nP=(INT4)floor(dTbary/(1.0*Period));
     
     #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
       fprintf(stdout,"dTbary is %f\n",dTbary);
       fprintf(stdout,"dTbarySP is %f\n",dTbarySP);
       fprintf(stdout,"nP is %i\n",nP);
       fflush(stdout);   
     #endif

     /* begin root finding procedure */
     tr0 = dTbarySP;        /* we wish to find the value of the eccentric anomaly E corresponding to the time */
                            /* since the last periapse passage */
     input.function = Ft;   /* This is the name of the function we must solve to find E */
     input.xmin = 0.0;      /* We know that E will be found between 0 and 2PI */
     input.xmax = LAL_TWOPI;
     input.xacc = acc;      /* The accuracy of the root finding procedure */

     /* expand domain until a root is bracketed */
     LALDBracketRoot(status->statusPtr,&input,&tr0); 

     /* bisect domain to find eccentric anomoly E corresponding to the current midpoint timestamp */
     LALDBisectionFindRoot(status->statusPtr,&E,&input,&tr0); 
 
     /* Now we calculate the time interval since the input periapse passage as measured at the source */ 
     dTperi=(Period/LAL_TWOPI)*(E-(ecc*sin(E)))+((REAL8)nP*Period); 

     #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
       fprintf(stdout,"dTperi is %f\n",dTperi);     
       fflush(stdout);   
     #endif

     /* The following quantity is the derivative of the time coordinate measured at the source with */
     /* respect to the time coordinate measured in the SSB : dt_(source)/dt_(SSB) */
     dTcoord=(1.0-(ecc*cos(E)))/(1.0+(p*cos(E))-(q*sin(E)));  

     /* The following quantity is the derivitive of the time coordinate measured in the SSB with */
     /* respect to the time coordinate measured at the chosen detector.  It was calculated via the */
     /* last call to LALBarycenter : dt_(SSB)/dt_(detector)  */
     Tdotbin = params->emit->tDot*dTcoord; /*=dt_source/dt_detector puts you back into the source*/ 

     /*fprintf(stdout,"%g %g\n", params->emit->tDot, dTcoord);*/

     #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
        fprintf(stdout,"tDot is %f\n",params->emit->tDot); 
       fprintf(stdout,"dTcoord is %f\n",dTcoord);     
       fprintf(stdout,"Tdotbin is %f\n",Tdotbin);
       fflush(stdout);   
     #endif

     /*    Tdotbin = csParams->emit->tDot*dTcoord; */
     
     /* Loop over all spin down orders plus 0th order (f0) */
     /* In this loop we calculate the SkyConstants defined in the documentation as A_{s,alpha} and B_{s,alpha} */

      
     /*!*/ pTdotsAndDeltaTs->vecTDots[n]= Tdotbin;
     
     #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
       fprintf(stdout,"pTdotsAndDeltaTs->vecTDots is %f\n",pTdotsAndDeltaTs->vecTDots[n]);
       fflush(stdout);   
     #endif

     for (m=0; m<params->spinDwnOrder; m++)
     {
       /* raise the quantity dTperi to the power m */
       basedTperi = pow(dTperi, (REAL8)m+1);

       
       #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
         fprintf(stdout,"basedTperi %f\n",basedTperi);
         fflush(stdout);
       #endif         

       /*!*/ /*the 2 lines below must be changed */

       /* Calculate A coefficients */
       /* skyConst[2*n*(params->spinDwnOrder+1)+2*(INT4)m]=1.0/((REAL8)m+1.0)*basedTperi*dTperi-0.5*params->tSFT*basedTperi*Tdotbin;*/
       /* Calculate B coefficients */
       /* skyConst[2*n*(params->spinDwnOrder+1)+2*(INT4)m+1]= params->tSFT*basedTperi*Tdotbin;*/

       /*expressing the time difference in the SSB */
       /*!*/ /*pTdotsAndDeltaTs->vecDeltaTs[m][n]= basedTperi*pTdotsAndDeltaTs->vecTDots[n]; */
       pTdotsAndDeltaTs->vecDeltaTs[n][m]= basedTperi; /*in the Source*/ 

       #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
         fprintf(stdout,"vecDeltaTs %f\n", pTdotsAndDeltaTs->vecDeltaTs[n][m]);
         fflush(stdout);
       #endif
    
     } /* END for (m=0; m<params->spinDwnOrder; m++) */
    
     #ifdef DEBUG_STACKSLIDECOMPUTESKYBINARY_FNC
       fprintf(stdout,"end function StackSlideComputeSkyBinary\n");
       fflush(stdout);
     #endif
  } /* for (n=0; n<params->mObsSFT; n++) */
  /*LALFree(params->edat->ephemE);
  LALFree(params->edat->ephemS);
  LALFree(params->edat);*/

  /* Normal Exit */
  DETATCHSTATUSPTR(status);
  RETURN(status);
}
Exemplo n.º 4
0
void StackSlideComputeSky (LALStatus            *status,
			   TdotsAndDeltaTs      *pTdotsAndDeltaTs,
			   StackSlideSkyParams  *params)
{  
  
  INT4 m, n;
  /* REAL8 t; */                  /* 07/27/05 gam; this and next variable are no longer used */
  /* REAL8 tBary; */
  REAL8 dTbary;                   /* T - T0 */
  REAL8 basedTbary;               /* temporary container for (T - T0)^m */
  /* REAL8 tB0; */                /* 07/27/05 gam; use next four variable to compute T - T0 in SSB using LAL functions */
  LIGOTimeGPS ssbT0;              /* T0 in the Solar System BaryCenter */
  LALTimeInterval dTBaryInterval; /* T - T0 in the Solar System BaryCenter */
  LALTimeInterval HalfSFT;        /* timebase of SFT/2 as GPS interval  */
  REAL8 HalfSFTfloat;             /* timebase of SFT/2 as REAL8 number */

  INITSTATUS(status);
  #ifdef DEBUG_STACKSLIDECOMPUTESKY_FNC
     fprintf(stdout, "Start StackSlideComputeSky\n"); 
     fflush(stdout);
  #endif  
  ATTATCHSTATUSPTR(status);
 
  /* Check for non-negativity of sky positions in SkyCoh[] */
  /* removed this, so is there another check we should do on sky position validity? */
  /* ASSERT(iSkyCoh>=0, status, STACKSLIDECOMPUTESKYH_ENEGA, STACKSLIDECOMPUTESKYH_MSGENEGA); */
 
  /* Check to make sure sky positions are loaded */
  ASSERT(params->skyPos!=NULL, status, STACKSLIDECOMPUTESKYH_ENULL, STACKSLIDECOMPUTESKYH_MSGENULL);
  ASSERT(params->skyPos!=NULL, status, STACKSLIDECOMPUTESKYH_ENULL, STACKSLIDECOMPUTESKYH_MSGENULL);
 
  /* Check to make sure parameters are loaded and reasonable */
  ASSERT(params->spinDwnOrder>=0, status, STACKSLIDECOMPUTESKYH_ENEGA, STACKSLIDECOMPUTESKYH_MSGENEGA);
  /* ASSERT(params->mObsSFT>=0, status, STACKSLIDECOMPUTESKYH_ENEGA, STACKSLIDECOMPUTESKYH_MSGENEGA); */ /* 07/27/05 gam */
  ASSERT(params->mObsSFT>0, status, STACKSLIDECOMPUTESKYH_ENEGA, STACKSLIDECOMPUTESKYH_MSGENEGA);
  ASSERT(params->tSFT>=0, status, STACKSLIDECOMPUTESKYH_ENEGA, STACKSLIDECOMPUTESKYH_MSGENEGA);
 
  for(n=0;n<params->mObsSFT;n++) {
     ASSERT(params->tGPS[n].gpsSeconds>=0, status, STACKSLIDECOMPUTESKYH_ENEGA, STACKSLIDECOMPUTESKYH_MSGENEGA);
  }
 
  /* Check to make sure pointer to output is not NULL */
  ASSERT(pTdotsAndDeltaTs!=NULL, status, STACKSLIDECOMPUTESKYH_ENNUL, STACKSLIDECOMPUTESKYH_MSGENNUL);
 
  /* 07/27/05 gam; note that the gpsStartTime refers to the start of the epoch that defines the template spindown parameters. */
  /* Next lines of code find ssbT0 == T0, the SSB time that defines this epoch */  
  /* 06/05/04 gam; set these to epoch that gives T0 at SSB. */  
  /* params->baryinput->tgps.gpsSeconds = params->gpsStartTimeSec;
  params->baryinput->tgps.gpsNanoSeconds = params->gpsStartTimeNan;
  LALBarycenterEarth(status->statusPtr, params->earth, &(params->baryinput->tgps), params->edat); CHECKSTATUSPTR(status);
  LALBarycenter(status->statusPtr, params->emit, params->baryinput, params->earth); CHECKSTATUSPTR(status); */
  /* TimeToFloat(&tB0, &(params->emit->te)); */ /* 07/27/05 gam; replace tB0 with ssbT0 */
  /* ssbT0.gpsSeconds = params->emit->te.gpsSeconds;
  ssbT0.gpsNanoSeconds = params->emit->te.gpsNanoSeconds; */
  /* 08/31/05 gam; set ssbT0 to gpsStartTime; this now gives the epoch that defines T0 at the SSB! */
  ssbT0.gpsSeconds = ((INT4)params->gpsStartTimeSec);
  ssbT0.gpsNanoSeconds = ((INT4)params->gpsStartTimeNan);

  /* 07/27/05 gam; Find GPS interval the represent 1/2 the SFT time baseline */
  HalfSFTfloat=params->tSFT/2.0;
  LALFloatToInterval(status->statusPtr,&HalfSFT,&HalfSFTfloat); CHECKSTATUSPTR(status);

  /* Find T - T0, dT/dt, powers of T - T0 for midpoint time of each SFT; save in pTdotsAndDeltaTs struct */
  for (n=0; n<params->mObsSFT; n++) {     
     /* 07/27/05 gam; set params->baryinput->tgps to the midpoint time of the current SFT */
     /*t=(REAL8)(params->tGPS[n].gpsSeconds)+(REAL8)(params->tGPS[n].gpsNanoSeconds)*1.0E-9+0.5*params->tSFT;
     FloatToTime(&(params->baryinput->tgps), &t);*/ /* Instead use LALIncrementGPS: */
     LALIncrementGPS(status->statusPtr, &(params->baryinput->tgps),&(params->tGPS[n]),&HalfSFT);
          
     /* 07/27/05 gam; find T - T0 in SSB and tDot = dT/dt for midpoint time of current SFT */
     LALBarycenterEarth(status->statusPtr, params->earth, &(params->baryinput->tgps), params->edat); CHECKSTATUSPTR(status);
     LALBarycenter(status->statusPtr, params->emit, params->baryinput, params->earth); CHECKSTATUSPTR(status);
     /* TimeToFloat(&tBary, &(params->emit->te));  
     dTbary = tBary-tB0; */ /* 07/27/05 gam; replace tB0 with ssbT0 */
     /* Subtract two LIGOTimeGPS to get LALTimeInterval; convert to REAL8 */
     LALDeltaGPS(status->statusPtr,&dTBaryInterval,&(params->emit->te),&ssbT0); CHECKSTATUSPTR(status);
     LALIntervalToFloat(status->statusPtr,&dTbary,&dTBaryInterval); CHECKSTATUSPTR(status);
     pTdotsAndDeltaTs->vecTDots[n]= params->emit->tDot;
     
     /* for (m=0; m<params->spinDwnOrder+1; m++) */
      for (m=0; m<params->spinDwnOrder; m++) {
         basedTbary = pow(dTbary, (REAL8)m+1);
         pTdotsAndDeltaTs->vecDeltaTs[n][m]= basedTbary;
      }
  }
  
  /* Normal Exit */
  DETATCHSTATUSPTR(status);
  RETURN(status);
} /* END StackSlideComputeSky() */
Exemplo n.º 5
0
int main(int argc, char **argv)
{
    FILE *fp  = NULL;
    FILE *fp2 = NULL;
    FILE *fp3 = NULL;
    FILE *fp4 = NULL;
    LALStatus status = blank_status;
    
    SFTCatalog *catalog = NULL;
    SFTVector *sft_vect = NULL;
    INT4 i,j,k,l;
    INT4 numBins, nSFT;
    SFTConstraints constraints=empty_SFTConstraints;
    LIGOTimeGPS startTime, endTime; 
    REAL8 avg =0;
    REAL4 *timeavg =NULL;
    REAL4 PWR,SNR;
    REAL8 f =0;
    CHAR outbase[256],outfile[256],outfile2[256],outfile3[256], outfile4[256]; /*, outfile6[256]; */
    REAL8 NumBinsAvg =0;
    REAL8 timebaseline =0;
    
    BOOLEAN help = 0;
    CHAR *SFTpatt = NULL;
    CHAR *IFO = NULL;
    INT4 startGPS = 0;
    INT4 endGPS = 0;
    REAL8 f_min = 0.0;
    REAL8 f_max = 0.0;
    REAL8 freqres =0.0;
    INT4 blocksRngMed = 101;
    CHAR *outputBname = NULL;
    INT4 cur_epoch = 0, next_epoch = 0;
    
    /* these varibales are for converting GPS seconds into UTC time and date*/
    struct tm         date;
    CHARVector        *timestamp = NULL;
    CHARVector	     *year_date = NULL;
    REAL8Vector     *timestamps=NULL;
    
    CHAR *psrInput = NULL;
    CHAR *psrEphemeris = NULL;
    CHAR *earthFile = NULL;
    CHAR *sunFile = NULL;
  /*========================================================================================================================*/
    
    
    LAL_CALL(LALRegisterBOOLUserVar  (&status, "help",         'h', UVAR_HELP,     "Print this help message",     &help        ), &status);
    LAL_CALL(LALRegisterSTRINGUserVar(&status, "SFTs",         'p', UVAR_REQUIRED, "SFT location/pattern",        &SFTpatt     ), &status);
    LAL_CALL(LALRegisterSTRINGUserVar(&status, "IFO",          'I', UVAR_REQUIRED, "Detector",                    &IFO         ), &status);
    LAL_CALL(LALRegisterINTUserVar   (&status, "startGPS",     's', UVAR_REQUIRED, "Starting GPS time",           &startGPS    ), &status);
    LAL_CALL(LALRegisterINTUserVar   (&status, "endGPS",       'e', UVAR_REQUIRED, "Ending GPS time",             &endGPS      ), &status);
    LAL_CALL(LALRegisterREALUserVar  (&status, "fMin",         'f', UVAR_REQUIRED, "Minimum frequency",           &f_min       ), &status);
    LAL_CALL(LALRegisterREALUserVar  (&status, "fMax",         'F', UVAR_REQUIRED, "Maximum frequency",           &f_max       ), &status);
    LAL_CALL(LALRegisterINTUserVar   (&status, "blocksRngMed", 'w', UVAR_OPTIONAL, "Running Median window size",  &blocksRngMed), &status);
    LAL_CALL(LALRegisterSTRINGUserVar(&status, "outputBname",  'o', UVAR_OPTIONAL, "Base name of output files",   &outputBname ), &status);
    LAL_CALL(LALRegisterREALUserVar  (&status, "freqRes",      'r', UVAR_REQUIRED, "Spectrogram freq resolution", &freqres     ), &status);
    LAL_CALL(LALRegisterREALUserVar  (&status, "timeBaseline", 't', UVAR_REQUIRED, "The time baseline of sfts",   &timebaseline), &status);
    LAL_CALL(LALRegisterSTRINGUserVar(&status, "psrInput",     'P', UVAR_OPTIONAL, "name of tempo pulsar file",   &psrInput ), &status);
    LAL_CALL(LALRegisterSTRINGUserVar(&status, "psrEphemeris", 'S', UVAR_OPTIONAL, "pulsar ephemeris file",   &psrEphemeris ), &status);
    LAL_CALL(LALRegisterSTRINGUserVar(&status, "earthFile",  'y', UVAR_OPTIONAL, "earth .dat file",   &earthFile ), &status);
    LAL_CALL(LALRegisterSTRINGUserVar(&status, "sunFile",   'z', UVAR_OPTIONAL, "sun .dat file",   &sunFile ), &status);
    
    LAL_CALL(LALUserVarReadAllInput(&status, argc, argv), &status);
    if (help)
    return(0);
    
    startTime.gpsSeconds = startGPS;/*cg; startTime is a structure, and gpsSeconds is a member of that structure*/
    startTime.gpsNanoSeconds = 0;/*cg; gps NanoSeconds is also a member of the startTime structure */
    constraints.minStartTime = &startTime; /*cg; & operator gets the address of variable, &a is a pointer to a.  This line puts the startTime structure into the structure constraints*/
    
    endTime.gpsSeconds = endGPS;
    endTime.gpsNanoSeconds = 0;
    constraints.maxEndTime = &endTime;/*cg; This line puts the end time into the structure constraints*/
    constraints.detector = IFO;/*cg; this adds the interferometer into the contraints structure*/
    LALSFTdataFind ( &status, &catalog, SFTpatt, &constraints );/*cg; creates SFT catalog, uses the constraints structure*/

    if (catalog == NULL)/*need to check for a NULL pointer, and print info about circumstances if it is null*/
    {
        fprintf(stderr, "SFT catalog pointer is NULL!  There has been an error with LALSFTdataFind\n");
        fprintf(stderr, "LALStatus info.... status code: %d, message: %s, offending function: %s\n", status.statusCode, status.statusDescription, status.function);
        exit(0);
    }
    if (catalog->length == 0)
    {
        fprintf(stderr, "No SFTs found, please exmanine start time, end time, frequency range etc\n");
        exit(0);
    }

    LALLoadSFTs ( &status, &sft_vect, catalog, f_min,f_max);/*cg;reads the SFT data into the structure sft_vect*/

    if (sft_vect == NULL)
    {
        fprintf(stderr, "SFT vector pointer is NULL!  There has been an error with LALLoadSFTs\n");
        fprintf(stderr, "LALStatus info.... status code: %d, message: %s, offending function: %s\n", status.statusCode, status.statusDescription, status.function);
        exit(0);
    }

    LALDestroySFTCatalog( &status, &catalog);/*cg; desctroys the SFT catalogue*/
    numBins = sft_vect->data->data->length;/*the number of bins in the freq_range*/
    nSFT = sft_vect->length;/* the number of sfts.*/
    
    fprintf(stderr, "nSFT = %d\tnumBins = %d\tf0 = %f\n", nSFT, numBins,sft_vect->data->f0);/*print->logs/spectrumAverage_testcg_0.err */
    if (LALUserVarWasSet(&outputBname))
    strcpy(outbase, outputBname);
    else
    sprintf(outbase, "spec_%.2f_%.2f_%s_%d_%d", f_min,f_max,constraints.detector,startTime.gpsSeconds,endTime.gpsSeconds);/*cg; this is the default name for producing the output files, the different suffixes are just added to this*/
    sprintf(outfile,  "%s", outbase);/*cg; name of first file to be output*/
    sprintf(outfile2, "%s_timestamps", outbase);/*cg: name of second file to be output*/
    sprintf(outfile3, "%s.txt", outbase);/*cg; name of third file to be output*/
    sprintf(outfile4, "%s_date", outbase);/*cg;file for outputting the date, which is used in matlab plotting.*/

    fp = fopen(outfile, "w");/*cg;  open all three files for writing, if they don't exist create them, if they do exist overwrite them*/
    fp2 = fopen(outfile2, "w");
    fp3 = fopen(outfile3, "w");
    fp4 = fopen(outfile4, "w");

/*----------------------------------------------------------------------------------------------------------------*/
/*cg; Create the first file called spec_blah_blah.  This file outputs the power in each spectrogram bin.  The number of bins depends on the frequency range, freq resolution, and number of SFTs.*/

/*cg;  Create the second file, called    blah_b;ah_blah_timestamps.  This will simply contain the time in GPS seconds of each SFT.*/

    NumBinsAvg = freqres*numBins/(f_max-f_min);/*this calcs the number of bins over which to average the sft data, this is worked out so it produces the same freq resolution as specified in the arguments passed to fscanDriver.py. numBins is the total number of bins in the raw sft data*/

    l=0;/*l is used as a counter to count how many SFTs and fake zero SFTs (used for gaps) are output for specgram.*/
    timestamps = XLALCreateREAL8Vector(l);/*test for getting rid of second loop*/
    LALCHARCreateVector(&status, &year_date, (UINT4)128); 

  /*create output files and check for missing sfts*/
    for (j=0;j<nSFT;j++)/*cg;nSFT is the numnber of SFT files used for the time specified. So process is repeated for each SFT*/
    {
        cur_epoch = sft_vect->data[j].epoch.gpsSeconds;/*finds the gps time of the current sft in the sequence with index j*/
        fprintf(fp2, "%d.\t%d\n", l, cur_epoch);/*cg; this bit writes the second file, i.e. the timestamps*/
    
        XLALResizeREAL8Vector(timestamps, l+1);/*resizes the vector timestamps, so cur_epoch can be added*/
        timestamps->data[l]= cur_epoch;/*number of gaps is not know in advance, hence need for te resizing*/
        XLALGPSToUTC(&date, cur_epoch);/*cg; gets the UTC date in struct tm format from the GPS seconds.*/
        fprintf(fp4, "%d\t %i\t %i\t %i\t %i\t %i\t %i\n", l, (date.tm_year+1900), date.tm_mon+1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
    
        for ( i=0; i < (numBins-2); i+=NumBinsAvg)/*cg; this loop works out the powers and writes the first file.*/
        {/*cg; each SFT is split up into a number of bins, the number of bins is read in from the SFT file*/
            avg = 0.0;/*cg; the vairable avg is reset each time.*/
            if (i+NumBinsAvg>numBins) {printf("Error\n");return(2);}/*cg; error is detected, to prevent referencing data past the end of sft_vect.*/
            for (k=0;k<NumBinsAvg;k++)/*cg; for each bin, k goes trhough each entry from 0 to 180.*/
                avg += sqrt(2*(crealf(sft_vect->data[j].data->data[i+k])*crealf(sft_vect->data[j].data->data[i+k]) + 
                cimagf(sft_vect->data[j].data->data[i+k])*cimagf(sft_vect->data[j].data->data[i+k]))/timebaseline);/*cg; re amd im are real and imaginary parts of SFT, duh!*/
            fprintf(fp,"%e\t",avg/NumBinsAvg);
        }
        fprintf(fp,"\n");
        /*------------------------------*/
        /*Bit to check if there is a gap in the sfts*/
        if ( j < (nSFT-1) )/*in all cases except when we are examining the last sft, check that there is no gap to the next sft*/
        {
            next_epoch = sft_vect->data[j+1].epoch.gpsSeconds;
            /*test to see if SFT gap is longer than 3/2*timebaseline, if so create another entry in the matrix*/
            while ((cur_epoch+((3/2)*timebaseline)) < next_epoch)
            {
                for ( i=0; i < (numBins-2); i+=NumBinsAvg)
                {
                    avg = 0.0;
                    if (i+NumBinsAvg>numBins) {printf("Error\n");return(2);}
                    fprintf(fp,"%e\t",avg);
                }
                fprintf(fp,"\n");
                l=l+1;
                cur_epoch=cur_epoch+timebaseline;
                fprintf(fp2, "%d.\t%d\n", l, cur_epoch );
                    
                XLALResizeREAL8Vector(timestamps, l+1);
                timestamps->data[l]= cur_epoch;
                XLALGPSToUTC(&date, cur_epoch);/*cg; gets the UTC date in struct tm format from the GPS seconds.*/
                fprintf(fp4, "%d\t %i\t %i\t %i\t %i\t %i\t %i\n", l, (date.tm_year+1900), date.tm_mon+1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
            }
            
        }
        l=l+1;
    }
    fprintf(stderr,"finished checking for missing sfts, l=%d\n", l);
/*----------------------------------------------------------------------------------------------------------------*/
/*cg;  Create the third and final file, called   blah_blah_blah.txt.  This file will contain the data used in the matlab plot script to plot the normalised average power vs the frequency.*/

    /* Find time average of normalized SFTs */
    LALNormalizeSFTVect(&status, sft_vect, blocksRngMed);   
    LALNormalizeSFTVect(&status, sft_vect, blocksRngMed);   
    timeavg = XLALMalloc(numBins*sizeof(REAL4));
    if (timeavg == NULL) fprintf(stderr,"Timeavg memory not allocated\n");

    for (j=0;j<nSFT;j++)
    { 
        for ( i=0; i < numBins; i++)
        {
            if (j == 0) 
            {
                timeavg[i] = crealf(sft_vect->data[j].data->data[i])*crealf(sft_vect->data[j].data->data[i]) + 
                            cimagf(sft_vect->data[j].data->data[i])*cimagf(sft_vect->data[j].data->data[i]);
            } 
            else 
            {
                timeavg[i] += crealf(sft_vect->data[j].data->data[i])*crealf(sft_vect->data[j].data->data[i]) + 
                            cimagf(sft_vect->data[j].data->data[i])*cimagf(sft_vect->data[j].data->data[i]);
            }
        }
    }
    /*timeavg records the power of each bin*/
    for ( i=0; i < numBins; i++)
    {
        f = sft_vect->data->f0 + ((REAL4)i)*sft_vect->data->deltaF;
	PWR=timeavg[i]/((REAL4)nSFT);
	SNR=(PWR-1)*(sqrt(((REAL4)nSFT)));
        fprintf(fp3,"%16.8f %g %g\n",f, PWR, SNR);
    } 
/*------------------------------------------------------------------------------------------------------------------------*/ 
/*End of normal spec_avg code, the remaining code is for crab freq calc.*/
/*================================================================================================================*/
/*================================================================================================================*/
    /*This next block of code is for the crab specific changes to fscan*/
    #define CRAB 0
    /*change this to CRAB 0 to prevent this section of code from compiling, change to 1 to compile it.*/
    #if CRAB
    /*--------------------------------------------------------------------------------------------------------------*/
    /*some header files for the crab*/
    /*#include "../TDS_isolated/HeterodyneCrabPulsar.h"*/
    /*#include "../TDS_isolated/heterodyne_pulsar.h"*/
    #include<../TDS_isolated/HeterodyneCrabPulsar.h>

    if (psrInput != NULL){

    fprintf(stderr,"--------------------\n\n");
    fprintf(stderr,"start of crab stuff\n");
    LIGOTimeGPS dataEpoch;
    /*below 4 structures are from HeterodyneCrabPulsar.h*/
    GetCrabEphemerisInput input; /*this is needed to get the crab ephemeris*/
    CrabSpindownParamsInput crabEphemerisData;
    CrabSpindownParamsOutput crabOutput;
    ParamsForHeterodyne hetParams;
    
    /*CG; these lines allocate memory for the crab ephemeris and crab output variables...*/
    crabEphemerisData.f1 = NULL;
    LALDCreateVector( &status, &crabEphemerisData.f1, NUM);
    
    crabEphemerisData.f0 = NULL;
    LALDCreateVector( &status, &crabEphemerisData.f0, NUM);
    
    crabEphemerisData.tArr = NULL;
    LALDCreateVector( &status, &crabEphemerisData.tArr, NUM);
    
    crabOutput.tArr = NULL;
    LALDCreateVector( &status, &crabOutput.tArr, NUM);
        
    crabOutput.f0 = NULL;
    LALDCreateVector( &status, &crabOutput.f0, NUM);
    
    crabOutput.f1 = NULL;
    LALDCreateVector( &status, &crabOutput.f1, NUM);
    
    crabOutput.f2 = NULL;
    LALDCreateVector( &status, &crabOutput.f2, NUM);
    
    crabOutput.f3 = NULL;
    LALDCreateVector( &status, &crabOutput.f3, NUM);
    
    crabOutput.f4 = NULL;
    LALDCreateVector( &status, &crabOutput.f4, NUM);
        
        
    /*This next set of variables are to do with the doppler shifts that are then applied to to the crab feq.*/
    REAL8 t2=0., tdt=0.;
    EphemerisData *edat=NULL;
    BarycenterInput baryinput, baryinput2;
    EarthState earth, earth2;
    EmissionTime  emit, emit2;
    REAL8 df=0., freq, finalFreq, max_df, minf, maxf;
    REAL8 dtpos=0.; /* time between position epoch and data timestamp */
    BinaryPulsarParams pulsarParams; /*general pulsar params strcut, despite binary name*/
    /*CHAR *psrInput = NULL;*/ /* pulsar input file containing params f0, f1 etc. */
    LALDetector det;
    CHAR detName[256];
    REAL8 ecliptic_lat, e_tilt=0.409092627;/*the ecliptic latitude of the source, and hte earth's tilt in radians (23.439281 degrees)*/

    char outfile5[256];
    FILE *fp5 = NULL;
    sprintf(outfile5, "%s_crab", outbase);
    fp5 = fopen(outfile5, "w");

    /*----------------------------------------------------------------------------------------------------------------*/
    /*cg; calculating the crab freq, done in three steps. This is done for each sft*/
    /*----------------------------------------------------------------------------------------------------------------*/
    /*    ---1---   */
    /*Find rough guess of crabs freq from ephemeris*/
    /*----------------------------------------------------------------------------------------------------------------*/
    
    /*Get detector position, this is needed for barycentre calcs*/
    det = *XLALGetSiteInfo( IFO );

    /* read in tempo par file for pulsar, This is one of the optional command line arguments*/
    /*fprintf(stderr,"%s\n",psrInput);*/
    fprintf(stderr,"%s\n",psrInput);
    XLALReadTEMPOParFile(&pulsarParams, psrInput);

    /*Make sure that posepoch and pepoch are set*/
    if(pulsarParams.pepoch == 0. && pulsarParams.posepoch != 0.)
	pulsarParams.pepoch = pulsarParams.posepoch;
    else if(pulsarParams.posepoch == 0. && pulsarParams.pepoch != 0.)
	pulsarParams.posepoch = pulsarParams.pepoch;
    fprintf(stderr,"Check on read tempo file, pepoch: %f\n", pulsarParams.pepoch);

    /*input.filename=psrEphemeris;*/ /*/archive/home/colingill/lalsuite/lalapps/src/pulsar/fscan/ /archive/home/colingill/public_html/crab_ephemeris.txt*/
    input.filename = XLALMalloc(sizeof(CHAR)*256);
    if(input.filename == NULL) fprintf(stderr,"input.filename pointer memory not allocated\t");

    strcpy(input.filename,psrEphemeris);
    /*fprintf(stderr,"psrEphemeris:%s\n", input.filename);*/

    /*The first stage is to read in f and fdot from the ephemeris, the crab_ephemeris.txt file is part of lalapps and is maintained by matt*/
    LALGetCrabEphemeris( &status, &crabEphemerisData, &input );
    /*check on the outputs, crabEphemerisData is a struct of type CrabSpindownParamsInput, and has members tArr, f0, f1*/
    fprintf(stderr,"input crab ephemeris present, number of entries: %i\n", crabEphemerisData.numOfData);
    fprintf(stderr,"crabEphemerisData: \ttarr= %f\tf0= %f\tf_dot= %e\n", crabEphemerisData.tArr->data[0], crabEphemerisData.f0->data[0], crabEphemerisData.f1->data[0]);
    
    /*Now I have f and fdot, use function below to compute the higher order derrivatives of the crabs frequency*/
    LALComputeFreqDerivatives( &status, &crabOutput, &crabEphemerisData );
    /*check on this function, crabOutput is datatype CrabSpindownParamsOutput*/
    fprintf(stderr,"crabOutput:\tf0= %f\tf1= %e\tf2= %e\n", crabOutput.f0->data[0], crabOutput.f1->data[0], crabOutput.f2->data[0]);/*need to change the type of printf for F1 and f2 to exponentials.*/
    fprintf(stderr,"--------------------\n");

    /*Allocate memory for edat, no need to do in the loop*/
    edat = XLALMalloc(sizeof(*edat));
    (*edat).ephiles.earthEphemeris = earthFile; /*"/archive/home/colingill/lalsuite/lal/packages/pulsar/test/earth05-09.dat";*/
    (*edat).ephiles.sunEphemeris = sunFile;/*"/archive/home/colingill/lalsuite/lal/packages/pulsar/test/sun05-09.dat";*/

    /*work out the eclitptic lattitude of the source, used in max freq calc.*/
    ecliptic_lat=asin(cos(e_tilt)*sin(pulsarParams.dec)-sin(pulsarParams.ra)*cos(pulsarParams.dec)*sin(e_tilt));
    fprintf(stderr,"eqcliptic_lat: %e\t", ecliptic_lat);

    for (i=0;i<l;i++)
    {
        if (i == (l-1))/*catches the last iteration where there is no i+1 entry in timestamps*/
        {
            cur_epoch = timestamps->data[i]+(timebaseline/2);
        }
        else
        {
            cur_epoch = timestamps->data[i]+((timestamps->data[i+1] - timestamps->data[i])/2);
        }

        fprintf(stderr,"cur_epoch: %d\t", cur_epoch);
        /*The time has to be set so that the nearest entry to that time in the ephemeris can be used*/
        dataEpoch.gpsSeconds = cur_epoch; /*INT8)floor(time->data[j]);*/
        dataEpoch.gpsNanoSeconds = 0;
    
        /*prepare hetParams, which is then used to get the freq derrivatives out and also in the next sub-section for Bary functions*/
        LALSetSpindownParams( &status, &hetParams, &crabOutput, dataEpoch );
        fprintf(stderr,"hetparams epoch: %f\t f0= %f\tf1= %e\n", hetParams.epoch, hetParams.f0, hetParams.f1);
    
        /*----------------------------------------------------------------------------------------------------------------*/
        /*    ---2---   */
        /*Add corrections for timing noise to get a better guess at the freq*/
        /*----------------------------------------------------------------------------------------------------------------*/
    
        /*now I want to use these params to calc the freq at any point in time.  Using the higher order derrivatives is how we adjust for timing noise.*/
    
        /*Get the time difference between the current epoch and the epoch of the ephemeris entry*/
        tdt= cur_epoch - hetParams.epoch;
        fprintf(stderr,"dt: %f,\tf1= %e,\tf2= %e,\tf3= %e,\tf4=%e\n", tdt, hetParams.f1, hetParams.f2, hetParams.f3, hetParams.f4);
    
        freq = 2.0*( hetParams.f0 + ((hetParams.f1)*tdt) + (((hetParams.f2)*tdt*tdt)/2) + (((hetParams.f3)*tdt*tdt*tdt)/6) + (((hetParams.f4)*tdt*tdt*tdt*tdt)/24) );
        fprintf(stderr,"crab fcoarse: %f\t", freq);
    
        /*freq = 2.0*(params->f0 + params->f1*t1 + (params->f2)*t1*t1+ (params->f3)*t1*t1*t1 + (params->f4)*t1*t1*t1*t1);*/  /*cg;line 486 from hetcrabpulsar, works out freq, this is with one order of t removed for each of the derrivatives of f, and also each term is divided by a factorial, 1!, 2!, 3!, but this starts one term along from the oroginal code as we have integrated the orginal code to get freq not phase*/
    
        /*----------------------------------------------------------------------------------------------------------------*/
        /*    ---3---   */
        /*Add doppler shifts for earth's motion back onto the freq to get actual observed freq at detectors.*/
        /*----------------------------------------------------------------------------------------------------------------*/
        
        /*now I have the freq, I need to add the doppler shift for the earths motion around the sun */
        baryinput.dInv = 0.;/*I can always set this to zero, as Matt said so, I must ask him why*/

        LAL_CALL( LALInitBarycenter(&status, edat), &status );/*  */
    
        /*this lines take position of detector which are in xyz coords in meters from earths centre and converts them into seconds (time)*/
        baryinput.site.location[0] = det.location[0]/LAL_C_SI;
        baryinput.site.location[1] = det.location[1]/LAL_C_SI;
        baryinput.site.location[2] = det.location[2]/LAL_C_SI;
    
        /*dtpos should be the time between the entry in the ephemeris and the point in time for which doppler shifts are being calc.ed*/
        dtpos = cur_epoch - pulsarParams.posepoch;
    
        /* set up RA, DEC, and distance variables for LALBarycenter*/
        baryinput.delta = pulsarParams.dec + dtpos*pulsarParams.pmdec;
        baryinput.alpha = pulsarParams.ra + dtpos*pulsarParams.pmra/cos(baryinput.delta);
        
        t2=cur_epoch+1;
    
        baryinput2 = baryinput;
        
        baryinput.tgps.gpsSeconds = (INT4)floor(cur_epoch);
        baryinput.tgps.gpsNanoSeconds = (INT4)floor((fmod(cur_epoch,1.0)*1.e9));
    
        baryinput2.tgps.gpsSeconds = (INT4)floor(t2);
        baryinput2.tgps.gpsNanoSeconds = (INT4)floor((fmod(t2,1.0)*1.e9));
    
        /*the barycentre functions are needed to calc the inputs for the correction to fcoarse, namely emit, earth and baryinput*/
        LAL_CALL( LALBarycenterEarth(&status, &earth, &baryinput.tgps, edat), &status );
        LAL_CALL( LALBarycenter(&status, &emit, &baryinput, &earth), &status );
        
        LAL_CALL( LALBarycenterEarth(&status, &earth2, &baryinput2.tgps, edat), &status );
        LAL_CALL( LALBarycenter(&status, &emit2, &baryinput2, &earth2), &status );
    
        /* I need to calc the correction to the freq for the doppler shifts, the correction is df, from line 1074 heterdyne_pulsar.  deltaT is T_emission in TDB - T_arrrival in GPS + light travel time to SSB.  we are working out delta(delatT) over 1 second, so do not bother with the divide by one bit.*/
        df = freq*(emit2.deltaT - emit.deltaT);
        fprintf(stderr,"df: %f,\t", df);

        /*Calc maximum possible df and then subtract applied df from it, use the remaining df to plot range over which f will wander.*/
        max_df=freq*(( (29.783e3*cos(ecliptic_lat))+(465*cos(pulsarParams.dec)) )/3.0e8);/*max doppler shift, from speed of earth in plane of direction to source over c.*/
        fprintf(stderr,"max df: %f\tbeta: %e\n", max_df, ecliptic_lat);
        maxf=freq+max_df;
        minf=freq-max_df;

        finalFreq=freq+df;
        /*df = fcoarse*(emit2.deltaT - emit.deltaT + binOutput2.deltaT - binOutput.deltaT);*//*use when have binary calcs in here also.*/
        fprintf(fp5,"%f\t%f\t%f\t%f\t%f\n", freq, df, minf, finalFreq, maxf);
        fprintf(stderr,"crab freq calc, i:%d,  minf:%f,  f:%f,  maxf:%f\n", i, minf, finalFreq, maxf);

        /*----------------------------------------------------------------------------------------------------------------*/
    }
    fclose(fp5);
    fprintf(stderr,"end of crab stuff\n");
    
    /*Free up any memory allocated in crab section*/
    XLALFree(edat);
    
    }
    #endif

    /*fprintf(stderr,"end of spec_avg 1\n");*/

    /*=======================================================================================================================*/
    /*=======================================================================================================================*/


    /*release a;; the allocaeted memory*/
    LALCHARDestroyVector(&status, &timestamp);
    LALCHARDestroyVector(&status, &year_date);
    LALDestroySFTVector (&status, &sft_vect );

    /*fprintf(stderr,"end of spec_avg 2\n");*/

    if (timeavg != NULL) XLALFree(timeavg);

    /*fprintf(stderr,"end of spec_avg 3\n");*/

    LAL_CALL(LALDestroyUserVars(&status), &status);

    /*fprintf(stderr,"end of spec_avg 4\n");*/
    /*close all the files, spec_avg.c is done, all info written to the files.*/
    fclose(fp);
    fclose(fp2);
    fclose(fp3);
    fclose(fp4);

    fprintf(stderr,"end of spec_avg\n");

    return(0);


}
int
main( void )
{
  static LALStatus status;

  char eEphFileBad[] = TEST_DATA_DIR "earth47.dat";
  char eEphFile[] = TEST_DATA_DIR "earth98.dat";
  char sEphFile[] = TEST_DATA_DIR "sun98.dat";

  /* Checking response if data files not present */
  EphemerisData edat;
  edat.ephiles.earthEphemeris = eEphFileBad;
  edat.ephiles.sunEphemeris   = sEphFile;
  LALInitBarycenter(&status, &edat);
  if ( status.statusCode != LALINITBARYCENTERH_EOPEN)
    {
      XLALPrintError( "Got error code %d and message '%s', but expected error code %d\n", status.statusCode, status.statusDescription, LALINITBARYCENTERH_EOPEN);
      return LALBARYCENTERTESTC_EOPEN;
    }
  else
    {
      // XLALPrintError ("==================== this error is as expected and OK!! ==================== \n");
      xlalErrno = 0;
    }

  /* Now inputting kosher ephemeris. files and leap sec, to illustrate
   * proper usage. The real, serious TEST of the code is a script written
   * by Rejean Dupuis comparing LALBarycenter to TEMPO for thousands
   * of source positions and times.
   */
  edat.ephiles.earthEphemeris = eEphFile;
  edat.ephiles.sunEphemeris = sEphFile;
  LALInitBarycenter(&status, &edat);
  if ( status.statusCode ) {
    XLALPrintError ("LALInitBarycenter() failed with code %d\n", status.statusCode);
    return XLAL_EFAILED;
  }

  /* ===== now test equivalence of new XLALInitBarycenter() function ========== */
  EphemerisData *edat_xlal;
  if ( ( edat_xlal = XLALInitBarycenter ( eEphFile, sEphFile )) == NULL ) {
    XLALPrintError ("Something failed in XLALInitBarycenter(), errno =%d\n", xlalErrno );
    return XLAL_EFAILED;
  }
  if ( compare_ephemeris ( &edat, edat_xlal ) != XLAL_SUCCESS ) {
    XLALPrintError ("Equivalence test failed between XLALInitEphemeris() and LALInitEphemeris()\n" );
    return XLAL_EFAILED;
  }
  XLALDestroyEphemerisData ( edat_xlal );

  /* ========================================================================== */


 /* The routines using LALBarycenter package, the code above, leading
    up LALInitBarycenter call, should be near top of main. The idea is
    that ephemeris data is read into RAM once, at the beginning.

    NOTE that the only part of the piece of the LALDetector structure
    baryinput.site that has to be filled in by the driver code is
    the 3-vector: baryinput.site.location[] .

    NOTE that the driver code that calls LALInitBarycenter must
    LALFree(edat->ephemE) and LALFree(edat->ephemS).
    The driver code that calls LALBarycenter must LALFree(edat).
 */

  /* Now getting coords for detector */
  LALDetector cachedDetector;
  cachedDetector = lalCachedDetectors[LALDetectorIndexGEO600DIFF];

  BarycenterInput XLAL_INIT_DECL(baryinput);
  baryinput.site.location[0]=cachedDetector.location[0]/LAL_C_SI;
  baryinput.site.location[1]=cachedDetector.location[1]/LAL_C_SI;
  baryinput.site.location[2]=cachedDetector.location[2]/LAL_C_SI;

  EarthState earth;
  EarthState earth_xlal;
  EmissionTime  emit, emit_xlal, emit_opt;

  /* ----- Checking error messages when the timestamp is not within the 1-yr ephemeris files */
  LIGOTimeGPS tGPS = {t1998+5e7, 0 };
  LALBarycenterEarth ( &status, &earth, &tGPS, &edat );
  if ( status.statusCode == 0 ) {
    XLALPrintError ( "LALBarycenterEarth() succeeded but expected to get error\n");
    return LALBARYCENTERTESTC_EOUTOFRANGEE;
  } else {
    XLALPrintError ("==================== this error is as expected and OK!! ==================== \n");
    xlalErrno = 0;
  }

  /* next try calling for bad choice of RA,DEC (e.g., something sensible in degrees, but radians)*/
  tGPS.gpsSeconds = t1998+3600;
  LALBarycenterEarth ( &status, &earth, &tGPS, &edat );

  baryinput.alpha= 120;
  baryinput.delta = 60;
  baryinput.dInv = 0;

  LALBarycenter ( &status, &emit, &baryinput, &earth );
  if ( status.statusCode == 0 ) {
    XLALPrintError( "LALBarycenter() succeeded but expected to get error\n" );
    return LALBARYCENTERTESTC_EBADSOURCEPOS;
  } else {
    XLALPrintError ("==================== this error is as expected and OK!! ==================== \n");
    xlalErrno = 0;
  }

  /* ---------- Now running program w/o errors, to illustrate proper use. ---------- */
  EmissionTime XLAL_INIT_DECL(maxDiff);
  EmissionTime XLAL_INIT_DECL(maxDiffOpt);
  REAL8 tic, toc;
  UINT4 NRepeat = 1;
  UINT4 counter = 0;
  REAL8 tau_lal = 0, tau_xlal = 0, tau_opt = 0;
  BarycenterBuffer *buffer = NULL;

  unsigned int seed = XLALGetTimeOfDay();
  srand ( seed );

  /* Outer loop over different sky positions */
  for ( UINT4 k=0; k < 300; k++)
    {
      baryinput.alpha = ( 1.0 * rand() / RAND_MAX ) * LAL_TWOPI;	// in [0, 2pi]
      baryinput.delta = ( 1.0 * rand() / RAND_MAX ) * LAL_PI - LAL_PI_2;// in [-pi/2, pi/2]
      baryinput.dInv = 0.e0;

      /* inner loop over pulse arrival times */
      for ( UINT4 i=0; i < 100; i++ )
        {
          REAL8 tPulse = t1998 + ( 1.0 * rand() / RAND_MAX ) * LAL_YRSID_SI;	// t in [1998, 1999]
          XLALGPSSetREAL8( &tGPS, tPulse );
          baryinput.tgps = tGPS;

          /* ----- old LAL interface ---------- */
          LALBarycenterEarth ( &status, &earth, &tGPS, &edat);
          if ( status.statusCode ) {
            XLALPrintError ("LALBarycenterEarth() failed with code %d\n", status.statusCode);
            return XLAL_EFAILED;
          }

          tic = XLALGetTimeOfDay();
          for ( UINT4 l = 0; l < NRepeat; l++ )
            LALBarycenter ( &status, &emit, &baryinput, &earth );
          toc = XLALGetTimeOfDay();
          tau_lal += ( toc - tic ) / NRepeat;
          if ( status.statusCode ) {
            XLALPrintError ("LALBarycenter() failed with code %d\n", status.statusCode);
            return XLAL_EFAILED;
          }

          /* ----- new XLAL interface ---------- */
          XLAL_CHECK ( XLALBarycenterEarth ( &earth_xlal, &tGPS, &edat ) == XLAL_SUCCESS, XLAL_EFAILED );
          tic = XLALGetTimeOfDay();
          for ( UINT4 l = 0; l < NRepeat; l ++ )
            XLAL_CHECK ( XLALBarycenter ( &emit_xlal, &baryinput, &earth_xlal ) == XLAL_SUCCESS, XLAL_EFAILED );
          toc = XLALGetTimeOfDay();
          tau_xlal += ( toc - tic ) / NRepeat;

          /* collect maximal deviations over all struct-fields of 'emit' */
          EmissionTime thisDiff;
          diffEmissionTime ( &thisDiff, &emit, &emit_xlal );
          absmaxEmissionTime ( &maxDiff, &maxDiff, &thisDiff );

          /* ----- optimized XLAL version with buffering ---------- */
          tic = XLALGetTimeOfDay();
          for ( UINT4 l = 0; l < NRepeat; l ++ )
            XLAL_CHECK ( XLALBarycenterOpt ( &emit_opt, &baryinput, &earth_xlal, &buffer ) == XLAL_SUCCESS, XLAL_EFAILED );
          toc = XLALGetTimeOfDay();
          tau_opt += ( toc - tic ) / NRepeat;

          /* collect maximal deviations over all struct-fields of 'emit' */
          diffEmissionTime ( &thisDiff, &emit, &emit_opt );
          absmaxEmissionTime ( &maxDiffOpt, &maxDiffOpt, &thisDiff );

          counter ++;
        } /* for i */

    } /* for k */

  XLALFree ( buffer );
  buffer = NULL;

  /* ----- check differences in results ---------- */
  REAL8 tolerance = 1e-9;	// in seconds: can't go beyond nanosecond precision due to GPS limitation
  REAL8 maxEmitDiff = maxErrInEmissionTime ( &maxDiff );
  REAL8 maxEmitDiffOpt = maxErrInEmissionTime ( &maxDiffOpt );
  XLALPrintInfo ( "Max error (in seconds) between LALBarycenter() and XLALBarycenter()     = %g s (tolerance = %g s)\n", maxEmitDiff, tolerance );
  XLAL_CHECK ( maxEmitDiff < tolerance, XLAL_EFAILED,
               "Max error (in seconds) between LALBarycenter() and XLALBarycenter()  = %g s, exceeding tolerance of %g s\n", maxEmitDiff, tolerance );

  XLALPrintInfo ( "Max error (in seconds) between LALBarycenter() and XLALBarycenterOpt()  = %g s (tolerance = %g s)\n", maxEmitDiffOpt, tolerance );
  XLAL_CHECK ( maxEmitDiffOpt < tolerance, XLAL_EFAILED,
               "Max error (in seconds) between LALBarycenter() and XLALBarycenterOpt()  = %g s, exceeding tolerance of %g s\n",
               maxEmitDiffOpt, tolerance );
  printf ( "%g	%g %d %d %g	%g %g %g	%g %g %g\n",
           maxEmitDiffOpt,
           maxDiffOpt.deltaT, maxDiffOpt.te.gpsSeconds, maxDiffOpt.te.gpsNanoSeconds, maxDiffOpt.tDot,
           maxDiffOpt.rDetector[0], maxDiffOpt.rDetector[1], maxDiffOpt.rDetector[2],
           maxDiffOpt.vDetector[0], maxDiffOpt.vDetector[1], maxDiffOpt.vDetector[2]
           );

  /* ----- output runtimes ---------- */
  XLALPrintError ("Runtimes per function-call, averaged over %g calls\n", 1.0 * NRepeat * counter );
  XLALPrintError ("LALBarycenter() 	%g s\n", tau_lal / counter );
  XLALPrintError ("XLALBarycenter()	%g s (= %.1f %%)\n", tau_xlal / counter, - 100 * (tau_lal - tau_xlal ) / tau_lal );
  XLALPrintError ("XLALBarycenterOpt()	%g s (= %.1f %%)\n", tau_opt / counter,  - 100 * (tau_lal - tau_opt ) / tau_lal );

  /* ===== test XLALRestrictEphemerisData() ===== */
  XLALPrintInfo("\n\nTesting XLALRestrictEphemerisData() ... ");
  {
    XLAL_CHECK( edat.nentriesS >= 100, XLAL_EFAILED );
    const INT4 orig_nentriesS = edat.nentriesS;
    for (INT4 i = 1; i <= 4; ++i) {
      REAL8 start, end;
      LIGOTimeGPS startGPS, endGPS;
      INT4 diff_nentriesS;

      start = edat.ephemS[2*i].gps;
      end = edat.ephemS[edat.nentriesS - 1 - 3*i].gps;
      XLAL_CHECK( XLALGPSSetREAL8(&startGPS, start) != NULL, XLAL_EFUNC );
      XLAL_CHECK( XLALGPSSetREAL8(&endGPS, end) != NULL, XLAL_EFUNC );
      XLAL_CHECK( XLALRestrictEphemerisData(&edat, &startGPS, &endGPS) == XLAL_SUCCESS, XLAL_EFUNC );
      XLAL_CHECK( edat.ephemS[0].gps == start, XLAL_EFAILED, "\nTest S%dA FAILED: %0.9f != start %0.9f\n", i, edat.ephemS[0].gps, start );
      XLAL_CHECK( edat.ephemS[edat.nentriesS - 1].gps == end, XLAL_EFAILED, "\nTest S%dA FAILED: end %0.9f != %0.9f\n", i, edat.ephemS[edat.nentriesS - 1].gps, end );
      diff_nentriesS = ((i*i + i) * 5) / 2 + 2*(i-1);
      XLAL_CHECK( orig_nentriesS - edat.nentriesS == diff_nentriesS, XLAL_EFAILED, "\nTest S%dA FAILED: nentries %d != %d\n", i, orig_nentriesS - edat.nentriesS, diff_nentriesS );

      XLAL_CHECK( XLALGPSSetREAL8(&startGPS, start + 0.5*edat.dtStable) != NULL, XLAL_EFUNC );
      XLAL_CHECK( XLALGPSSetREAL8(&endGPS, end - 0.5*edat.dtStable) != NULL, XLAL_EFUNC );
      start = edat.ephemS[0].gps;
      end = edat.ephemS[edat.nentriesS - 1].gps;
      XLAL_CHECK( XLALRestrictEphemerisData(&edat, &startGPS, &endGPS) == XLAL_SUCCESS, XLAL_EFUNC );
      XLAL_CHECK( edat.ephemS[0].gps == start, XLAL_EFAILED, "\nTest S%dB FAILED: start %0.9f != %0.9f\n", i, edat.ephemS[0].gps, start );
      XLAL_CHECK( edat.ephemS[edat.nentriesS - 1].gps == end, XLAL_EFAILED, "\nTest S%dB FAILED: end %0.9f != %0.9f\n", i, edat.ephemS[edat.nentriesS - 1].gps, end );
      diff_nentriesS = ((i*i + i) * 5) / 2 + 2*(i-1);
      XLAL_CHECK( orig_nentriesS - edat.nentriesS == diff_nentriesS, XLAL_EFAILED, "\nTest S%dB FAILED: nentries %d != %d\n", i, orig_nentriesS - edat.nentriesS, diff_nentriesS );

      XLAL_CHECK( XLALGPSSetREAL8(&startGPS, start + 1.5*edat.dtStable) != NULL, XLAL_EFUNC );
      XLAL_CHECK( XLALGPSSetREAL8(&endGPS, end - 1.5*edat.dtStable) != NULL, XLAL_EFUNC );
      start = edat.ephemS[1].gps;
      end = edat.ephemS[edat.nentriesS - 2].gps;
      XLAL_CHECK( XLALRestrictEphemerisData(&edat, &startGPS, &endGPS) == XLAL_SUCCESS, XLAL_EFUNC );
      XLAL_CHECK( edat.ephemS[0].gps == start, XLAL_EFAILED, "\nTest S%dC FAILED: start %0.9f != %0.9f\n", i, edat.ephemS[0].gps, start );
      XLAL_CHECK( edat.ephemS[edat.nentriesS - 1].gps == end, XLAL_EFAILED, "\nTest S%dC FAILED: end %0.9f != %0.9f\n", i, edat.ephemS[edat.nentriesS - 1].gps, end );
      diff_nentriesS = ((i*i + i) * 5) / 2 + 2*i;
      XLAL_CHECK( orig_nentriesS - edat.nentriesS == diff_nentriesS, XLAL_EFAILED, "\nTest S%dC FAILED: nentries %d != %d\n", i, orig_nentriesS - edat.nentriesS, diff_nentriesS );
    }

    XLAL_CHECK( edat.nentriesE >= 100, XLAL_EFAILED );
    const INT4 orig_nentriesE = edat.nentriesE;
    for (INT4 i = 1; i <= 4; ++i) {
      REAL8 start, end;
      LIGOTimeGPS startGPS, endGPS;
      INT4 diff_nentriesE;

      start = edat.ephemE[2*i].gps;
      end = edat.ephemE[edat.nentriesE - 1 - 3*i].gps;
      XLAL_CHECK( XLALGPSSetREAL8(&startGPS, start) != NULL, XLAL_EFUNC );
      XLAL_CHECK( XLALGPSSetREAL8(&endGPS, end) != NULL, XLAL_EFUNC );
      XLAL_CHECK( XLALRestrictEphemerisData(&edat, &startGPS, &endGPS) == XLAL_SUCCESS, XLAL_EFUNC );
      XLAL_CHECK( edat.ephemE[0].gps == start, XLAL_EFAILED, "\nTest E%dA FAILED: %0.9f != start %0.9f\n", i, edat.ephemE[0].gps, start );
      XLAL_CHECK( edat.ephemE[edat.nentriesE - 1].gps == end, XLAL_EFAILED, "\nTest E%dA FAILED: end %0.9f != %0.9f\n", i, edat.ephemE[edat.nentriesE - 1].gps, end );
      diff_nentriesE = ((i*i + i) * 5) / 2 + 2*(i-1);
      XLAL_CHECK( orig_nentriesE - edat.nentriesE == diff_nentriesE, XLAL_EFAILED, "\nTest E%dA FAILED: nentries %d != %d\n", i, orig_nentriesE - edat.nentriesE, diff_nentriesE );

      XLAL_CHECK( XLALGPSSetREAL8(&startGPS, start + 0.5*edat.dtEtable) != NULL, XLAL_EFUNC );
      XLAL_CHECK( XLALGPSSetREAL8(&endGPS, end - 0.5*edat.dtEtable) != NULL, XLAL_EFUNC );
      start = edat.ephemE[0].gps;
      end = edat.ephemE[edat.nentriesE - 1].gps;
      XLAL_CHECK( XLALRestrictEphemerisData(&edat, &startGPS, &endGPS) == XLAL_SUCCESS, XLAL_EFUNC );
      XLAL_CHECK( edat.ephemE[0].gps == start, XLAL_EFAILED, "\nTest E%dB FAILED: start %0.9f != %0.9f\n", i, edat.ephemE[0].gps, start );
      XLAL_CHECK( edat.ephemE[edat.nentriesE - 1].gps == end, XLAL_EFAILED, "\nTest E%dB FAILED: end %0.9f != %0.9f\n", i, edat.ephemE[edat.nentriesE - 1].gps, end );
      diff_nentriesE = ((i*i + i) * 5) / 2 + 2*(i-1);
      XLAL_CHECK( orig_nentriesE - edat.nentriesE == diff_nentriesE, XLAL_EFAILED, "\nTest E%dB FAILED: nentries %d != %d\n", i, orig_nentriesE - edat.nentriesE, diff_nentriesE );

      XLAL_CHECK( XLALGPSSetREAL8(&startGPS, start + 1.5*edat.dtEtable) != NULL, XLAL_EFUNC );
      XLAL_CHECK( XLALGPSSetREAL8(&endGPS, end - 1.5*edat.dtEtable) != NULL, XLAL_EFUNC );
      start = edat.ephemE[1].gps;
      end = edat.ephemE[edat.nentriesE - 2].gps;
      XLAL_CHECK( XLALRestrictEphemerisData(&edat, &startGPS, &endGPS) == XLAL_SUCCESS, XLAL_EFUNC );
      XLAL_CHECK( edat.ephemE[0].gps == start, XLAL_EFAILED, "\nTest E%dC FAILED: start %0.9f != %0.9f\n", i, edat.ephemE[0].gps, start );
      XLAL_CHECK( edat.ephemE[edat.nentriesE - 1].gps == end, XLAL_EFAILED, "\nTest E%dC FAILED: end %0.9f != %0.9f\n", i, edat.ephemE[edat.nentriesE - 1].gps, end );
      diff_nentriesE = ((i*i + i) * 5) / 2 + 2*i;
      XLAL_CHECK( orig_nentriesE - edat.nentriesE == diff_nentriesE, XLAL_EFAILED, "\nTest E%dC FAILED: nentries %d != %d\n", i, orig_nentriesE - edat.nentriesE, diff_nentriesE );
    }
  }
  XLALPrintInfo("PASSED\n\n");

  LALFree(edat.ephemE);
  LALFree(edat.ephemS);

  LALCheckMemoryLeaks();

  XLALPrintError ("==> OK. All tests successful!\n\n");

  return 0;

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

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

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

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

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

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

  INITSTATUS(stat);
  ATTATCHSTATUSPTR( stat );

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /* Compute table of responses. */
    LALComputeDetAMResponseSeries( stat->statusPtr, &polResponse,
                                   &input, &params );
    BEGINFAIL( stat ) {
      TRY( LALSDestroyVector( stat->statusPtr,
                              &( polResponse.pPlus->data ) ), stat );
      TRY( LALSDestroyVector( stat->statusPtr,
                              &( polResponse.pCross->data ) ), stat );
      TRY( LALSDestroyVector( stat->statusPtr,
                              &( polResponse.pScalar->data ) ), stat );
      LALFree( polResponse.pPlus );
      LALFree( polResponse.pCross );
      LALFree( polResponse.pScalar );
      TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
    } ENDFAIL( stat );
  } else {
Exemplo n.º 8
0
/**
 * Given a set of input parameters defining a source location in the sky and
 * the binary system in which the source resides, this routine returns the phase
 * model coefficients \f$A_{s\alpha}\f$ and \f$B_{s\alpha}\f$ which are needed to
 * correctly account for the phase variance of a signal over time. The
 * \c CSBParams parameter structure contains relevant information
 * for this routine to properly run.  In particular, it contains an array of
 * timestamps in \c LIGOTimeGPS format, which are the GPS times of the first
 * data from each SFT.  The \c input is an \c INT4 variable
 * \c iSkyCoh, which is the index of the sky location under consideration.  For
 * each sky location and set of orbital parameters, this code needs to be run
 * once; the necessary phase model
 * coefficients are calculated, and can then be applied to the relevant spindown
 * parameter sets one is using in their search.
 *
 * ### Algorithm ###
 *
 * The routine uses a simplistic nested for-loop structure.  The outer loop is
 * over the number of SFTs in the observation timescale; this accounts for the
 * temporal variability of the phase model coefficients.  The inner loop is over
 * the number of spindown parameters in one set.  Inside the inner loop, the
 * values are calculated using the analytical formulae given in the
 * \ref ComputeSkyBinary.h documentation.
 */
void LALComputeSkyBinary (LALStatus	*status,
                          REAL8 	*skyConst,
                          INT8 		iSkyCoh,
                          CSBParams 	*params)
{

	INT4	m, n, nP;
	REAL8	dTbary;
	REAL8   dTbarySP;
	REAL8   dTperi;
	REAL8   dTcoord;
	REAL8   Tdotbin;
	REAL8   basedTperi;
	DFindRootIn input;
	REAL8 tr0;
	REAL8 acc;

 INITSTATUS(status);
 ATTATCHSTATUSPTR(status);

/* Check for non-negativity of sky positions in SkyCoh[] */
 ASSERT(iSkyCoh>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);

/* Check to make sure sky positions are loaded */
 ASSERT(params->skyPos!=NULL, status, COMPUTESKYBINARYH_ENULL, COMPUTESKYBINARYH_MSGENULL);
 ASSERT(params->skyPos!=NULL, status, COMPUTESKYBINARYH_ENULL, COMPUTESKYBINARYH_MSGENULL);

/* Check to make sure parameters are loaded and reasonable */
 ASSERT(params->spinDwnOrder>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
 ASSERT(params->mObsSFT>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
 ASSERT(params->tSFT>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);

/* Check to make sure orbital parameters are loaded and reasonable */
 ASSERT(params->SemiMajorAxis>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
 ASSERT(params->OrbitalPeriod>0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
 ASSERT(params->OrbitalEccentricity>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
 ASSERT((params->ArgPeriapse>=0)&&(params->ArgPeriapse<=LAL_TWOPI), status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
 ASSERT(params->TperiapseSSB.gpsSeconds>=0, status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);
 ASSERT((params->TperiapseSSB.gpsNanoSeconds>=0)&&(params->TperiapseSSB.gpsNanoSeconds<1e9), status, COMPUTESKYBINARYH_ENEGA, COMPUTESKYBINARYH_MSGENEGA);


 /* Here we redefine the orbital variables for ease of use */
 a=params->SemiMajorAxis;  /* This is the projected semi-major axis of the orbit normalised by the speed of light */
 Period=params->OrbitalPeriod;  /* This is the period of the orbit in seconds */
 ecc=params->OrbitalEccentricity;  /* This is the eccentricity of the orbit */
 parg=params->ArgPeriapse;  /* This is the argument of periapse defining the angular location of the source at periapsis */
                            /* measured relative to the ascending node */
 Tperi.gpsSeconds=params->TperiapseSSB.gpsSeconds;  /* This is the GPS time as measured in the SSB of the observed */
 Tperi.gpsNanoSeconds=params->TperiapseSSB.gpsNanoSeconds;  /* periapse passage of the source */

 /* Here we check that the GPS timestamps are greater than zero */
 for(n=0;n<params->mObsSFT;n++)
   {
     ASSERT(params->tGPS[n].gpsSeconds>=0, status, COMPUTESKYBINARYH_ENEGA, 	COMPUTESKYBINARYH_MSGENEGA);
   }

 /* Check to make sure pointer to output is not NULL */
 ASSERT(skyConst!=NULL, status, COMPUTESKYBINARYH_ENNUL, COMPUTESKYBINARYH_MSGENNUL);

 /* prepare params input sky position structure */
 params->baryinput->alpha=params->skyPos[iSkyCoh];
 params->baryinput->delta=params->skyPos[iSkyCoh+1];

 /* calculate phase model coefficients p and q which are defined in the ComputeSkyBinary header LAL documentation  */
 p=((LAL_TWOPI/(Period*1.0))*a*sqrt(1-(ecc*ecc))*cos(parg))-ecc;
 q=(LAL_TWOPI/(Period*1.0))*a*sin(parg);

 /* Calculate the required accuracy for the root finding procedure in the main loop */
 acc=LAL_TWOPI*(REAL8)ACC/Period;   /* ACC is defined in ComputeSkyBinary.h and represents the required */
                                    /* timing precision in seconds (roughly)*/

 /* begin loop over SFT's */
 for (n=0; n<params->mObsSFT; n++)
   {
     /* Calculate the detector time at the mid point of current SFT ( T(i)+(tsft/2) ) using LAL functions */
     params->baryinput->tgps = params->tGPS[n];
     XLALGPSAdd(&(params->baryinput->tgps), params->tSFT / 2.0);

     /* Convert this mid point detector time into barycentric time (SSB) */
     LALBarycenterEarth(status->statusPtr, params->earth, &(params->baryinput->tgps), params->edat);
     LALBarycenter(status->statusPtr, params->emit, params->baryinput, params->earth);

     /* Calculate the time difference since the observed periapse passage in barycentric time (SSB). */
     /* This time difference, when converted to REAL8, should lose no precision unless we are dealing */
     /* with periods >~ 1 Year */
     dTbary = XLALGPSDiff(&(params->emit->te),&Tperi);

     /* Calculate the time since the last periapse passage ( < Single Period (SP) ) */
     dTbarySP=Period*((dTbary/(1.0*Period))-(REAL8)floor(dTbary/(1.0*Period)));

     /* Calculate number of full orbits completed since the input observed periapse passage */
     nP=(INT4)floor(dTbary/(1.0*Period));

     /* begin root finding procedure */
     tr0 = dTbarySP;        /* we wish to find the value of the eccentric amomoly E coresponding to the time */
                            /* since the last periapse passage */
     input.function = Ft;   /* This is the name of the function we must solve to find E */
     input.xmin = 0.0;      /* We know that E will be found between 0 and 2PI */
     input.xmax = LAL_TWOPI;
     input.xacc = acc;      /* The accuracy of the root finding procedure */

     /* expand domain until a root is bracketed */
     LALDBracketRoot(status->statusPtr,&input,&tr0);

     /* bisect domain to find eccentric anomoly E corresponding to the current midpoint timestamp */
     LALDBisectionFindRoot(status->statusPtr,&E,&input,&tr0);

     /* Now we calculate the time interval since the input periapse passage as measured at the source */
     dTperi=(Period/LAL_TWOPI)*(E-(ecc*sin(E)))+((REAL8)nP*Period);

     /* The following quantity is the derivative of the time coordinate measured at the source with */
     /* respect to the time coordinate measured in the SSB */
     dTcoord=(1.0-(ecc*cos(E)))/(1.0+(p*cos(E))-(q*sin(E)));

     /* The following quantity is the derivitive of the time coordinate measured in the SSB with */
     /* respect to the time coordinate measured at the chosen detector.  It was calculated via the */
     /* last call to LALBarycenter. */
     Tdotbin = params->emit->tDot*dTcoord;

     /* Loop over all spin down orders plus 0th order (f0) */
     /* In this loop we calculate the SkyConstants defined in the documentation as A_{s,alpha} and B_{s,alpha} */
     for (m=0; m<params->spinDwnOrder+1; m++)
       {
	 /* raise the quantity dTperi to the power m */
	 basedTperi = pow(dTperi, (REAL8)m);
	 /* Calculate A coefficients */
	 skyConst[2*n*(params->spinDwnOrder+1)+2*(INT4)m]=1.0/((REAL8)m+1.0)*basedTperi*dTperi-0.5*params->tSFT*basedTperi*Tdotbin;
	 /* Calculate B coefficients */
	 skyConst[2*n*(params->spinDwnOrder+1)+2*(INT4)m+1]= params->tSFT*basedTperi*Tdotbin;
       }
   }

 /* Normal Exit */
 DETATCHSTATUSPTR(status);
 RETURN(status);
}