Example #1
0
int main(int argc, char *argv[])
{
   FILE *fftfile, *candfile;
   float powargr, powargi, *powers = NULL, *minifft;
   float norm, numchunks, *powers_pos;
   int nbins, newncand, nfftsizes, fftlen, halffftlen, binsleft;
   int numtoread, filepos = 0, loopct = 0, powers_offset, ncand2;
   int ii, ct, newper = 0, oldper = 0, numsumpow = 1;
   double T, totnumsearched = 0.0, minsig = 0.0, min_orb_p, max_orb_p;
   char *rootfilenm, *notes;
   fcomplex *data = NULL;
   rawbincand tmplist[MININCANDS], *list;
   infodata idata;
   struct tms runtimes;
   double ttim, utim, stim, tott;
   Cmdline *cmd;
   fftwf_plan fftplan;

   /* Prep the timer */

   tott = times(&runtimes) / (double) CLK_TCK;

   /* Call usage() if we have no command line arguments */

   if (argc == 1) {
      Program = argv[0];
      printf("\n");
      usage();
      exit(1);
   }

   /* Parse the command line using the excellent program Clig */

   cmd = parseCmdline(argc, argv);

#ifdef DEBUG
   showOptionValues();
#endif

   printf("\n\n");
   printf("     Phase Modulation Pulsar Search Routine\n");
   printf("              by Scott M. Ransom\n\n");

   {
      int hassuffix = 0;
      char *suffix;

      hassuffix = split_root_suffix(cmd->argv[0], &rootfilenm, &suffix);
      if (hassuffix) {
         if (strcmp(suffix, "fft") != 0) {
            printf("\nInput file ('%s') must be a FFT file ('.fft')!\n\n",
                   cmd->argv[0]);
            free(suffix);
            exit(0);
         }
         free(suffix);
      } else {
         printf("\nInput file ('%s') must be a FFT file ('.fft')!\n\n",
                cmd->argv[0]);
         exit(0);
      }
   }

   /* Read the info file */

   readinf(&idata, rootfilenm);
   T = idata.N * idata.dt;
   if (strlen(remove_whitespace(idata.object)) > 0) {
      printf("Analyzing '%s' data from '%s'.\n\n",
             remove_whitespace(idata.object), cmd->argv[0]);
   } else {
      printf("Analyzing data from '%s'.\n\n", cmd->argv[0]);
   }
   min_orb_p = MINORBP;
   if (cmd->noaliasP)
      max_orb_p = T / 2.0;
   else
      max_orb_p = T / 1.2;

   /* open the FFT file and get its length */

   fftfile = chkfopen(cmd->argv[0], "rb");
   nbins = chkfilelen(fftfile, sizeof(fcomplex));

   /* Check that cmd->maxfft is an acceptable power of 2 */

   ct = 4;
   ii = 1;
   while (ct < MAXREALFFT || ii) {
      if (ct == cmd->maxfft)
         ii = 0;
      ct <<= 1;
   }
   if (ii) {
      printf("\n'maxfft' is out of range or not a power-of-2.\n\n");
      exit(1);
   }

   /* Check that cmd->minfft is an acceptable power of 2 */

   ct = 4;
   ii = 1;
   while (ct < MAXREALFFT || ii) {
      if (ct == cmd->minfft)
         ii = 0;
      ct <<= 1;
   }
   if (ii) {
      printf("\n'minfft' is out of range or not a power-of-2.\n\n");
      exit(1);
   }

   /* Low and high Fourier freqs to check */

   if (cmd->floP) {
      cmd->rlo = floor(cmd->flo * T);
      if (cmd->rlo < cmd->lobin)
         cmd->rlo = cmd->lobin;
      if (cmd->rlo > cmd->lobin + nbins - 1) {
         printf("\nLow frequency to search 'flo' is greater than\n");
         printf("   the highest available frequency.  Exiting.\n\n");
         exit(1);
      }
   } else {
      cmd->rlo = 1.0;
      if (cmd->rlo < cmd->lobin)
         cmd->rlo = cmd->lobin;
      if (cmd->rlo > cmd->lobin + nbins - 1) {
         printf("\nLow frequency to search 'rlo' is greater than\n");
         printf("   the available number of points.  Exiting.\n\n");
         exit(1);
      }
   }
   if (cmd->fhiP) {
      cmd->rhi = ceil(cmd->fhi * T);
      if (cmd->rhi > cmd->lobin + nbins - 1)
         cmd->rhi = cmd->lobin + nbins - 1;
      if (cmd->rhi < cmd->rlo) {
         printf("\nHigh frequency to search 'fhi' is less than\n");
         printf("   the lowest frequency to search 'flo'.  Exiting.\n\n");
         exit(1);
      }
   } else if (cmd->rhiP) {
      if (cmd->rhi > cmd->lobin + nbins - 1)
         cmd->rhi = cmd->lobin + nbins - 1;
      if (cmd->rhi < cmd->rlo) {
         printf("\nHigh frequency to search 'rhi' is less than\n");
         printf("   the lowest frequency to search 'rlo'.  Exiting.\n\n");
         exit(1);
      }
   }

   /* Determine how many different mini-fft sizes we will use */

   nfftsizes = 1;
   ii = cmd->maxfft;
   while (ii > cmd->minfft) {
      ii >>= 1;
      nfftsizes++;
   }

   /* Allocate some memory and prep some variables.             */
   /* For numtoread, the 6 just lets us read extra data at once */

   numtoread = 6 * cmd->maxfft;
   if (cmd->stack == 0)
      powers = gen_fvect(numtoread);
   minifft = (float *) fftwf_malloc(sizeof(float) *
                                    (cmd->maxfft * cmd->numbetween + 2));
   ncand2 = 2 * cmd->ncand;
   list = (rawbincand *) malloc(sizeof(rawbincand) * ncand2);
   for (ii = 0; ii < ncand2; ii++)
      list[ii].mini_sigma = 0.0;
   for (ii = 0; ii < MININCANDS; ii++)
      tmplist[ii].mini_sigma = 0.0;
   filepos = cmd->rlo - cmd->lobin;
   numchunks = (float) (cmd->rhi - cmd->rlo) / numtoread;
   printf("Searching...\n");
   printf("   Amount complete = %3d%%", 0);
   fflush(stdout);

   /* Prep FFTW */
   read_wisdom();

   /* Loop through fftfile */

   while ((filepos + cmd->lobin) < cmd->rhi) {

      /* Calculate percentage complete */

      newper = (int) (loopct / numchunks * 100.0);

      if (newper > oldper) {
         newper = (newper > 99) ? 100 : newper;
         printf("\r   Amount complete = %3d%%", newper);
         oldper = newper;
         fflush(stdout);
      }

      /* Adjust our search parameters if close to end of zone to search */

      binsleft = cmd->rhi - (filepos + cmd->lobin);
      if (binsleft < cmd->minfft)
         break;
      if (binsleft < numtoread) {       /* Change numtoread */
         numtoread = cmd->maxfft;
         while (binsleft < numtoread) {
            cmd->maxfft /= 2;
            numtoread = cmd->maxfft;
         }
      }
      fftlen = cmd->maxfft;

      /* Read from fftfile */

      if (cmd->stack == 0) {
         data = read_fcomplex_file(fftfile, filepos, numtoread);
         for (ii = 0; ii < numtoread; ii++)
            powers[ii] = POWER(data[ii].r, data[ii].i);
         numsumpow = 1;
      } else {
         powers = read_float_file(fftfile, filepos, numtoread);
         numsumpow = cmd->stack;
      }
      if (filepos == 0)
         powers[0] = 1.0;

      /* Chop the powers that are way above the median level */

      prune_powers(powers, numtoread, numsumpow);

      /* Loop through the different small FFT sizes */

      while (fftlen >= cmd->minfft) {

         halffftlen = fftlen / 2;
         powers_pos = powers;
         powers_offset = 0;

         /* Create the appropriate FFT plan */

         fftplan = fftwf_plan_dft_r2c_1d(cmd->interbinP ? fftlen : 2 * fftlen,
                                         minifft, (fftwf_complex *) minifft,
                                         FFTW_PATIENT);

         /* Perform miniffts at each section of the powers array */

         while ((numtoread - powers_offset) >
                (int) ((1.0 - cmd->overlap) * cmd->maxfft + DBLCORRECT)) {

            /* Copy the proper amount and portion of powers into minifft */

            memcpy(minifft, powers_pos, fftlen * sizeof(float));
            /* For Fourier interpolation use a zeropadded FFT */
            if (cmd->numbetween > 1 && !cmd->interbinP) {
               for (ii = fftlen; ii < cmd->numbetween * fftlen; ii++)
                  minifft[ii] = 0.0;
            }

            /* Perform the minifft */

            fftwf_execute(fftplan);

            /* Normalize and search the miniFFT */

            norm = sqrt(fftlen * numsumpow) / minifft[0];
            for (ii = 0; ii < (cmd->interbinP ? fftlen + 1 : 2 * fftlen + 1); ii++)
               minifft[ii] *= norm;
            search_minifft((fcomplex *) minifft, halffftlen, min_orb_p,
                           max_orb_p, tmplist, MININCANDS, cmd->harmsum,
                           cmd->numbetween, idata.N, T,
                           (double) (powers_offset + filepos + cmd->lobin),
                           cmd->interbinP ? INTERBIN : INTERPOLATE,
                           cmd->noaliasP ? NO_CHECK_ALIASED : CHECK_ALIASED);

            /* Check if the new cands should go into the master cand list */

            for (ii = 0; ii < MININCANDS; ii++) {
               if (tmplist[ii].mini_sigma > minsig) {

                  /* Check to see if another candidate with these properties */
                  /* is already in the list.                                 */

                  if (not_already_there_rawbin(tmplist[ii], list, ncand2)) {
                     list[ncand2 - 1] = tmplist[ii];
                     minsig = percolate_rawbincands(list, ncand2);
                  }
               } else {
                  break;
               }
               /* Mini-fft search for loop */
            }

            totnumsearched += fftlen;
            powers_pos += (int) (cmd->overlap * fftlen);
            powers_offset = powers_pos - powers;

            /* Position of mini-fft in data set while loop */
         }

         fftwf_destroy_plan(fftplan);
         fftlen >>= 1;

         /* Size of mini-fft while loop */
      }

      if (cmd->stack == 0)
         vect_free(data);
      else
         vect_free(powers);
      filepos += (numtoread - (int) ((1.0 - cmd->overlap) * cmd->maxfft));
      loopct++;

      /* File position while loop */
   }

   /* Print the final percentage update */

   printf("\r   Amount complete = %3d%%\n\n", 100);

   /* Print the number of frequencies searched */

   printf("Searched %.0f pts (including interbins).\n\n", totnumsearched);

   printf("Timing summary:\n");
   tott = times(&runtimes) / (double) CLK_TCK - tott;
   utim = runtimes.tms_utime / (double) CLK_TCK;
   stim = runtimes.tms_stime / (double) CLK_TCK;
   ttim = utim + stim;
   printf("    CPU time: %.3f sec (User: %.3f sec, System: %.3f sec)\n",
          ttim, utim, stim);
   printf("  Total time: %.3f sec\n\n", tott);

   printf("Writing result files and cleaning up.\n");

   /* Count how many candidates we actually have */

   ii = 0;
   while (ii < ncand2 && list[ii].mini_sigma != 0)
      ii++;
   newncand = (ii > cmd->ncand) ? cmd->ncand : ii;

   /* Set our candidate notes to all spaces */

   notes = malloc(sizeof(char) * newncand * 18 + 1);
   for (ii = 0; ii < newncand; ii++)
      strncpy(notes + ii * 18, "                     ", 18);

   /* Check the database for possible known PSR detections */

   if (idata.ra_h && idata.dec_d) {
      for (ii = 0; ii < newncand; ii++) {
         comp_rawbin_to_cand(&list[ii], &idata, notes + ii * 18, 0);
      }
   }

   /* Compare the candidates with each other */

   compare_rawbin_cands(list, newncand, notes);

   /* Send the candidates to the text file */

   file_rawbin_candidates(list, notes, newncand, cmd->harmsum, rootfilenm);

   /* Write the binary candidate file */
   {
      char *candnm;

      candnm = (char *) calloc(strlen(rootfilenm) + 15, sizeof(char));
      sprintf(candnm, "%s_bin%d.cand", rootfilenm, cmd->harmsum);
      candfile = chkfopen(candnm, "wb");
      chkfwrite(list, sizeof(rawbincand), (unsigned long) newncand, candfile);
      fclose(candfile);
      free(candnm);
   }

   /* Free our arrays and close our files */

   if (cmd->stack == 0)
      vect_free(powers);
   free(list);
   fftwf_free(minifft);
   free(notes);
   free(rootfilenm);
   fclose(fftfile);
   printf("Done.\n\n");
   return (0);
}
Example #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;
   }
}