示例#1
0
void spread_no_pad(fcomplex * data, int numdata,
                   fcomplex * result, int numresult, int numbetween)
  /* Prepare the data array for correlation by spreading         */
  /*      the input data array.                                  */
  /* Arguments:                                                  */
  /*   'data' is the FFT array to be prepared                    */
  /*   'numdata' is the number of complex points in 'data'       */
  /*   'result' is the prepped data array                        */
  /*   'numresult' is the number of complex points in 'result'   */
  /*   'numbetween' is the number of interpolated pts per bin    */
{
   spread_with_pad(data, numdata, result, numresult, numbetween, 0);
}
示例#2
0
void search_minifft(fcomplex * minifft, int numminifft,
                    double min_orb_p, double max_orb_p,
                    rawbincand * cands, int numcands, int numharmsum,
                    int numbetween, double numfullfft, double timefullfft,
                    double lorfullfft, presto_interptype interptype,
                    presto_checkaliased checkaliased)
  /* This routine searches a short FFT (usually produced using the   */
  /* MiniFFT binary search method) and returns a candidte vector     */
  /* containing information about the best binary candidates found.  */
  /* The routine uses either interbinning or interpolation as well   */
  /* as harmonic summing during the search.                          */
  /* Arguments:                                                      */
  /*   'minifft' is the FFT to search (complex valued)               */
  /*   'numminifft' is the number of complex points in 'minifft'     */
  /*   'min_orb_p' is the minimum orbital period (s) to search       */
  /*   'max_orb_p' is the maximum orbital period (s) to search       */
  /*   'cands' is a pre-allocated vector of rawbincand type in which */
  /*      the sorted (in decreasing sigma) candidates are returned   */
  /*   'numcands' is the length of the 'cands' vector                */
  /*   'numharmsum' the number of harmonics to sum during the search */
  /*   'numbetween' the points to interpolate per bin                */
  /*   'numfullfft' the number of points in the original long FFT    */
  /*   'timefullfft' the duration of the original time series (s)    */
  /*   'lorfullfft' the 1st bin of the long FFT that was miniFFT'd   */
  /*   'interptype' is either INTERBIN or INTERPOLATE.               */
