LALHashTbl *XLALHashTblCreate2(
  LALHashTblDtorFcn dtor,
  LALHashTblHashParamFcn hash,
  void *hash_param,
  LALHashTblCmpParamFcn cmp,
  void *cmp_param
  )
{

  /* Check input */
  XLAL_CHECK_NULL( hash != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( cmp != NULL, XLAL_EFAULT );

  /* Allocate memory for hash table struct */
  LALHashTbl *ht = XLALCalloc( 1, sizeof( *ht ) );
  XLAL_CHECK_NULL( ht != NULL, XLAL_ENOMEM );

  /* Set hash table struct parameters */
  ht->dtor = dtor;
  ht->hash = hash;
  ht->hash_param = hash_param;
  ht->cmp = cmp;
  ht->cmp_param = cmp_param;

  return ht;

}
/**
 * Append the given PulsarParamsVector 'add' to the vector 'list' ( which can be NULL), return resulting list
 * with new elements 'add' appended at the end of 'list'.
 */
PulsarParamsVector *
XLALPulsarParamsVectorAppend ( PulsarParamsVector *list, const PulsarParamsVector *add )
{
  XLAL_CHECK_NULL ( add != NULL, XLAL_EINVAL );

  PulsarParamsVector *ret;
  if ( list == NULL )
    {
      XLAL_CHECK_NULL ( (ret = XLALCalloc ( 1, sizeof(*ret))) != NULL, XLAL_ENOMEM );
    }
  else
    {
      ret = list;
    }

  UINT4 oldlen = ret->length;
  UINT4 addlen = add->length;
  UINT4 newlen = oldlen + addlen;
  ret->length = newlen;
  XLAL_CHECK_NULL ( (ret->data = XLALRealloc ( ret->data, newlen * sizeof(ret->data[0]) )) != NULL, XLAL_ENOMEM );
  memcpy ( ret->data + oldlen, add->data, addlen * sizeof(ret->data[0]) );
  // we have to properly copy the 'name' string fields
  for ( UINT4 i = 0; i < addlen; i ++ )
    {
      XLAL_CHECK_NULL ( (ret->data[oldlen + i].name = XLALStringDuplicate ( add->data[i].name )) != NULL, XLAL_EFUNC );
    }

  return ret;

} // XLALPulsarParamsVectorAppend()
Beispiel #3
0
/**
 * Get the 'detector state' (ie detector-tensor, position, velocity, etc) for the given
 * multi-vector of SFTs, shifted by a common time-shift \a tOffset.
 *
 * \a tOffset allows one to easily use the midpoints of SFT-timestamps, for example.
 *
 */
MultiDetectorStateSeries *
XLALGetMultiDetectorStatesFromMultiSFTs(
  const MultiSFTVector *multiSFTs,		/**< [in] multi-IFO SFTs */
  const EphemerisData *edat,			/**< [in] ephemeris data */
  REAL8 tOffset					/**< [in] shift all timestamps by this amount */
  )
{

  // Check input
  XLAL_CHECK_NULL( multiSFTs != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( edat != NULL, XLAL_EFAULT );

  // XLALGetMultiDetectorStates() wants detector-array and timestamps-vectors directly,
  // instead of a multi-SFT vector. We therefore need to extract this info from the
  // multi-SFT vector first
  MultiLALDetector multiIFO;
  XLAL_CHECK_NULL( XLALMultiLALDetectorFromMultiSFTs ( &multiIFO, multiSFTs ) == XLAL_SUCCESS, XLAL_EFUNC );
  MultiLIGOTimeGPSVector *multiTS;
  XLAL_CHECK_NULL( ( multiTS = XLALExtractMultiTimestampsFromSFTs ( multiSFTs )) != NULL, XLAL_EFUNC );

  // call XLALGetMultiDetectorStates()
  MultiDetectorStateSeries *ret = NULL;
  XLAL_CHECK_NULL( ( ret = XLALGetMultiDetectorStates( multiTS, &multiIFO, edat, tOffset )) != NULL, XLAL_EFUNC );

  // free temporary mem
  XLALDestroyMultiTimestamps ( multiTS );

  return ret;

} /* XLALGetMultiDetectorStatesFromMultiSFTs() */
// convert 'old-style' REAL8Vector metric into a new 'gsl_matrix' type
// also converts 'old-style' spindown f1 = f1dot / Freq, back into 'f1dot' coordinates
static gsl_matrix *
convert_old_metric_2_new ( const REAL8Vector *m0, REAL8 Freq )
{
  XLAL_CHECK_NULL ( m0, XLAL_EINVAL, "Invalid NULL input 'm0'\n");
  XLAL_CHECK_NULL ( Freq > 0, XLAL_EINVAL, "Invalid input Freq = %g must be > 0\n", Freq );
  XLAL_CHECK_NULL ( m0->length > 0, XLAL_EINVAL, "Invalid zero-length metric input 'm0'\n");

  UINT4 len = m0->length;
  REAL4 dim0 = -0.5 + sqrt ( 2 * len + 0.25 );

  UINT4 dim = round ( dim0 );
  XLAL_CHECK_NULL ( fabs (dim0 - 1.0 * dim) < 1e-4, XLAL_EDOM, "Vector length '%d' invalid: must be of the form (n^2 + n)/2, where n is a positive integer\n", len );

  gsl_matrix *gij = gsl_matrix_calloc ( dim, dim );
  XLAL_CHECK_NULL ( gij != NULL, XLAL_ENOMEM, "gsl_matrix_calloc(%d,%d) failed\n", dim, dim );

  for ( UINT4 i = 0; i < dim; i ++ )
    {
      for ( UINT4 j = i; j < dim; j ++ )
        {
          REAL8 el_ij = m0->data[ PMETRIC_INDEX ( i, j ) ];
          if ( i == 3 ) el_ij /= Freq;
          if ( j == 3 ) el_ij /= Freq;
          gsl_matrix_set ( gij, i, j, el_ij );
          gsl_matrix_set ( gij, j, i, el_ij );

        } // for j = i ... dim
    } // for i < dim

  return gij;

} // convert_old_metric_2_new()
Beispiel #5
0
/**
 * Return a log-string representing the <em>complete</em> user-input.
 * <em>NOTE:</em> we only record user-variables that have been set
 * by the user.
 */
CHAR *
XLALUserVarGetLog ( UserVarLogFormat format 	/**< output format: return as config-file or command-line */
                    )
{
  XLAL_CHECK_NULL ( UVAR_vars.next != NULL, XLAL_EINVAL, "No UVAR memory allocated. Did you register any user-variables?" );
  XLAL_CHECK_NULL ( format < UVAR_LOGFMT_LAST, XLAL_EINVAL );

  CHAR *record = NULL;

  if ( format == UVAR_LOGFMT_CMDLINE ) {
    XLAL_CHECK_NULL ( (record = XLALStringAppend ( record, program_name)) != NULL, XLAL_EFUNC );
  }

  LALUserVariable *ptr = &UVAR_vars;
  while ( (ptr = ptr->next) )
    {
      if ( ! ptr->was_set ) { // skip unset variables
	continue;
      }

      CHAR *valstr;
      XLAL_CHECK_NULL ( (valstr = UserVarTypeMap [ ptr->type ].printer( ptr->varp )) != NULL, XLAL_EFUNC );

      char append[256];
      switch (format)
	{
	case UVAR_LOGFMT_CFGFILE:
	  snprintf (append, sizeof(append), "%s = %s;\n", ptr->name, valstr);
	  break;

	case UVAR_LOGFMT_CMDLINE:
	  snprintf (append, sizeof(append), " --%s=%s", ptr->name, valstr);
	  break;

	case UVAR_LOGFMT_PROCPARAMS:
	  snprintf (append, sizeof(append), "--%s = %s :%s;", ptr->name, valstr, UserVarTypeMap[ptr->type].name );
	  break;

	default:
          XLAL_ERROR_NULL ( XLAL_EINVAL, "Unknown format for recording user-input: '%i'\n", format );
	  break;
	} // switch (format)
      XLAL_LAST_ELEM(append) = 0;

      XLAL_CHECK_NULL ( (record = XLALStringAppend (record, append)) != NULL, XLAL_EFUNC );

      XLALFree (valstr);
    } // while ptr=ptr->next

  return record;

} // XLALUserVarGetLog()
Beispiel #6
0
MultiNoiseWeights *
XLALComputeConstantMultiNoiseWeightsFromNoiseFloor ( const MultiNoiseFloor *multiNoiseFloor,	/**< [in] noise floor values sqrt(S) for all detectors */
                                                     const MultiLIGOTimeGPSVector *multiTS,	/**< [in] timestamps vectors for all detectors, only needed for their lengths */
                                                     const UINT4 Tsft				/**< [in] length of SFTs in secons, needed for normalization factor Sinv_Tsft */
                                                     )
{

  /* check input parameters */
  XLAL_CHECK_NULL ( multiNoiseFloor != NULL, XLAL_EINVAL );
  XLAL_CHECK_NULL ( multiTS != NULL, XLAL_EINVAL );
  UINT4 numDet = multiNoiseFloor->length;
  XLAL_CHECK_NULL ( numDet == multiTS->length, XLAL_EINVAL, "Inconsistent length between multiNoiseFloor (%d) and multiTimeStamps (%d) structs.\n", numDet, multiTS->length );

  /* create multi noise weights for output */
  MultiNoiseWeights *multiWeights = NULL;
  XLAL_CHECK_NULL ( (multiWeights = XLALCalloc(1, sizeof(*multiWeights))) != NULL, XLAL_ENOMEM, "Failed call to XLALCalloc ( 1, %zu )\n", sizeof(*multiWeights) );
  XLAL_CHECK_NULL ( (multiWeights->data = XLALCalloc(numDet, sizeof(*multiWeights->data))) != NULL, XLAL_ENOMEM, "Failed call to XLALCalloc ( %d, %zu )\n", numDet, sizeof(*multiWeights->data) );
  multiWeights->length = numDet;

  REAL8 sqrtSnTotal = 0;
  UINT4 numSFTsTotal = 0;
  for (UINT4 X = 0; X < numDet; X++) { /* first loop over detectors: compute total noise floor normalization */
    sqrtSnTotal  += multiTS->data[X]->length / SQ ( multiNoiseFloor->sqrtSn[X] ); /* actually summing up 1/Sn, not sqrtSn yet */
    numSFTsTotal += multiTS->data[X]->length;
  }
  sqrtSnTotal = sqrt ( numSFTsTotal / sqrtSnTotal ); /* SnTotal = harmonicMean{S_X} assuming per-detector stationarity */

  for (UINT4 X = 0; X < numDet; X++) { /* second loop over detectors: compute the weights */

    /* compute per-IFO weights */
    REAL8 noise_weight_X = SQ(sqrtSnTotal/multiNoiseFloor->sqrtSn[X]); /* w_Xalpha = S_Xalpha^-1/S^-1 = S / S_Xalpha */

    /* create k^th weights vector */
    if( ( multiWeights->data[X] = XLALCreateREAL8Vector ( multiTS->data[X]->length ) ) == NULL ) {
      /* free weights vectors created previously in loop */
      XLALDestroyMultiNoiseWeights ( multiWeights );
      XLAL_ERROR_NULL ( XLAL_EFUNC, "Failed to allocate noiseweights for IFO X = %d\n", X );
    } /* if XLALCreateREAL8Vector() failed */

    /* loop over SFT timestamps and use same weights for all */
    for ( UINT4 alpha = 0; alpha < multiTS->data[X]->length; alpha++) {
      multiWeights->data[X]->data[alpha] = noise_weight_X;
    }

  } /* for X < numDet */

  multiWeights->Sinv_Tsft = Tsft / SQ ( sqrtSnTotal );

  return multiWeights;

} /* XLALComputeConstantMultiNoiseWeightsFromNoiseFloor() */
Beispiel #7
0
/**
 * Allocate a candidateVector
 * \param [in] length Length of the candidateVector
 * \return Pointer to the allocated candidateVector
 */
candidateVector * new_candidateVector(UINT4 length)
{

   candidateVector *vector = NULL;
   XLAL_CHECK_NULL( (vector = XLALMalloc(sizeof(*vector))) != NULL, XLAL_ENOMEM );

   vector->length = length;
   vector->numofcandidates = 0;
   if (length==0) vector->data = NULL;
   else XLAL_CHECK_NULL( (vector->data = XLALMalloc( length*sizeof(*vector->data) )) != NULL, XLAL_ENOMEM );

   return vector;

} /* new_candidateVector() */
/**
 * Create *zero-initialized* PulsarParamsVector for numPulsars
 */
PulsarParamsVector *
XLALCreatePulsarParamsVector ( UINT4 numPulsars )
{
  PulsarParamsVector *ret;
  XLAL_CHECK_NULL ( ( ret = XLALCalloc ( 1, sizeof(*ret))) != NULL, XLAL_ENOMEM );

  ret->length = numPulsars;
  if ( numPulsars > 0 ) {
    XLAL_CHECK_NULL ( (ret->data = XLALCalloc ( numPulsars, sizeof(ret->data[0]))) != NULL, XLAL_ENOMEM );
  }

  return ret;

} // XLALCreatePulsarParamsVector()
FstatInputData*
XLALSetupFstat_Demod(
  MultiSFTVector **multiSFTs,
  MultiNoiseWeights **multiWeights,
  const EphemerisData *edat,
  const SSBprecision SSBprec,
  const UINT4 Dterms,
  const DemodHLType demodHL
  )
{

  // Check non-common input
  XLAL_CHECK_NULL(Dterms > 0, XLAL_EINVAL);

  // Check common input and allocate input data struct
  FstatInputData* input = SetupFstat_Common(multiSFTs, multiWeights, edat, SSBprec);
  XLAL_CHECK_NULL(input != NULL, XLAL_EFUNC);

  // Allocate demodulation input data struct
  FstatInputData_Demod *demod = XLALCalloc(1, sizeof(FstatInputData_Demod));
  XLAL_CHECK_NULL(demod != NULL, XLAL_ENOMEM);

  // Save pointer to input SFTs, set supplied pointer to NULL
  demod->multiSFTs = *multiSFTs;
  *multiSFTs = NULL;

  // Calculate the detector states from the SFTs
  {
    LALStatus status = empty_status;
    LALGetMultiDetectorStates(&status, &demod->multiDetStates, demod->multiSFTs, edat);
    if (status.statusCode) {
      XLAL_ERROR_NULL(XLAL_EFAILED, "LALGetMultiDetectorStates() failed: %s (statusCode=%i)", status.statusDescription, status.statusCode);
    }
  }

  // Set parameters to pass to ComputeFStat()
  demod->params.Dterms = Dterms;
  demod->params.SSBprec = SSBprec;
  demod->params.buffer = NULL;
  demod->params.edat = edat;
  demod->params.demodHL = demodHL;

  // Save pointer to demodulation input data
  input->demod = demod;

  return input;

} // XLALSetupFstat_Demod()
Beispiel #10
0
/**
 * Allocate a new UpperLimitVector
 * \param [in] length Length of the vector
 * \return Pointer to newly allocated UpperLimitVector
 */
UpperLimitVector * new_UpperLimitVector(UINT4 length)
{

    UpperLimitVector *vector = NULL;
    XLAL_CHECK_NULL( (vector = XLALMalloc(sizeof(*vector))) != NULL, XLAL_ENOMEM );

    vector->length = length;
    if (length==0) vector->data = NULL;
    else {
        XLAL_CHECK_NULL( (vector->data = XLALMalloc( length*sizeof(*vector->data) )) != NULL, XLAL_ENOMEM );
        for (UINT4 ii=0; ii<length; ii++) reset_UpperLimitStruct(&(vector->data[ii]));
    }

    return vector;

} /* new_UpperLimitVector() */
Beispiel #11
0
/**
 * Allocate memory for farStruct
 * \return Pointer to a farStruct
 */
farStruct * new_farStruct(void)
{
   farStruct *farstruct = NULL;
   XLAL_CHECK_NULL( (farstruct = XLALMalloc(sizeof(*farstruct))) != NULL, XLAL_ENOMEM );
   farstruct->far = 1.0;
   farstruct->topRvalues = NULL;
   return farstruct;
} /* new_farStruct() */
/** (Complex)Sinc-interpolate an input SFT to an output SFT.
 * This is a simple convenience wrapper to XLALSincInterpolateCOMPLEX8FrequencySeries()
 * for the special case of interpolating onto new SFT frequency bins
 */
SFTtype *
XLALSincInterpolateSFT ( const SFTtype *sft_in,		///< [in] input SFT
                              REAL8 f0Out,		///< [in] new start frequency
                              REAL8 dfOut,		///< [in] new frequency step-size
                              UINT4 numBinsOut,		///< [in] new number of bins
                              UINT4 Dterms		///< [in] truncate interpolation kernel sum to +-Dterms around max
                              )
{
  XLAL_CHECK_NULL ( sft_in != NULL, XLAL_EINVAL );
  XLAL_CHECK_NULL ( dfOut > 0, XLAL_EINVAL );
  XLAL_CHECK_NULL ( numBinsOut > 0, XLAL_EINVAL );

  // setup frequency vector
  REAL8Vector *f_out;
  XLAL_CHECK_NULL ( (f_out = XLALCreateREAL8Vector ( numBinsOut )) != NULL, XLAL_EFUNC );
  for ( UINT4 k = 0; k < numBinsOut; k ++ ) {
    f_out->data[k] = f0Out + k * dfOut;
  } // for k < numBinsOut

  SFTtype *out;
  XLAL_CHECK_NULL ( (out = XLALCalloc ( 1, sizeof(*out))) != NULL, XLAL_EFUNC );
  (*out) = (*sft_in);	// copy header
  out->f0 = f0Out;
  out->deltaF = dfOut;
  XLAL_CHECK_NULL ( (out->data = XLALCreateCOMPLEX8Vector ( numBinsOut )) != NULL, XLAL_EFUNC );

  XLAL_CHECK_NULL ( XLALSincInterpolateCOMPLEX8FrequencySeries ( out->data, f_out, sft_in, Dterms ) == XLAL_SUCCESS, XLAL_EFUNC );

  XLALDestroyREAL8Vector ( f_out );

  return out;

} // XLALSincInterpolateSFT()
Beispiel #13
0
///
/// Compute the extent of the bounding box of the mismatch ellipse of a metric \f$ g_{ij} \f$.
///
gsl_vector *XLALMetricEllipseBoundingBox(
  const gsl_matrix *g_ij,		///< [in] Parameter-space metric \f$ g_{ij} \f$
  const double max_mismatch		///< [in] Maximum prescribed mismatch
  )
{

  // Check input
  XLAL_CHECK_NULL( g_ij != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( g_ij->size1 == g_ij->size2, XLAL_ESIZE );

  const size_t n = g_ij->size1;

  // Allocate memory
  gsl_matrix *GAMAT_NULL( LU_decomp, n, n );
  gsl_permutation *GAPERM_NULL( LU_perm, n );
  gsl_matrix *GAMAT_NULL( diag_norm, n, n );
  gsl_matrix *GAMAT_NULL( inverse, n, n );
  gsl_vector *GAVEC_NULL( bounding_box, n );

  // Diagonally normalize metric
  XLAL_CHECK_NULL( XLALDiagNormalizeMetric( &LU_decomp, &diag_norm, g_ij ) == XLAL_SUCCESS, XLAL_EFUNC );

  // Compute metric inverse
  int LU_sign = 0;
  XLAL_CHECK_NULL( gsl_linalg_LU_decomp( LU_decomp, LU_perm, &LU_sign ) == 0, XLAL_EFAILED, "'g_ij' cannot be LU-decomposed" );
  XLAL_CHECK_NULL( gsl_linalg_LU_invert( LU_decomp, LU_perm, inverse ) == 0, XLAL_EFAILED, "'g_ij' cannot be inverted" );

  // Compute bounding box, and invert diagonal normalization
  for( size_t i = 0; i < n; ++i ) {
    const double diag_norm_i = gsl_matrix_get( diag_norm, i, i );
    const double bounding_box_i = 2.0 * sqrt( max_mismatch * gsl_matrix_get( inverse, i, i ) ) * diag_norm_i;
    gsl_vector_set( bounding_box, i, bounding_box_i );
  }

  // Cleanup
  GFMAT( LU_decomp, diag_norm, inverse );
  GFPERM( LU_perm );

  return bounding_box;

} // XLALMetricEllipseBoundingBox()
/**
 * Duplicates a COMPLEX8TimeSeries structure.
 * Allocates memory and copies contents.
 */
COMPLEX8TimeSeries *
XLALDuplicateCOMPLEX8TimeSeries ( COMPLEX8TimeSeries *times )
{
  XLAL_CHECK_NULL ( times != NULL, XLAL_EINVAL );
  XLAL_CHECK_NULL ( (times->data != NULL) && (times->data->length > 0) && ( times->data->data != NULL ), XLAL_EINVAL );

  COMPLEX8TimeSeries *out;
  XLAL_CHECK_NULL ( (out = XLALCalloc ( 1, sizeof(*out) )) != NULL, XLAL_ENOMEM );

  // copy header info [including data-pointer, will be reset]
  memcpy ( out, times, sizeof(*times) );

  UINT4 numBins = times->data->length;
  XLAL_CHECK_NULL ( (out->data = XLALCreateCOMPLEX8Vector ( numBins )) != NULL, XLAL_EFUNC );

  // copy contents of COMPLEX8 vector
  memcpy ( out->data->data, times->data->data, numBins * sizeof(times->data->data[0]) );

  return out;

} // XLALDuplicateCOMPLEX8TimeSeries()
/**
 * Duplicates a MultiCOMPLEX8TimeSeries structure.
 * Allocates memory and copies contents.
 */
MultiCOMPLEX8TimeSeries *
XLALDuplicateMultiCOMPLEX8TimeSeries ( MultiCOMPLEX8TimeSeries *multiTimes )
{
  XLAL_CHECK_NULL ( multiTimes != NULL, XLAL_EINVAL );
  XLAL_CHECK_NULL ( multiTimes->length > 0, XLAL_EINVAL );

  UINT4 numDetectors = multiTimes->length;

  // ----- prepare memory for multicomplex8timeseries container
  MultiCOMPLEX8TimeSeries *out;
  XLAL_CHECK_NULL ( (out = XLALCalloc ( 1, sizeof(*out) )) != NULL, XLAL_ENOMEM );
  out->length = numDetectors;
  XLAL_CHECK_NULL ( (out->data = XLALCalloc ( numDetectors, sizeof(*out->data) )) != NULL, XLAL_ENOMEM );

  // ----- copy each of the numDet complex8timeseries contents
  for ( UINT4 X = 0; X < numDetectors; X ++ ) {
    XLAL_CHECK_NULL ( (out->data[X] = XLALDuplicateCOMPLEX8TimeSeries ( multiTimes->data[X] )) != NULL, XLAL_EFUNC );
  }

  return out;

} // XLALDuplicateMultiCOMPLEX8TimeSeries()
/**
 * Turn the given multiSFTvector into multiple long COMPLEX8TimeSeries, properly dealing with gaps.
 * Memory allocation for the output MultiCOMPLEX8TimeSeries is done within this function.
 *
 */
MultiCOMPLEX8TimeSeries *
XLALMultiSFTVectorToCOMPLEX8TimeSeries ( const MultiSFTVector *multisfts  /**< [in] multi SFT vector */
                                         )
{
  // check input sanity
  XLAL_CHECK_NULL ( (multisfts != NULL) && (multisfts->length > 0), XLAL_EINVAL );
  UINT4 numDetectors = multisfts->length;

  /* allocate memory for the output structure */
  MultiCOMPLEX8TimeSeries *out;
  XLAL_CHECK_NULL ( (out = XLALMalloc ( sizeof(MultiCOMPLEX8TimeSeries) )) != NULL, XLAL_ENOMEM );
  XLAL_CHECK_NULL ( (out->data = XLALMalloc ( numDetectors * sizeof(COMPLEX8TimeSeries*) )) != NULL, XLAL_ENOMEM );
  out->length = numDetectors;

  /* loop over detectors */
  for ( UINT4 X=0; X < numDetectors; X++ ) {
    XLAL_CHECK_NULL ( (out->data[X] = XLALSFTVectorToCOMPLEX8TimeSeries ( multisfts->data[X] )) != NULL, XLAL_EFUNC );
  }

  return out;

} // XLALMultiSFTVectorToCOMPLEX8TimeSeries()
LALHashTbl *XLALHashTblCreate(
  LALHashTblDtorFcn dtor,
  LALHashTblHashFcn hash,
  LALHashTblCmpFcn cmp
  )
{

  /* Create a hash table using hashtbl_no_param_hash/cmp as the hash/comparison functions */
  LALHashTbl *ht = XLALHashTblCreate2( dtor, hashtbl_no_param_hash, hash, hashtbl_no_param_cmp, cmp );
  XLAL_CHECK_NULL( ht != NULL, XLAL_EFUNC );

  return ht;

}
Beispiel #18
0
/*--------------------------------------------------
 * calculate the difference of two SFT-vectors
 *--------------------------------------------------*/
SFTVector *
subtractSFTVectors ( const SFTVector *sftvect1, const SFTVector *sftvect2 )
{
  XLAL_CHECK_NULL ( (sftvect1 != NULL) && (sftvect2 != NULL), XLAL_EINVAL );
  XLAL_CHECK_NULL ( sftvect1->length == sftvect2->length, XLAL_EINVAL );

  UINT4 numSFTs = sftvect1->length;
  UINT4 numBins = sftvect1->data[0].data->length;

  SFTVector *vect;
  XLAL_CHECK_NULL ( (vect = XLALCreateSFTVector ( numSFTs, numBins )) != NULL, XLAL_EFUNC );

  for ( UINT4 alpha = 0; alpha < numSFTs; alpha ++ )
    {
      for ( UINT4 j=0; j < numBins; j++ )
	{
	  vect->data[alpha].data->data[j] = sftvect1->data[alpha].data->data[j] - sftvect2->data[alpha].data->data[j];
	}
    } /* for alpha < numSFTs */

  return vect;

} /* subtractSFTVectors() */
Beispiel #19
0
/**
 * Sample a number (sampleSize) of values from an alignedREAL4VectorArray (input) randomly from vector 0 up to numberofvectors without accepting any values of zero
 * Needs this numberofvectors limit because of the IHS algorithm
 * \param [in] input           Pointer to a alignedREAL4VectorArray to be sampled from
 * \param [in] numberofvectors Number of vectors from the start from which to sample from
 * \param [in] sampleSize      Integer value for the length of the output vector
 * \param [in] rng             Pointer to a gsl_rng generator
 * \return Newly allocated REAL4Vector of sampled values from the input vector
 */
REAL4Vector * sampleAlignedREAL4VectorArray_nozerosaccepted(alignedREAL4VectorArray *input, INT4 numberofvectors, INT4 sampleSize, gsl_rng *rng)
{

   REAL4Vector *output = NULL;
   XLAL_CHECK_NULL( (output = XLALCreateREAL4Vector(sampleSize)) != NULL, XLAL_EFUNC );

   for (INT4 ii=0; ii<sampleSize; ii++) {
      output->data[ii] = input->data[(INT4)floor(gsl_rng_uniform(rng)*numberofvectors)]->data[(INT4)floor(gsl_rng_uniform(rng)*input->data[0]->length)];
      while (output->data[ii]==0.0) output->data[ii] = input->data[(INT4)floor(gsl_rng_uniform(rng)*numberofvectors)]->data[(INT4)floor(gsl_rng_uniform(rng)*input->data[0]->length)];
   }

   return output;

} /* sampleREAL4VectorSequence_nozerosaccepted() */
Beispiel #20
0
/**
 * Resize a candidateVector
 * \param [in] vector Pointer of vector to resize
 * \param [in] length New length of candidateVector
 * \return Pointer to resized vector
 */
candidateVector * resize_candidateVector(candidateVector *vector, UINT4 length)
{

   if (vector==NULL) return new_candidateVector(length);
   if (length==0) {
      free_candidateVector(vector);
      return NULL;
   }

   XLAL_CHECK_NULL( (vector->data = XLALRealloc(vector->data, length*sizeof(*vector->data))) != NULL, XLAL_ENOMEM );

   vector->length = length;

   return vector;

} /* resize_candidateVector() */
Beispiel #21
0
/**
 * Resize an UpperLimitVector
 * \param [in,out] vector Pointer to UpperLimitVector to resize
 * \param [in]     length New length of the vector
 * \return Pointer to reallocated UpperLimitVector
 */
UpperLimitVector * resize_UpperLimitVector(UpperLimitVector *vector, UINT4 length)
{

    if (vector==NULL) return new_UpperLimitVector(length);
    if (length==0) {
        free_UpperLimitVector(vector);
        return NULL;
    }

    UINT4 oldlength = vector->length;

    XLAL_CHECK_NULL( (vector->data = XLALRealloc(vector->data, length*sizeof(*vector->data))) != NULL, XLAL_ENOMEM );
    vector->length = length;
    for (UINT4 ii=oldlength; ii<length; ii++) reset_UpperLimitStruct(&(vector->data[ii]));

    return vector;

} /* resize_UpperLimitVector() */
/**
 * Parse a given 'CWsources' config file for PulsarParams, return vector
 * of all pulsar definitions found [using sections]
 */
PulsarParamsVector *
XLALPulsarParamsFromFile ( const char *fname 		///< [in] 'CWsources' config file name
                           )
{
  XLAL_CHECK_NULL ( fname != NULL, XLAL_EINVAL );

  LALParsedDataFile *cfgdata = NULL;
  XLAL_CHECK_NULL ( XLALParseDataFile ( &cfgdata, fname ) == XLAL_SUCCESS, XLAL_EFUNC );

  LALStringVector *sections;
  XLAL_CHECK_NULL ( (sections = XLALListConfigFileSections ( cfgdata )) != NULL, XLAL_EFUNC );

  UINT4 numPulsars = sections->length;	// currently only single-section defs supported! FIXME

  PulsarParamsVector *sources;
  XLAL_CHECK_NULL ( (sources = XLALCreatePulsarParamsVector ( numPulsars )) != NULL, XLAL_EFUNC );

  for ( UINT4 i = 0; i < numPulsars; i ++ )
    {
      const char *sec_i = sections->data[i];

      if ( strcmp ( sec_i, "default" ) == 0 ) {	// special handling of 'default' section
        sec_i = NULL;
      }
      XLAL_CHECK_NULL ( XLALReadPulsarParams ( &sources->data[i], cfgdata, sec_i ) == XLAL_SUCCESS, XLAL_EFUNC );

      // ----- source naming convention: 'filename:section'
      char *name;
      size_t len = strlen(fname) + strlen(sections->data[i]) + 2;
      XLAL_CHECK_NULL ( (name = XLALCalloc(1, len)) != NULL, XLAL_ENOMEM );
      sprintf ( name, "%s:%s", fname, sections->data[i] );
      sources->data[i].name = name;

    } // for i < numPulsars

  XLALDestroyStringVector ( sections );
  XLALDestroyParsedDataFile ( cfgdata );

  return sources;

} // XLALPulsarParamsFromFile()
Beispiel #23
0
///
/// Create output results
///
WeaveOutputResults *XLALWeaveOutputResultsCreate(
  const LIGOTimeGPS *ref_time,
  const size_t nspins,
  WeaveStatisticsParams *statistics_params,
  const UINT4 toplist_limit,
  const BOOLEAN toplist_tmpl_idx
  )
{
  // Check input
  XLAL_CHECK_NULL( ref_time != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( statistics_params != NULL, XLAL_EFAULT );

  // Allocate memory
  WeaveOutputResults *out = XLALCalloc( 1, sizeof( *out ) );
  XLAL_CHECK_NULL( out != NULL, XLAL_ENOMEM );

  // Set fields
  out->ref_time = *ref_time;
  out->nspins = nspins;
  out->toplist_limit = toplist_limit;
  out->toplist_tmpl_idx = toplist_tmpl_idx;
  out->statistics_params = statistics_params;

  WeaveStatisticType toplist_statistics = statistics_params->toplist_statistics;

  // Initialise number of toplists
  out->ntoplists = 0;

  // Create a toplist which ranks results by mean multi-detector F-statistic
  if ( toplist_statistics & WEAVE_STATISTIC_MEAN2F ) {
    out->toplists[out->ntoplists] = XLALWeaveResultsToplistCreate( nspins, statistics_params, WEAVE_STATISTIC_NAME( WEAVE_STATISTIC_MEAN2F ), "average multi-detector F-statistic", toplist_limit, toplist_tmpl_idx, toplist_results_mean2F, toplist_item_get_mean2F, toplist_item_set_mean2F );
    XLAL_CHECK_NULL( out->toplists[out->ntoplists] != NULL, XLAL_EFUNC );
    XLAL_CHECK_NULL( out->ntoplists < XLAL_NUM_ELEM( out->toplists ), XLAL_EFAILED );
    out->ntoplists++;
  }

  // Create a toplist which ranks results by summed multi-detector F-statistic
  if ( toplist_statistics & WEAVE_STATISTIC_SUM2F ) {
    out->toplists[out->ntoplists] = XLALWeaveResultsToplistCreate( nspins, statistics_params, WEAVE_STATISTIC_NAME( WEAVE_STATISTIC_SUM2F ), "summed multi-detector F-statistic", toplist_limit, toplist_tmpl_idx, toplist_results_sum2F, toplist_item_get_sum2F, toplist_item_set_sum2F );
    XLAL_CHECK_NULL( out->toplists[out->ntoplists] != NULL, XLAL_EFUNC );
    XLAL_CHECK_NULL( out->ntoplists < XLAL_NUM_ELEM( out->toplists ), XLAL_EFAILED );
    out->ntoplists++;
  }

  // Create a toplist which ranks results by line-robust log10(B_S/GL) statistic
  if ( toplist_statistics & WEAVE_STATISTIC_BSGL ) {
    out->toplists[out->ntoplists] = XLALWeaveResultsToplistCreate( nspins, statistics_params, WEAVE_STATISTIC_NAME( WEAVE_STATISTIC_BSGL ), "line-robust log10BSGL statistic", toplist_limit, toplist_tmpl_idx, toplist_results_log10BSGL, toplist_item_get_log10BSGL, toplist_item_set_log10BSGL );
    XLAL_CHECK_NULL( out->toplists[out->ntoplists] != NULL, XLAL_EFUNC );
    XLAL_CHECK_NULL( out->ntoplists < XLAL_NUM_ELEM( out->toplists ), XLAL_EFAILED );
    out->ntoplists++;
  }

  // Create a toplist which ranks results by transient-line-robust log10(B_S/GLtL) statistic
  if ( toplist_statistics & WEAVE_STATISTIC_BSGLtL ) {
    out->toplists[out->ntoplists] = XLALWeaveResultsToplistCreate( nspins, statistics_params, WEAVE_STATISTIC_NAME( WEAVE_STATISTIC_BSGLtL ), "transient line-robust log10BSGLtL statistic", toplist_limit, toplist_tmpl_idx, toplist_results_log10BSGLtL, toplist_item_get_log10BSGLtL, toplist_item_set_log10BSGLtL );
    XLAL_CHECK_NULL( out->toplists[out->ntoplists] != NULL, XLAL_EFUNC );
    XLAL_CHECK_NULL( out->ntoplists < XLAL_NUM_ELEM( out->toplists ), XLAL_EFAILED );
    out->ntoplists++;
  }

  // Create a toplist which ranks results by transient-signal line-robust log10(B_tS/GLtL) statistic
  if ( toplist_statistics & WEAVE_STATISTIC_BtSGLtL ) {
    out->toplists[out->ntoplists] = XLALWeaveResultsToplistCreate( nspins, statistics_params, WEAVE_STATISTIC_NAME( WEAVE_STATISTIC_BtSGLtL ), "transient signal line-robust log10BtSGLtL statistic", toplist_limit, toplist_tmpl_idx, toplist_results_log10BtSGLtL, toplist_item_get_log10BtSGLtL, toplist_item_set_log10BtSGLtL );
    XLAL_CHECK_NULL( out->toplists[out->ntoplists] != NULL, XLAL_EFUNC );
    XLAL_CHECK_NULL( out->ntoplists < XLAL_NUM_ELEM( out->toplists ), XLAL_EFAILED );
    out->ntoplists++;
  }

  // Comnsistency check on number of toplists
  XLAL_CHECK_NULL( out->ntoplists == statistics_params->ntoplists, XLAL_EFAILED );

  return out;

}
/**
 * Turn the given multi-IFO SFTvectors into one long Fourier transform (LFT) over the total observation time
 */
SFTtype *
XLALSFTVectorToLFT ( SFTVector *sfts,		/**< input SFT vector (gets modified!) */
		     REAL8 upsampling		/**< upsampling factor >= 1 */
                     )
{
  XLAL_CHECK_NULL ( (sfts != NULL) && (sfts->length > 0), XLAL_EINVAL );
  XLAL_CHECK_NULL ( upsampling >= 1, XLAL_EDOM, "Upsampling factor (%f) must be >= 1 \n", upsampling );

  // ----- some useful SFT infos
  SFTtype *firstSFT = &(sfts->data[0]);
  UINT4 numBinsSFT = firstSFT->data->length;
  REAL8 dfSFT = firstSFT->deltaF;
  REAL8 Tsft = 1.0 / dfSFT;
  REAL8 f0SFT = firstSFT->f0;

  // ----- turn input SFTs into a complex (heterodyned) timeseries
  COMPLEX8TimeSeries *lTS;
  XLAL_CHECK_NULL ( (lTS = XLALSFTVectorToCOMPLEX8TimeSeries ( sfts )) != NULL, XLAL_EFUNC );
  REAL8 dt = lTS->deltaT;
  UINT4 numSamples0 = lTS->data->length;
  REAL8 Tspan0 = numSamples0 * dt;

  // ---------- determine time-span of upsampled time-series
  /* NOTE: Tspan MUST be an integer multiple of Tsft,
   * in order for the frequency bins of the final FFT
   * to be commensurate with the SFT bins.
   * This is required so that fHet is an exact
   * frequency-bin in both cases
   */
  UINT4 numSFTsFit = lround ( (Tspan0 * upsampling) / Tsft );
  REAL8 Tspan = numSFTsFit * Tsft;
  UINT4 numSamples = lround ( Tspan / dt );

  // ----- enlarge TimeSeries container for zero-padding if neccessary
  if ( numSamples > numSamples0 )
    {
      XLAL_CHECK_NULL ( (lTS->data->data = XLALRealloc ( lTS->data->data, numSamples * sizeof(lTS->data->data[0]) )) != NULL, XLAL_ENOMEM );
      lTS->data->length = numSamples;
      memset ( lTS->data->data + numSamples0, 0, (numSamples - numSamples0) * sizeof(lTS->data->data[0])); /* set all new time-samples to zero */
    }

  /* translate this back into fmin for the LFT (counting down from DC==fHet) */
  /* fHet = DC of our internal DFTs */
  UINT4 NnegSFT = NhalfNeg ( numBinsSFT );
  REAL8 fHet = f0SFT + 1.0 * NnegSFT * dfSFT;

  UINT4 NnegLFT = NhalfNeg ( numSamples );
  REAL8 f0LFT = fHet - NnegLFT / Tspan;

  // ----- prepare output LFT ----------
  SFTtype *outputLFT;
  XLAL_CHECK_NULL ( (outputLFT = XLALCreateSFT ( numSamples )) != NULL, XLAL_EFUNC );

  // prepare LFT header
  strcpy ( outputLFT->name, firstSFT->name );
  strncat ( outputLFT->name, ":long Fourier transform", sizeof(outputLFT->name) - 1 - strlen(outputLFT->name));
  outputLFT->epoch  = firstSFT->epoch;
  outputLFT->f0     = f0LFT;
  outputLFT->deltaF = 1.0 / Tspan;
  outputLFT->sampleUnits = firstSFT->sampleUnits;

  // ---------- FFT the long timeseries ----------
  COMPLEX8FFTPlan *LFTplan;
  XLAL_CHECK_NULL ( (LFTplan = XLALCreateForwardCOMPLEX8FFTPlan( numSamples, 0 )) != NULL, XLAL_EFUNC );
  XLAL_CHECK_NULL ( XLALCOMPLEX8VectorFFT( outputLFT->data, lTS->data, LFTplan ) == XLAL_SUCCESS, XLAL_EFUNC );
  XLAL_CHECK_NULL ( XLALReorderFFTWtoSFT (outputLFT->data) == XLAL_SUCCESS, XLAL_EFUNC );
  // apply proper normalization 'dt'
  for ( UINT4 k = 0; k < outputLFT->data->length; k ++ ) {
    outputLFT->data->data[k] *= dt;
  }

  /* cleanup memory */
  XLALDestroyCOMPLEX8TimeSeries ( lTS );
  XLALDestroyCOMPLEX8FFTPlan ( LFTplan );

  return outputLFT;

} // XLALSFTVectorToLFT()
/**
 * Turn the given SFTvector into one long time-series, properly dealing with gaps.
 */
COMPLEX8TimeSeries *
XLALSFTVectorToCOMPLEX8TimeSeries ( const SFTVector *sftsIn         /**< [in] SFT vector */
                                    )
{
  // check input sanity
  XLAL_CHECK_NULL ( (sftsIn !=NULL) && (sftsIn->length > 0), XLAL_EINVAL );

  // create a local copy of the input SFTs, as they will be locally modified!
  SFTVector *sfts;
  XLAL_CHECK_NULL ( (sfts = XLALDuplicateSFTVector ( sftsIn )) != NULL, XLAL_EFUNC );

  /* define some useful shorthands */
  UINT4 numSFTs = sfts->length;
  SFTtype *firstSFT = &(sfts->data[0]);
  SFTtype *lastSFT = &(sfts->data[numSFTs-1]);
  UINT4 numFreqBinsSFT = firstSFT->data->length;
  REAL8 dfSFT = firstSFT->deltaF;
  REAL8 Tsft = 1.0 / dfSFT;
  REAL8 deltaT = Tsft / numFreqBinsSFT;	// complex FFT: numSamplesSFT = numFreqBinsSFT
  REAL8 f0SFT = firstSFT->f0;

  /* if the start and end input pointers are NOT NULL then determine start and time-span of the final long time-series */
  LIGOTimeGPS start = firstSFT->epoch;
  LIGOTimeGPS end = lastSFT->epoch;
  XLALGPSAdd ( &end, Tsft );

  /* determine output time span */
  REAL8 Tspan;
  XLAL_CHECK_NULL ( (Tspan = XLALGPSDiff ( &end, &start ) ) > 0, XLAL_EINVAL );

  UINT4 numSamples = lround ( Tspan / deltaT );

  /* determine the heterodyning frequency */
  /* fHet = DC of our internal DFTs */
  UINT4 NnegSFT = NhalfNeg ( numFreqBinsSFT );
  REAL8 fHet = f0SFT + 1.0 * NnegSFT * dfSFT;

  /* ----- Prepare invFFT of SFTs: compute plan for FFTW */
  COMPLEX8FFTPlan *SFTplan;
  XLAL_CHECK_NULL ( (SFTplan = XLALCreateReverseCOMPLEX8FFTPlan( numFreqBinsSFT, 0 )) != NULL, XLAL_EFUNC );

  /* ----- Prepare short time-series holding ONE invFFT of a single SFT */
  LIGOTimeGPS XLAL_INIT_DECL(epoch);
  COMPLEX8TimeSeries *sTS;
  XLAL_CHECK_NULL ( (sTS = XLALCreateCOMPLEX8TimeSeries ( "short timeseries", &epoch, 0, deltaT, &emptyLALUnit, numFreqBinsSFT )) != NULL, XLAL_EFUNC );

  /* ----- prepare long TimeSeries container ---------- */
  COMPLEX8TimeSeries *lTS;
  XLAL_CHECK_NULL ( (lTS = XLALCreateCOMPLEX8TimeSeries ( firstSFT->name, &start, fHet, deltaT, &emptyLALUnit, numSamples )) != NULL, XLAL_EFUNC );
  memset ( lTS->data->data, 0, numSamples * sizeof(*lTS->data->data)); 	/* set all time-samples to zero (in case there are gaps) */

  /* ---------- loop over all SFTs and inverse-FFT them ---------- */
  for ( UINT4 n = 0; n < numSFTs; n ++ )
    {
      SFTtype *thisSFT = &(sfts->data[n]);

      /* find bin in long timeseries corresponding to starttime of *this* SFT */
      REAL8 offset_n = XLALGPSDiff ( &(thisSFT->epoch), &start );
      UINT4 bin0_n = lround ( offset_n / deltaT );	/* round to closest bin */

      REAL8 nudge_n = bin0_n * deltaT - offset_n;		/* rounding error */
      nudge_n = 1e-9 * round ( nudge_n * 1e9 );	/* round to closest nanosecond */
      /* nudge SFT into integer timestep bin if necessary */
      XLAL_CHECK_NULL ( XLALTimeShiftSFT ( thisSFT, nudge_n ) == XLAL_SUCCESS, XLAL_EFUNC  );

      /* determine heterodyning phase-correction for this SFT */
      REAL8 offset = XLALGPSDiff ( &thisSFT->epoch, &start );	// updated value after time-shift
      // fHet * Tsft is an integer by construction, because fHet was chosen as a frequency-bin of the input SFTs
      // therefore we only need the remainder (offset % Tsft)
      REAL8 offsetEff = fmod ( offset, Tsft );
      REAL8 hetCycles = fmod ( fHet * offsetEff, 1); // heterodyning phase-correction for this SFT

      if ( nudge_n != 0 ){
        XLALPrintInfo("n = %d, offset_n = %g, nudge_n = %g, offset = %g, offsetEff = %g, hetCycles = %g\n",
                      n, offset_n, nudge_n, offset, offsetEff, hetCycles );
      }

      REAL4 hetCorrection_re, hetCorrection_im;
      XLAL_CHECK_NULL ( XLALSinCos2PiLUT ( &hetCorrection_im, &hetCorrection_re, -hetCycles ) == XLAL_SUCCESS, XLAL_EFUNC );
      COMPLEX8 hetCorrection = crectf( hetCorrection_re, hetCorrection_im );

      /* Note: we also bundle the overall normalization of 'df' into the het-correction.
       * This ensures that the resulting timeseries will have the correct normalization, according to
       * x_l = invFT[sft]_l = df * sum_{k=0}^{N-1} xt_k * e^(i 2pi k l / N )
       * where x_l is the l-th timestamp, and xt_k is the k-th frequency bin of the SFT.
       * See the LAL-conventions on FFTs:  http://www.ligo.caltech.edu/docs/T/T010095-00.pdf
       * (the FFTw convention does not contain the factor of 'df', which is why we need to
       * apply it ourselves)
       *
       */
      hetCorrection *= dfSFT;

      XLAL_CHECK_NULL ( XLALReorderSFTtoFFTW (thisSFT->data) == XLAL_SUCCESS, XLAL_EFUNC );
      XLAL_CHECK_NULL ( XLALCOMPLEX8VectorFFT( sTS->data, thisSFT->data, SFTplan ) == XLAL_SUCCESS, XLAL_EFUNC );

      for ( UINT4 j=0; j < sTS->data->length; j++) {
        sTS->data->data[j] *= hetCorrection;
      } // for j < numFreqBinsSFT

      // copy the short (shifted) heterodyned timeseries into correct location within long timeseries
      UINT4 binsLeft = numSamples - bin0_n;
      UINT4 copyLen = MYMIN ( numFreqBinsSFT, binsLeft );		/* make sure not to write past the end of the long TS */
      memcpy ( &lTS->data->data[bin0_n], sTS->data->data, copyLen * sizeof(lTS->data->data[0]) );

    } /* for n < numSFTs */

  // cleanup memory
  XLALDestroySFTVector ( sfts );
  XLALDestroyCOMPLEX8TimeSeries ( sTS );
  XLALDestroyCOMPLEX8FFTPlan ( SFTplan );

  return lTS;

} // XLALSFTVectorToCOMPLEX8TimeSeries()
/**
 * Function to determine the PulsarParamsVector input from a user-input defining CW sources.
 *
 * This option supports a dual-type feature: if any string in the list is of the form '{...}', then
 * it determines the *contents* of a config-file, otherwise the name-pattern of config-files to be parsed by XLALFindFiles(),
 * NOTE: when specifying file-contents, options can be separated by ';' and/or newlines)
 */
PulsarParamsVector *
XLALPulsarParamsFromUserInput ( const LALStringVector *UserInput		///< [in] user-input CSV list defining 'CW sources'
                                )
{
  XLAL_CHECK_NULL ( UserInput, XLAL_EINVAL );
  XLAL_CHECK_NULL ( UserInput->length > 0, XLAL_EINVAL );

  PulsarParamsVector *allSources = NULL;

  for ( UINT4 l = 0; l < UserInput->length; l ++ )
    {
      const char *thisInput = UserInput->data[l];

      if ( thisInput[0] != '{' )	// if it's an actual file-specification
        {
          LALStringVector *file_list;
          XLAL_CHECK_NULL ( ( file_list = XLALFindFiles ( &thisInput[0] )) != NULL, XLAL_EFUNC );
          UINT4 numFiles = file_list->length;
          for ( UINT4 i = 0; i < numFiles; i ++ )
            {
              PulsarParamsVector *sources_i;
              XLAL_CHECK_NULL ( (sources_i = XLALPulsarParamsFromFile ( file_list->data[i] )) != NULL, XLAL_EFUNC );

              XLAL_CHECK_NULL ( (allSources = XLALPulsarParamsVectorAppend ( allSources, sources_i )) != NULL, XLAL_EFUNC );
              XLALDestroyPulsarParamsVector ( sources_i );
            } // for i < numFiles

          XLALDestroyStringVector ( file_list );

        } // if file-pattern given
      else
        {
          UINT4 len = strlen(thisInput);
          XLAL_CHECK_NULL ( (thisInput[0] == '{') && (thisInput[len-1] == '}'), XLAL_EINVAL, "Invalid file-content input:\n%s\n", thisInput );
          char *buf;
          XLAL_CHECK_NULL ( (buf = XLALStringDuplicate ( &thisInput[1] )) != NULL, XLAL_EFUNC );
          len = strlen(buf);
          buf[len-1] = 0;	// remove trailing '}'

          LALParsedDataFile *cfgdata = NULL;
          XLAL_CHECK_NULL ( XLALParseDataFileContent ( &cfgdata, buf ) == XLAL_SUCCESS, XLAL_EFUNC );
          XLALFree ( buf );

          PulsarParamsVector *addSource;
          XLAL_CHECK_NULL ( (addSource = XLALCreatePulsarParamsVector ( 1 )) != NULL, XLAL_EFUNC );

          XLAL_CHECK_NULL ( XLALReadPulsarParams ( &addSource->data[0], cfgdata, NULL ) == XLAL_SUCCESS, XLAL_EFUNC );
          XLAL_CHECK_NULL ( (addSource->data[0].name = XLALStringDuplicate ( "direct-string-input" )) != NULL, XLAL_EFUNC );
          XLALDestroyParsedDataFile ( cfgdata );

          XLAL_CHECK_NULL ( (allSources = XLALPulsarParamsVectorAppend ( allSources, addSource )) != NULL, XLAL_EFUNC );
          XLALDestroyPulsarParamsVector ( addSource );

        } // if direct config-string given

    } // for l < len(UserInput)

  return allSources;

} // XLALPulsarParamsFromUserInput()
///
/// Make SFTs from given REAL8TimeSeries at given timestamps, potentially applying a time-domain window on each timestretch first
///
SFTVector *
XLALMakeSFTsFromREAL8TimeSeries ( const REAL8TimeSeries *timeseries,	//!< input time-series
                                  const LIGOTimeGPSVector *timestamps, 	//!< timestamps to produce SFTs for (can be NULL), if given must all lies within timeseries' time-span
                                  const char *windowType,		//!< optional time-domain window function to apply before FFTing
                                  REAL8 windowBeta			//!< window parameter, if any
                                  )
{
  XLAL_CHECK_NULL ( timeseries != NULL, XLAL_EINVAL, "Invalid NULL input 'timeseries'\n");
  XLAL_CHECK_NULL ( timestamps != NULL, XLAL_EINVAL, "Invalid NULL input 'timestamps'\n");

  REAL8 dt = timeseries->deltaT;	// timeseries timestep */
  REAL8 Tsft = timestamps->deltaT;
  REAL8 df = 1.0 / Tsft;		// SFT frequency spacing

  // make sure that number of timesamples/SFT is an integer (up to possible rounding error 'eps')
  REAL8 timestepsSFT0 = Tsft / dt;
  UINT4 timestepsSFT  = lround ( timestepsSFT0 );
  XLAL_CHECK_NULL ( fabs ( timestepsSFT0 - timestepsSFT ) / timestepsSFT0 < eps, XLAL_ETOL,
                    "Inconsistent sampling-step (dt=%g) and Tsft=%g: must be integer multiple Tsft/dt = %g >= %g\n",
                    dt, Tsft, timestepsSFT0, eps );

  // prepare window function if requested
  REAL8Window *window = NULL;
  if ( windowType != NULL ) {
    XLAL_CHECK_NULL ( (window = XLALCreateNamedREAL8Window ( windowType, windowBeta, timestepsSFT )) != NULL, XLAL_EFUNC );
  }

  // ---------- Prepare FFT ----------
  REAL8Vector *timeStretchCopy;	// input array of length N
  XLAL_CHECK_NULL ( (timeStretchCopy = XLALCreateREAL8Vector ( timestepsSFT )) != NULL, XLAL_EFUNC, "XLALCreateREAL4Vector(%d) failed.\n", timestepsSFT );
  UINT4 numSFTBins = timestepsSFT / 2 + 1;	// number of positive frequency-bins + 'DC' to be stored in SFT
  fftw_complex *fftOut;	// output array of length N/2 + 1
  XLAL_CHECK_NULL ( (fftOut = fftw_malloc ( numSFTBins * sizeof(fftOut[0]) )) != NULL, XLAL_ENOMEM, "fftw_malloc(%d*sizeof(complex)) failed\n", numSFTBins );
  fftw_plan fftplan;	// FFTW plan
  LAL_FFTW_WISDOM_LOCK;
  XLAL_CHECK_NULL ( (fftplan = fftw_plan_dft_r2c_1d ( timestepsSFT, timeStretchCopy->data, fftOut, FFTW_ESTIMATE)) != NULL, XLAL_EFUNC );	// FIXME: or try FFTW_MEASURE
  LAL_FFTW_WISDOM_UNLOCK;

  LIGOTimeGPS tStart = timeseries->epoch;

  // get last possible start-time for an SFT
  REAL8 duration =  round ( timeseries->data->length * dt ); // rounded to seconds
  LIGOTimeGPS tLast = tStart;
  XLALGPSAdd( &tLast, duration - Tsft );

  // check that all timestamps lie within [tStart, tLast]
  for ( UINT4 i = 0; i < timestamps->length; i ++ )
    {
      char buf1[256], buf2[256];
      XLAL_CHECK_NULL ( XLALGPSDiff ( &tStart, &(timestamps->data[i]) ) <= 0, XLAL_EDOM, "Timestamp i=%d: %s before start-time %s\n",
                        i, XLALGPSToStr ( buf1, &(timestamps->data[i]) ), XLALGPSToStr ( buf2, &tStart ) );
      XLAL_CHECK_NULL ( XLALGPSDiff ( &tLast,   &(timestamps->data[i]) ) >=0, XLAL_EDOM, "Timestamp i=%d: %s after last start-time %s\n",
                        i, XLALGPSToStr ( buf1, &(timestamps->data[i]) ), XLALGPSToStr ( buf2, &tLast ) );
    }

  UINT4 numSFTs = timestamps->length;

  // prepare output SFT-vector
  SFTVector *sftvect;
  XLAL_CHECK_NULL ( (sftvect = XLALCreateSFTVector ( numSFTs, numSFTBins )) != NULL, XLAL_EFUNC,
                    "XLALCreateSFTVector(numSFTs=%d, numBins=%d) failed.\n", numSFTs, numSFTBins );

  // main loop: apply FFT to the requested time-stretches and store in output SFTs
  for ( UINT4 iSFT = 0; iSFT < numSFTs; iSFT++ )
    {
      SFTtype *thisSFT = &(sftvect->data[iSFT]);	// point to current SFT-slot to store output in

      // find the start-bin for this SFT in the time-series
      REAL8 offset = XLALGPSDiff ( &(timestamps->data[iSFT]), &tStart );
      INT4 offsetBins = lround ( offset / dt );

      // copy timeseries-data for that SFT into local buffer
      memcpy ( timeStretchCopy->data, timeseries->data->data + offsetBins, timeStretchCopy->length * sizeof(timeStretchCopy->data[0]) );

      // window the current time series stretch if required
      REAL8 sigma_window = 1;
      if ( window != NULL )
        {
	  sigma_window = sqrt ( window->sumofsquares / window->data->length );
	  for( UINT4 iBin = 0; iBin < timeStretchCopy->length; iBin++ ) {
            timeStretchCopy->data[iBin] *= window->data->data[iBin];
          }
        } // if window

      // FFT this time-stretch
      fftw_execute ( fftplan );

      // fill the header of the i'th output SFT */
      strcpy ( thisSFT->name, timeseries->name );
      thisSFT->epoch = timestamps->data[iSFT];
      thisSFT->f0 = timeseries->f0;			// SFT starts at heterodyning frequency
      thisSFT->deltaF = df;

      // normalize DFT-data to conform to v2 specification ==> multiply DFT by (dt/sigma{window})
      // the SFT normalization in case of windowing follows the conventions detailed in the SFTv2 specification,
      // namely LIGO-T040164, and in particular Eqs.(3),(4) and (6) in T010095-00.pdf
      // https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?.submit=Number&docid=T010095
      // https://dcc.ligo.org/DocDB/0026/T010095/000/T010095-00.pdf
      REAL8 norm = dt / sigma_window;
      for ( UINT4 k = 0; k < numSFTBins ; k ++ ) {
        thisSFT->data->data[k] = (COMPLEX8) ( norm * fftOut[k] );
      }

      // correct heterodyning-phase, IF NECESSARY: ie if (fHet * tStart) is not an integer, such that phase-corr = multiple of 2pi
      if ( ( (INT4)timeseries->f0 != timeseries->f0  ) || (timeseries->epoch.gpsNanoSeconds != 0) || (thisSFT->epoch.gpsNanoSeconds != 0) ) {
        XLAL_CHECK_NULL ( XLALcorrect_phase ( thisSFT, timeseries->epoch) == XLAL_SUCCESS, XLAL_EFUNC );
      }

    } // for iSFT < numSFTs

  // free memory
  fftw_free ( fftOut );
  LAL_FFTW_WISDOM_LOCK;
  fftw_destroy_plan ( fftplan );
  LAL_FFTW_WISDOM_UNLOCK;
  XLALDestroyREAL8Vector ( timeStretchCopy );
  XLALDestroyREAL8Window ( window );

  return sftvect;

} // XLALMakeSFTsFromREAL8TimeSeries()
Beispiel #28
0
///
/// Create coherent input data
///
WeaveCohInput *XLALWeaveCohInputCreate(
  const LALStringVector *setup_detectors,
  const WeaveSimulationLevel simulation_level,
  const SFTCatalog *sft_catalog,
  const UINT4 segment_index,
  const LALSeg *segment,
  const PulsarDopplerParams *min_phys,
  const PulsarDopplerParams *max_phys,
  const double dfreq,
  const EphemerisData *ephemerides,
  const LALStringVector *sft_noise_sqrtSX,
  const LALStringVector *Fstat_assume_sqrtSX,
  FstatOptionalArgs *Fstat_opt_args,
  const WeaveStatisticsParams *statistics_params,
  BOOLEAN recalc_stage
  )
{

  // Check input
  XLAL_CHECK_NULL( setup_detectors != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( ( simulation_level & WEAVE_SIMULATE_MIN_MEM ) || ( sft_catalog != NULL ), XLAL_EFAULT );
  XLAL_CHECK_NULL( segment != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( min_phys != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( max_phys != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( dfreq >= 0, XLAL_EINVAL );
  XLAL_CHECK_NULL( ephemerides != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( Fstat_opt_args != NULL, XLAL_EFAULT );
  XLAL_CHECK_NULL( statistics_params != NULL, XLAL_EFAULT );

  // Allocate memory
  WeaveCohInput *coh_input = XLALCalloc( 1, sizeof( *coh_input ) );
  XLAL_CHECK_NULL( coh_input != NULL, XLAL_ENOMEM );

  // Set fields
  coh_input->setup_detectors = setup_detectors;
  coh_input->simulation_level = simulation_level;
  coh_input->seg_info_have_sft_info = ( sft_catalog != NULL );
  coh_input->Fstat_collect_timing = Fstat_opt_args->collectTiming;

  // Record information from segment
  coh_input->seg_info.segment_start = segment->start;
  coh_input->seg_info.segment_end = segment->end;

  // Decide what F-statistic quantities to compute
  WeaveStatisticType requested_stats = ( recalc_stage ) ? statistics_params->completionloop_statistics[1] : statistics_params->mainloop_statistics;
  if ( requested_stats & WEAVE_STATISTIC_COH2F ) {
    coh_input->Fstat_what_to_compute |= FSTATQ_2F;
  }
  if ( requested_stats & WEAVE_STATISTIC_COH2F_DET ) {
    coh_input->Fstat_what_to_compute |= FSTATQ_2F_PER_DET;
  }

  // Return now if simulating search with minimal memory allocation
  if ( coh_input->simulation_level & WEAVE_SIMULATE_MIN_MEM ) {
    return coh_input;
  }

  // Get a timeslice of SFT catalog restricted to the given segment
  SFTCatalog XLAL_INIT_DECL( sft_catalog_seg );
  XLAL_CHECK_NULL( XLALSFTCatalogTimeslice( &sft_catalog_seg, sft_catalog, &segment->start, &segment->end ) == XLAL_SUCCESS, XLAL_EFUNC );
  XLAL_CHECK_NULL( sft_catalog_seg.length > 0, XLAL_EINVAL, "No SFTs found in segment %u", segment_index );

  // Check that the number of SFTs in each segment matches the number provided by the segment list in the setup file, if nonzero
  const UINT4 sft_count = ( UINT4 ) segment->id;
  XLAL_CHECK_NULL( sft_count == 0 || sft_catalog_seg.length == sft_count, XLAL_EFAILED, "Number of SFTs found for segment %u (%u) is inconsistent with expected number of SFTs given by segment list (%u)", segment_index, sft_catalog_seg.length, sft_count );

  // Get list of detectors of SFT catalog in this segment
  LALStringVector *sft_catalog_seg_detectors = XLALListIFOsInCatalog( &sft_catalog_seg );
  XLAL_CHECK_NULL( sft_catalog_seg_detectors != NULL, XLAL_EFUNC );

  // Compute frequency range covered by spindown range over in the given segment
  LIGOTimeGPS sft_start = sft_catalog_seg.data[0].header.epoch;
  LIGOTimeGPS sft_end = sft_catalog_seg.data[sft_catalog_seg.length - 1].header.epoch;
  const double sft_end_timebase = 1.0 / sft_catalog_seg.data[sft_catalog_seg.length - 1].header.deltaF;
  XLALGPSAdd( &sft_end, sft_end_timebase );
  PulsarSpinRange XLAL_INIT_DECL( spin_range );
  XLAL_CHECK_NULL( XLALInitPulsarSpinRangeFromSpins( &spin_range, &min_phys->refTime, min_phys->fkdot, max_phys->fkdot ) == XLAL_SUCCESS, XLAL_EFUNC );
  double sft_min_cover_freq = 0, sft_max_cover_freq = 0;
  XLAL_CHECK_NULL( XLALCWSignalCoveringBand( &sft_min_cover_freq, &sft_max_cover_freq, &sft_start, &sft_end, &spin_range, 0, 0, 0 ) == XLAL_SUCCESS, XLAL_EFUNC );

  // Parse SFT noise sqrt(Sh) string vector for detectors in this segment
  // - This is important when segments contain data from a subset of detectors
  MultiNoiseFloor Fstat_injectSqrtSX;
  if ( sft_noise_sqrtSX != NULL ) {
    XLAL_CHECK_NULL( XLALParseMultiNoiseFloorMapped( &Fstat_injectSqrtSX, sft_catalog_seg_detectors, sft_noise_sqrtSX, setup_detectors ) == XLAL_SUCCESS, XLAL_EFUNC );
    Fstat_opt_args->injectSqrtSX = &Fstat_injectSqrtSX;
  }

  // Parse F-statistic assumed sqrt(Sh) string vector for detectors in this segment
  // - This is important when segments contain data from a subset of detectors
  MultiNoiseFloor Fstat_assumeSqrtSX;
  if ( Fstat_assume_sqrtSX != NULL ) {
    XLAL_CHECK_NULL( XLALParseMultiNoiseFloorMapped( &Fstat_assumeSqrtSX, sft_catalog_seg_detectors, Fstat_assume_sqrtSX, setup_detectors ) == XLAL_SUCCESS, XLAL_EFUNC );
    Fstat_opt_args->assumeSqrtSX = &Fstat_assumeSqrtSX;
  }

  // Load F-statistic input data
  coh_input->Fstat_input = XLALCreateFstatInput( &sft_catalog_seg, sft_min_cover_freq, sft_max_cover_freq, dfreq, ephemerides, Fstat_opt_args );
  XLAL_CHECK_NULL( coh_input->Fstat_input != NULL, XLAL_EFUNC );
  Fstat_opt_args->prevInput = coh_input->Fstat_input;

  // Map detectors in F-statistic data in the given segment to their index in the coherent results
  // - This is important when segments contain data from a subset of detectors
  // - Map entry 'i' in 'Fstat_detector_info' (F-statistic data) to entry 'idx' in 'detectors' (coherent results)
  if ( coh_input->Fstat_what_to_compute & FSTATQ_2F_PER_DET ) {
    const MultiLALDetector *Fstat_detector_info = XLALGetFstatInputDetectors( coh_input->Fstat_input );
    coh_input->Fstat_ndetectors = Fstat_detector_info->length;
    char *statistics_detectors_string = XLALConcatStringVector( statistics_params->detectors, "," );
    for ( size_t i = 0; i < coh_input->Fstat_ndetectors; ++i ) {
      const char *prefix = Fstat_detector_info->sites[i].frDetector.prefix;
      const int idx = XLALFindStringInVector( prefix, statistics_params->detectors );
      XLAL_CHECK_NULL( idx >= 0, XLAL_EFAILED, "Detector '%s' from F-statistic data not found in list of detectors '%s'", prefix, statistics_detectors_string );
      coh_input->Fstat_res_idx[i] = idx;
    }
    XLALFree( statistics_detectors_string );
  }

  // Record information from SFTs in the given segment
  {
    MultiSFTCatalogView *sft_catalog_seg_view = XLALGetMultiSFTCatalogView( &sft_catalog_seg );
    XLAL_CHECK_NULL( sft_catalog_seg_view != NULL, XLAL_EINVAL );
    for ( size_t j = 0; j < sft_catalog_seg_view->length; ++j ) {
      XLAL_CHECK_NULL( sft_catalog_seg_view->data[j].length > 0, XLAL_EINVAL );
      char *detector_name = XLALGetChannelPrefix( sft_catalog_seg_view->data[j].data[0].header.name );
      XLAL_CHECK_NULL( detector_name != NULL, XLAL_EFUNC );
      const int k = XLALFindStringInVector( detector_name, sft_catalog_seg_detectors );
      if ( k >= 0 ) {
        const UINT4 length = sft_catalog_seg_view->data[j].length;
        coh_input->seg_info.sft_first[k] = sft_catalog_seg_view->data[j].data[0].header.epoch;
        coh_input->seg_info.sft_last[k] = sft_catalog_seg_view->data[j].data[length - 1].header.epoch;
        coh_input->seg_info.sft_count[k] = length;
      }
      XLALFree( detector_name );
    }
    XLALDestroyMultiSFTCatalogView( sft_catalog_seg_view );
  }
  XLAL_CHECK_NULL( XLALGetFstatInputSFTBand( coh_input->Fstat_input, &coh_input->seg_info.sft_min_freq, &coh_input->seg_info.sft_max_freq ) == XLAL_SUCCESS, XLAL_EFUNC );


  // Cleanup
  XLALDestroyStringVector( sft_catalog_seg_detectors );

  return coh_input;

}
/**
 * \brief Serializes a \c PulsarDopplerParams structure into a VOTable XML %node
 *
 * This function takes a \c PulsarDopplerParams structure and serializes it into a VOTable
 * \c RESOURCE %node identified by the given name. The returned \c xmlNode can then be
 * embedded into an existing %node hierarchy or turned into a full VOTable document.
 *
 * \param pdp [in] Pointer to the \c PulsarDopplerParams structure to be serialized
 * \param name [in] Unique identifier of this particular \c PulsarDopplerParams structure instance
 *
 * \return A pointer to a \c xmlNode that holds the VOTable fragment that represents
 * the \c PulsarDopplerParams structure.
 * In case of an error, a null-pointer is returned.\n
 * \b Important: the caller is responsible to free the allocated memory (when the
 * fragment isn't needed anymore) using \c xmlFreeNode. Alternatively, \c xmlFreeDoc
 * can be used later on when the returned fragment has been embedded in a XML document.
 *
 * \sa XLALCreateVOTParamNode
 * \sa XLALCreateVOTResourceNode
 * \sa XLALCreateVOTDocumentFromTree
 *
 * \author Oliver Bock\n
 * Albert-Einstein-Institute Hannover, Germany
 */
xmlNodePtr XLALPulsarDopplerParams2VOTNode(const PulsarDopplerParams *const pdp, const char *name)
{
    /* set up local variables */
    xmlNodePtr xmlParentNode = NULL;
    xmlNodePtr xmlChildNode = NULL;
    xmlNodePtr xmlChildNodeList = NULL;
    xmlNodePtr xmlCurrentChildNode = NULL;

    /* check and convert input parameters */
    XLAL_CHECK_NULL ( pdp != NULL, XLAL_EINVAL );

    CHAR Alpha[REAL8STR_MAXLEN] = {0};
    if( snprintf(Alpha, REAL8STR_MAXLEN, "%g", pdp->Alpha) < 0) {
        XLALPrintError("Invalid input parameter: PulsarDopplerParams->Alpha\n");
        XLAL_ERROR_NULL(XLAL_EINVAL);
    }
    CHAR Delta[REAL8STR_MAXLEN] = {0};
    if( snprintf(Delta, REAL8STR_MAXLEN, "%g", pdp->Delta) < 0) {
        XLALPrintError("Invalid input parameter: PulsarDopplerParams->Delta\n");
        XLAL_ERROR_NULL(XLAL_EINVAL);
    }
    CHAR argp[REAL8STR_MAXLEN] = {0};
    if( snprintf(argp, REAL8STR_MAXLEN, "%g", pdp->argp) < 0) {
        XLALPrintError("Invalid input parameter: PulsarDopplerParams->argp\n");
        XLAL_ERROR_NULL(XLAL_EINVAL);
    }
    CHAR asini[REAL8STR_MAXLEN] = {0};
    if( snprintf(asini, REAL8STR_MAXLEN, "%g", pdp->asini) < 0) {
        XLALPrintError("Invalid input parameter: PulsarDopplerParams->asini\n");
        XLAL_ERROR_NULL(XLAL_EINVAL);
    }
    CHAR ecc[REAL8STR_MAXLEN] = {0};
    if( snprintf(ecc, REAL8STR_MAXLEN, "%g", pdp->ecc) < 0) {
        XLALPrintError("Invalid input parameter: PulsarDopplerParams->ecc\n");
        XLAL_ERROR_NULL(XLAL_EINVAL);
    }
    CHAR period[REAL8STR_MAXLEN] = {0};
    if( snprintf(period, REAL8STR_MAXLEN, "%g", pdp->period) < 0) {
        XLALPrintError("Invalid input parameter: PulsarDopplerParams->period\n");
        XLAL_ERROR_NULL(XLAL_EINVAL);
    }

    if(!name || strlen(name) <= 0) {
        XLALPrintError("Invalid input parameter: name\n");
        XLAL_ERROR_NULL(XLAL_EINVAL);
    }

    /* ----- set up PARAM node (Alpha) */
    xmlChildNode = XLALCreateVOTParamNode("Alpha",
                                          "rad",
                                          VOT_REAL8,
                                          NULL,
                                          Alpha);
    if(!xmlChildNode) {
        XLALPrintError("Couldn't create PARAM node: %s.Alpha\n", name);
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* initialize child node list with first child */
    xmlChildNodeList = xmlChildNode;
    xmlCurrentChildNode = xmlChildNodeList;

    /* ----- set up PARAM node (Delta) */
    xmlChildNode = XLALCreateVOTParamNode("Delta",
                                          "rad",
                                          VOT_REAL8,
                                          NULL,
                                          Delta);
    if(!xmlChildNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create PARAM node: %s.Delta\n", name);
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* add child as next sibling to child node list */
    xmlCurrentChildNode->next = xmlChildNode;
    xmlCurrentChildNode = xmlCurrentChildNode->next;

    /* ----- set up PARAM node (fkdot) */
    xmlChildNode = XLALPulsarSpins2VOTNode(&pdp->fkdot, "fkdot");
    if(!xmlChildNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create PARAM node: %s.fkdot\n", name);
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* add child as next sibling to child node list */
    xmlCurrentChildNode->next = xmlChildNode;
    xmlCurrentChildNode = xmlCurrentChildNode->next;

    // ---------- handle binary-orbital parameters ----------
    /* ----- set up PARAM node (argp) */
    xmlChildNode = XLALCreateVOTParamNode("argp",
                                          "rad",
                                          VOT_REAL8,
                                          NULL,
                                          argp);
    if(!xmlChildNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create PARAM node: %s.argp\n", name);
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* add child as next sibling to child node list */
    xmlCurrentChildNode->next = xmlChildNode;
    xmlCurrentChildNode = xmlCurrentChildNode->next;

    /* ----- set up PARAM node (asini) */
    xmlChildNode = XLALCreateVOTParamNode("asini",
                                          "s",
                                          VOT_REAL8,
                                          NULL,
                                          asini);
    if(!xmlChildNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create PARAM node: %s.asini\n", name);
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }


    /* add child as next sibling to child node list */
    xmlCurrentChildNode->next = xmlChildNode;
    xmlCurrentChildNode = xmlCurrentChildNode->next;

    /* ----- set up PARAM node (ecc) */
    xmlChildNode = XLALCreateVOTParamNode("ecc",
                                          NULL,
                                          VOT_REAL8,
                                          NULL,
                                          ecc);
    if(!xmlChildNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create PARAM node: %s.ecc\n", name);
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* add child as next sibling to child node list */
    xmlCurrentChildNode->next = xmlChildNode;
    xmlCurrentChildNode = xmlCurrentChildNode->next;

    /* ----- set up PARAM node (period) */
    xmlChildNode = XLALCreateVOTParamNode("period",
                                          "s",
                                          VOT_REAL8,
                                          NULL,
                                          period);
    if(!xmlChildNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create PARAM node: %s.period\n", name);
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* add child as next sibling to child node list */
    xmlCurrentChildNode->next = xmlChildNode;
    xmlCurrentChildNode = xmlCurrentChildNode->next;

    /* ----- set up RESOURCE node (refTime)*/
    xmlChildNode = XLALLIGOTimeGPS2VOTNode(&pdp->refTime, "refTime" );
    if(!xmlChildNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create RESOURCE node: %s.refTime\n", name );
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* add child as next sibling to child node list */
    xmlCurrentChildNode->next = xmlChildNode;
    xmlCurrentChildNode = xmlCurrentChildNode->next;


     /* ----- set up RESOURCE node (tp)*/
    xmlChildNode = XLALLIGOTimeGPS2VOTNode(&pdp->tp, "tp");
    if(!xmlChildNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create RESOURCE node: tp\n");
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* add child as next sibling to child node list */
    xmlCurrentChildNode->next = xmlChildNode;
    xmlCurrentChildNode = xmlCurrentChildNode->next;
    // ---------- END: binary-orbital parameters ----------

    /* set up parent RESOURCE node*/
    xmlParentNode = XLALCreateVOTResourceNode("PulsarDopplerParams", name, xmlChildNodeList);
    if(!xmlParentNode) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create RESOURCE node: %s\n", name);
        XLAL_ERROR_NULL(XLAL_EFAILED);
    }

    /* return RESOURCE node (needs to be xmlFreeNode'd or xmlFreeDoc'd by caller!!!) */
    return xmlParentNode;

} // XLALPulsarDopplerParams2VOTNode()
/**
 * Set up a full multi-dimensional grid-scan.
 * Currently this only emulates a 'factored' grid-scan with 'sky x Freq x f1dot ...' , but
 * keeps all details within the DopplerScan module for future extension to real multidimensional
 * grids.
 *
 * NOTE: Use 'XLALNextDopplerPos()' to step through this template grid.
 *
 */
DopplerFullScanState *
XLALInitDopplerFullScan ( const DopplerFullScanInit *init       /**< [in] initialization parameters */
                          )
{
  XLAL_CHECK_NULL ( init != NULL, XLAL_EINVAL );

  DopplerFullScanState *thisScan;
  XLAL_CHECK_NULL ( (thisScan = LALCalloc (1, sizeof(*thisScan) )) != NULL, XLAL_ENOMEM );

  thisScan->gridType = init->gridType;

  /* store the user-input spinRange (includes refTime) in DopplerFullScanState */
  thisScan->spinRange.refTime = init->searchRegion.refTime;
  memcpy ( thisScan->spinRange.fkdot, init->searchRegion.fkdot, sizeof(PulsarSpins) );
  memcpy ( thisScan->spinRange.fkdotBand, init->searchRegion.fkdotBand, sizeof(PulsarSpins) );

  // check that some old metric-codes aren't used with refTime!=startTime, which they don't handle correctly
  switch ( thisScan->gridType )
    {
    case GRID_METRIC:
    case GRID_METRIC_SKYFILE:
    case GRID_SPINDOWN_SQUARE: /* square parameter space */
    case GRID_SPINDOWN_AGEBRK: /* age-braking index parameter space */

      XLAL_CHECK_NULL ( XLALGPSDiff ( &init->startTime, &init->searchRegion.refTime ) == 0, XLAL_EINVAL,
                        "NOTE: gridType={metric,4,spin-square,spin-age-brk} only work for refTime (%f) == startTime (%f)!\n",
                        XLALGPSGetREAL8(&(init->searchRegion.refTime)), XLALGPSGetREAL8(&(init->startTime)) );;

      break;
    default:
      break;
    }

  /* which "class" of template grid to generate?: factored, or full-multidim ? */
  switch ( thisScan->gridType )
    {
      /* emulate old 'factored' grids 'sky x f0dot x f1dot x f2dot x f3dot': */
    case GRID_FLAT:
    case GRID_ISOTROPIC:
    case GRID_METRIC:
    case GRID_FILE_SKYGRID:
    case GRID_METRIC_SKYFILE:
      /* backwards-compatibility mode */
      XLAL_CHECK_NULL ( XLALInitFactoredGrid ( thisScan, init ) == XLAL_SUCCESS, XLAL_EFUNC );
      break;

      /* ----- multi-dimensional covering of full parameter space ----- */
    case GRID_FILE_FULLGRID:
      XLAL_CHECK_NULL ( XLALLoadFullGridFile ( thisScan, init ) == XLAL_SUCCESS, XLAL_EFUNC );
      break;

    case GRID_SPINDOWN_SQUARE: /* square parameter space */
    case GRID_SPINDOWN_AGEBRK: /* age-braking index parameter space */
      {
        const size_t n = 2 + PULSAR_MAX_SPINS;

        /* Check that the reference time is the same as the start time */
        XLAL_CHECK_NULL ( XLALGPSCmp ( &thisScan->spinRange.refTime, &init->startTime) == 0, XLAL_EINVAL,
                          "\nGRID_SPINDOWN_{SQUARE,AGEBRK}: This option currently restricts the reference time to be the same as the start time.\n");

        /* Create a vector to hold lattice tiling parameter-space points */
        XLAL_CHECK_NULL ( (thisScan->spindownTilingPoint = gsl_vector_alloc(n)) != NULL, XLAL_ENOMEM,
                          "\nGRID_SPINDOWN_{SQUARE,AGEBRK}: gsl_vector_alloc failed\n");

        /* Create a lattice tiling */
        XLAL_CHECK_NULL ( (thisScan->spindownTiling = XLALCreateLatticeTiling(n)) != NULL, XLAL_EFUNC );

        /* Parse the sky region string and check that it consists of only one point, and set bounds on it */
        SkyRegion XLAL_INIT_DECL(sky);
        XLAL_CHECK_NULL ( XLALParseSkyRegionString ( &sky, init->searchRegion.skyRegionString ) == XLAL_SUCCESS, XLAL_EFUNC );
        XLAL_CHECK_NULL ( sky.numVertices == 1, XLAL_EINVAL, "\nGRID_SPINDOWN_{SQUARE,AGEBRK}: This option can only handle a single sky position.\n");
        XLAL_CHECK_NULL ( sky.vertices[0].system == COORDINATESYSTEM_EQUATORIAL, XLAL_EINVAL, "\nGRID_SPINDOWN_{SQUARE,AGEBRK}: This option only understands COORDINATESYSTEM_EQUATORIAL\n");

        XLAL_CHECK_NULL ( XLALSetLatticeTilingConstantBound(thisScan->spindownTiling, 0, sky.vertices[0].longitude, sky.vertices[0].longitude) == XLAL_SUCCESS, XLAL_EFUNC );

        XLAL_CHECK_NULL ( XLALSetLatticeTilingConstantBound(thisScan->spindownTiling, 1, sky.vertices[0].latitude, sky.vertices[0].latitude) == XLAL_SUCCESS, XLAL_EFUNC );
        if (sky.vertices) {
          XLALFree (sky.vertices);
        }

        /* Set up parameter space */
        if (thisScan->gridType == GRID_SPINDOWN_SQUARE) { /* square parameter space */

          /* Set square bounds on the frequency and spindowns */
          for (size_t i = 0; i < PULSAR_MAX_SPINS; ++i) {
            XLAL_CHECK_NULL ( XLALSetLatticeTilingConstantBound(thisScan->spindownTiling, 2 + i, init->searchRegion.fkdot[i], init->searchRegion.fkdot[i] + init->searchRegion.fkdotBand[i]) == XLAL_SUCCESS, XLAL_EFUNC );
          }

        } else if (thisScan->gridType == GRID_SPINDOWN_AGEBRK) { /* age-braking index parameter space */

          /* Get age and braking index from extra arguments */
          const REAL8 spindownAge = init->extraArgs[0];
          const REAL8 minBraking = init->extraArgs[1];
          const REAL8 maxBraking = init->extraArgs[2];

          /* Set age-braking index parameter space */
          XLAL_CHECK_NULL ( XLAL_SUCCESS == XLALSetLatticeTilingConstantBound(thisScan->spindownTiling, 2, init->searchRegion.fkdot[0], init->searchRegion.fkdot[0] + init->searchRegion.fkdotBand[0]), XLAL_EFUNC );
          XLAL_CHECK_NULL ( XLAL_SUCCESS == XLALSetLatticeTilingF1DotAgeBrakingBound(thisScan->spindownTiling, 2, 3, spindownAge, minBraking, maxBraking), XLAL_EFUNC );
          XLAL_CHECK_NULL ( XLAL_SUCCESS == XLALSetLatticeTilingF2DotBrakingBound(thisScan->spindownTiling, 2, 3, 4, minBraking, maxBraking), XLAL_EFUNC );

          /* This current only goes up to second spindown, so bound higher dimensions */
          for (size_t i = 3; i < PULSAR_MAX_SPINS; ++i) {
            XLAL_CHECK_NULL ( XLAL_SUCCESS == XLALSetLatticeTilingConstantBound(thisScan->spindownTiling, 2 + i, init->searchRegion.fkdot[i], init->searchRegion.fkdot[i] + init->searchRegion.fkdotBand[i]), XLAL_EFUNC );
          }

        }

        /* Create a lattice tiling with Anstar lattice and spindown metric */
        gsl_matrix* metric;
        XLAL_CHECK_NULL ( (metric = gsl_matrix_alloc(n, n)) != NULL, XLAL_ENOMEM );
        gsl_matrix_set_identity(metric);
        gsl_matrix_view spin_metric = gsl_matrix_submatrix(metric, 2, 2, PULSAR_MAX_SPINS, PULSAR_MAX_SPINS);
        XLAL_CHECK_NULL ( XLALSpindownMetric(&spin_metric.matrix, init->Tspan) == XLAL_SUCCESS, XLAL_EFUNC );
        XLAL_CHECK_NULL ( XLALSetTilingLatticeAndMetric(thisScan->spindownTiling, "Ans", metric, init->metricMismatch) == XLAL_SUCCESS, XLAL_EFUNC );

        /* Create iterator over flat lattice tiling */
        XLAL_CHECK_NULL ( (thisScan->spindownTilingItr = XLALCreateLatticeTilingIterator(thisScan->spindownTiling, n)) != NULL, XLAL_EFUNC );

        /* Cleanup */
        gsl_matrix_free(metric);

      }

      break;

    default:
      XLAL_ERROR_NULL ( XLAL_EINVAL, "\nInvalid grid type '%d'\n\n", init->gridType );
      break;
    } /* switch gridType */

  /* we're ready */
  thisScan->state = STATE_READY;

  /* return result */
  return thisScan;

} // XLALInitDopplerFullScan()