/*      INTERBIN = (interbinning) is fast but less sensitive.        */
/*         NOTE:  INTERBINNING is conducted by this routine!         */
/*      INTERPOLATE = (Fourier interpolation) is slower but more     */
/*        sensitive.                                                 */
/*         NOTE:  The interpolation is assumed to ALREADY have been  */
/*                completed by the calling function!  The easiest    */
/*                way is by zero-padding to 2*numminifft and FFTing. */
/*                If you use this method, make sure numminifft is the*/
/*                original length rather than the interpolated       */
/*                length and also make sure numbetween is correct.   */
  /*   'checkaliased' is either CHECK_ALIASED or NO_CHECK_ALIASED.   */
  /*      NO_CHECK_ALIASED = harmonic summing does not include       */
  /*        aliased freqs making it faster but less sensitive.       */
  /*      CHECK_ALIASED = harmonic summing includes aliased freqs    */
  /*        making it slower but more sensitive.                     */
{
   int ii, jj, fftlen, offset, numtosearch = 0, lobin, hibin, numspread = 0;
   float powargr, powargi, *fullpows = NULL, *sumpows;
   double twobypi, minpow, minsig, dr, numindep;
   fcomplex *spread;

   /* Override the value of numbetween if interbinning */

   if (interptype == INTERBIN)
      numbetween = 2;

   /* Prep some other values we will need */

   dr = 1.0 / (double) numbetween;
   twobypi = 2.0 / PI;
   fftlen = numminifft * numbetween;
   for (ii = 0; ii < numcands; ii++) {
      cands[ii].mini_sigma = 0.0;
      cands[ii].mini_power = 0.0;
   }
   lobin = ceil(2 * numminifft * min_orb_p / timefullfft);
   if (lobin <= 0)
      lobin = 1;
   hibin = floor(2 * numminifft * max_orb_p / timefullfft);
   if (hibin >= 2 * numminifft)
      hibin = 2 * numminifft - 1;
   lobin *= numbetween;
   hibin *= numbetween;

   /* Spread and interpolate the fft */

   numtosearch = (checkaliased == CHECK_ALIASED) ? 2 * fftlen : fftlen;
   numspread = numminifft * numbetween + 1;
   if (interptype == INTERPOLATE) {     /* INTERPOLATE */
      spread = minifft;
   } else {                     /* INTERBIN */
      spread = gen_cvect(numspread);
      spread_with_pad(minifft, numminifft, spread, numspread, numbetween, 0);
      for (ii = 1; ii < fftlen; ii += 2) {
         spread[ii].r = twobypi * (spread[ii - 1].r - spread[ii + 1].r);
         spread[ii].i = twobypi * (spread[ii - 1].i - spread[ii + 1].i);
      }
   }
   spread[0].r = spread[fftlen].r = 1.0;
   spread[0].i = spread[fftlen].i = 0.0;

   fullpows = gen_fvect(numtosearch);
   fullpows[0] = 1.0;
   if (checkaliased == CHECK_ALIASED)
      fullpows[fftlen] = 1.0;   /* used to be nyquist^2 */

   /* The following wraps the data around the Nyquist freq such that */
   /* we consider aliased frequencies as well (If CHECK_ALIASED).    */

   if (checkaliased == CHECK_ALIASED)
      for (ii = 1, jj = numtosearch - 1; ii < fftlen; ii++, jj--)
         fullpows[ii] = fullpows[jj] = POWER(spread[ii].r, spread[ii].i);
   else
      for (ii = 1; ii < numtosearch; ii++)
         fullpows[ii] = POWER(spread[ii].r, spread[ii].i);
   if (interptype == INTERBIN)
      vect_free(spread);

   /* Search the raw powers */

   numindep = hibin - lobin + 1.0;
   minpow = power_for_sigma(MINRETURNSIG, 1, numindep);
   for (ii = lobin; ii < hibin; ii++) {
      if (fullpows[ii] > minpow) {
         cands[numcands - 1].mini_r = dr * (double) ii;
         cands[numcands - 1].mini_power = fullpows[ii];
         cands[numcands - 1].mini_numsum = 1.0;
         cands[numcands - 1].mini_sigma = candidate_sigma(fullpows[ii], 1, numindep);
         minsig = percolate_rawbincands(cands, numcands);
         if (cands[numcands - 1].mini_power > minpow)
            minpow = cands[numcands - 1].mini_power;
      }
   }

   /* If needed, sum and search the harmonics */

   if (numharmsum > 1) {
      sumpows = gen_fvect(numtosearch);
      memcpy(sumpows, fullpows, sizeof(float) * numtosearch);
      for (ii = 2; ii <= numharmsum; ii++) {
         offset = ii / 2;
         numindep = (hibin - lobin + 1.0) / (double) ii;
         if (cands[numcands - 1].mini_sigma < MINRETURNSIG)
            minsig = MINRETURNSIG;
         else
            minsig = cands[numcands - 1].mini_sigma;
         minpow = power_for_sigma(minsig, ii, numindep);
         for (jj = lobin * ii; jj < hibin; jj++) {
            sumpows[jj] += fullpows[(jj + offset) / ii];
            if (sumpows[jj] > minpow) {
               cands[numcands - 1].mini_r = (dr * (double) jj) / ii;
               cands[numcands - 1].mini_power = sumpows[jj];
               cands[numcands - 1].mini_numsum = (double) ii;
               cands[numcands - 1].mini_sigma =
                   candidate_sigma(sumpows[jj], ii, numindep);
               minsig = percolate_rawbincands(cands, numcands);
               if (minsig > MINRETURNSIG)
                  minpow = power_for_sigma(minsig, ii, numindep);
            }
         }
      }
      vect_free(sumpows);
   }
   vect_free(fullpows);

   /* Add the rest of the rawbincand data to the candidate array */

   for (ii = 0; ii < numcands; ii++) {
      cands[ii].full_N = numfullfft;
      cands[ii].full_T = timefullfft;
      cands[ii].full_lo_r = lorfullfft;
      cands[ii].mini_N = 2 * numminifft;        /* # of real points */
      cands[ii].psr_p = timefullfft / (lorfullfft + numminifft);
      cands[ii].orb_p = timefullfft * cands[ii].mini_r / cands[ii].mini_N;
   }
}
示例#3
0
fftcand *search_fft(fcomplex * fft, int numfft, int lobin, int hibin,
                    int numharmsum, int numbetween,
                    presto_interptype interptype,
                    float norm, float sigmacutoff, int *numcands,
                    float *powavg, float *powvar, float *powmax)
/* This routine searches a short FFT of 'numfft' complex freqs      */
/* and returns a candidate vector of fftcand structures containing  */
/* information about the best candidates found.                     */
/* The routine uses either interbinning or interpolation as well    */
/* as harmonic summing during the search.                           */
/* The number of candidates returned is either 'numcands' if != 0,  */
/* or is determined automatically by 'sigmacutoff' -- which         */
/* takes into account the number of bins searched.                  */
/* The returned vector is sorted in order of decreasing power.      */
/* Arguments:                                                       */
/*   'fft' is the FFT to search (complex valued)                    */
/*   'numfft' is the number of complex points in 'fft'              */
/*   'lobin' is the lowest Fourier freq to search                   */
/*   'hibin' is the highest Fourier freq to search                  */
/*   'numharmsum' the number of harmonics to sum during the search  */
/*   'numbetween' the points to interpolate per bin                 */
/*   'interptype' is either INTERBIN or INTERPOLATE.                */
/*      INTERBIN = (interbinning) is fast but less sensitive.       */
/*         NOTE:  INTERBINNING is conducted by this routine!        */
/*      INTERPOLATE = (Fourier interpolation) is slower but more    */
/*        sensitive.                                                */
/*         NOTE:  The interpolation is assumed to ALREADY have been */
/*                completed by the calling function!  The easiest   */
/*                way is by zero-padding to 2*numfft and FFTing.    */
/*                If you use this method, make sure numfft is the   */
/*                original length rather than the interpolated      */
/*                length and also make sure numbetween is correct.  */
/*   'norm' is the normalization constant to multiply each power by */
/*   'sigmacutoff' if the number of candidates will be determined   */
/*      automatically, is the minimum Gaussian significance of      */
/*      candidates to keep -- taking into account the number of     */
/*      bins searched                                               */
/*   'numcands' if !0, is the number of candates to return.         */
/*      if 0, is a return value giving the number of candidates.    */
/*   'powavg' is a return value giving the average power level      */
/*   'powvar' is a return value giving the power level variance     */
/*   'powmax' is a return value giving the maximum power            */
{
   int ii, jj, offset, numtosearch, dynamic = 0;
   int numspread = 0, nc = 0, startnc = 10;
   float powargr, powargi, *fullpows = NULL, *sumpows, ftmp;
   double twobypi, minpow = 0.0, tmpminsig = 0.0, dr, davg, dvar;
   fftcand *cands, newcand;
   fcomplex *spread;

   /* Override the value of numbetween if interbinning */

   if (interptype == INTERBIN)
      numbetween = 2;
   norm = 1.0 / norm;
   *powmax = 0.0;

   /* Decide if we will manage the number of candidates */

   if (*numcands > 0)
      startnc = *numcands;
   else {
      dynamic = 1;
      minpow = power_for_sigma(sigmacutoff, 1, hibin - lobin);
   }
   cands = (fftcand *) malloc(startnc * sizeof(fftcand));
   for (ii = 0; ii < startnc; ii++)
      cands[ii].sig = 0.0;

   /* Prep some other values we will need */

   dr = 1.0 / (double) numbetween;
   twobypi = 2.0 / PI;
   numtosearch = numfft * numbetween;

   /* Spread and interpolate the fft */

   numspread = numfft * numbetween + 1;
   if (interptype == INTERPOLATE) {     /* INTERPOLATE */
      spread = fft;
   } else {                     /* INTERBIN */
      spread = gen_cvect(numspread);
      spread_with_pad(fft, numfft, spread, numspread, numbetween, 0);
      for (ii = 1; ii < numtosearch; ii += 2) {
         spread[ii].r = twobypi * (spread[ii - 1].r - spread[ii + 1].r);
         spread[ii].i = twobypi * (spread[ii - 1].i - spread[ii + 1].i);
      }
   }
   spread[0].r = spread[numtosearch].r = 1.0;
   spread[0].i = spread[numtosearch].i = 0.0;

   /* First generate the original powers in order to         */
   /* calculate the statistics.  Yes, this is inefficient... */

   fullpows = gen_fvect(numtosearch);
   for (ii = lobin, jj = 0; ii < hibin; ii++, jj++) {
      ftmp = POWER(fft[ii].r, fft[ii].i) * norm;
      fullpows[jj] = ftmp;
      if (ftmp > *powmax)
         *powmax = ftmp;
   }
   avg_var(fullpows, hibin - lobin, &davg, &dvar);
   *powavg = davg;
   *powvar = dvar;
   fullpows[0] = 1.0;
   for (ii = 1; ii < numtosearch; ii++)
      fullpows[ii] = POWER(spread[ii].r, spread[ii].i) * norm;
   if (interptype == INTERBIN)
      vect_free(spread);

   /* Search the raw powers */

   for (ii = lobin * numbetween; ii < hibin * numbetween; ii++) {
      if (fullpows[ii] > minpow) {
         newcand.r = dr * (double) ii;
         newcand.p = fullpows[ii];
         newcand.sig = candidate_sigma(fullpows[ii], 1, hibin - lobin);
         newcand.nsum = 1;
         cands[startnc - 1] = newcand;
         tmpminsig = percolate_fftcands(cands, startnc);
         if (dynamic) {
            nc++;
            if (nc == startnc) {
               startnc *= 2;
               cands = (fftcand *) realloc(cands, startnc * sizeof(fftcand));
               for (jj = nc; jj < startnc; jj++)
                  cands[jj].sig = 0.0;
            }
         } else {
            minpow = cands[startnc - 1].p;
            if (nc < startnc)
               nc++;
         }
      }
   }

   /* If needed, sum and search the harmonics */

   if (numharmsum > 1) {
      sumpows = gen_fvect(numtosearch);
      memcpy(sumpows, fullpows, sizeof(float) * numtosearch);
      for (ii = 2; ii <= numharmsum; ii++) {
         offset = ii / 2;
         if (dynamic)
            minpow = power_for_sigma(sigmacutoff, ii, hibin - lobin);
         else
            minpow = power_for_sigma(tmpminsig, ii, hibin - lobin);
         for (jj = lobin * numbetween; jj < numtosearch; jj++) {
            sumpows[jj] += fullpows[(jj + offset) / ii];
            if (sumpows[jj] > minpow) {
               newcand.r = dr * (double) jj;
               newcand.p = sumpows[jj];
               newcand.sig = candidate_sigma(sumpows[jj], ii, hibin - lobin);
               newcand.nsum = ii;
               cands[startnc - 1] = newcand;
               tmpminsig = percolate_fftcands(cands, startnc);
               if (dynamic) {
                  nc++;
                  if (nc == startnc) {
                     startnc *= 2;
                     cands = (fftcand *) realloc(cands, startnc * sizeof(fftcand));
                     for (jj = nc; jj < startnc; jj++)
                        cands[jj].sig = 0.0;
                  }
               } else {
                  minpow = power_for_sigma(tmpminsig, ii, hibin - lobin);
                  if (nc < startnc)
                     nc++;
               }
            }
         }
      }
      vect_free(sumpows);
   }
   vect_free(fullpows);

   /* Chop off the unused parts of the dynamic array */

   if (dynamic)
      cands = (fftcand *) realloc(cands, nc * sizeof(fftcand));
   *numcands = nc;
   return cands;
}