예제 #1
0
파일: explorefft.c 프로젝트: bretonr/presto
static fftpart *get_fftpart(int rlo, int numr)
{
   int ii, jj, index;
   float powargr, powargi, tmppwr, chunk[LOCALCHUNK];
   fftpart *fp;

   if (rlo + numr > Nfft) {
      return NULL;
   } else {
      fp = (fftpart *) malloc(sizeof(fftpart));
      fp->rlo = rlo;
      fp->numamps = numr;
#ifdef USEMMAP
      fp->amps = (fcomplex *) mmap(0, sizeof(fcomplex) * numr, PROT_READ,
                                   MAP_SHARED, mmap_file, 0);
#else
      fp->amps = read_fcomplex_file(fftfile, rlo, numr);
#endif
      if (rlo == 0)
         r0 = fp->amps[0].r;
      fp->rawpowers = gen_fvect(fp->numamps);
      fp->medians = gen_fvect(fp->numamps / LOCALCHUNK);
      fp->normvals = gen_fvect(fp->numamps / LOCALCHUNK);
      fp->maxrawpow = 0.0;
      for (ii = 0; ii < fp->numamps / LOCALCHUNK; ii++) {
         index = ii * LOCALCHUNK;
         for (jj = 0; jj < LOCALCHUNK; jj++, index++) {
            tmppwr = POWER(fp->amps[index].r, fp->amps[index].i);
            if (tmppwr > fp->maxrawpow)
               if (rlo || (rlo == 0 && index > 0))
                  fp->maxrawpow = tmppwr;
            fp->rawpowers[index] = tmppwr;
            chunk[jj] = tmppwr;
         }
         if (rlo == 0 && ii == 0) {
            chunk[0] = 1.0;
            fp->rawpowers[0] = 1.0;
         }
         fp->medians[ii] = median(chunk, LOCALCHUNK);
         fp->normvals[ii] = 1.0 / (1.4426950408889634 * fp->medians[ii]);
      }
      return fp;
   }
}
예제 #2
0
fcomplex *get_fourier_amplitudes(int lobin, int numbins, accelobs * obs)
{
    if (obs->mmap_file || obs->dat_input) {
        fcomplex *tmpdata = gen_cvect(numbins);
        int offset = 0;
        // zero-pad if we try to read before the beginning of the FFT
        if (lobin - obs->lobin < 0) {
            fcomplex zeros = {0.0, 0.0};
            int ii;
            offset = abs(lobin - obs->lobin);
            for (ii = 0 ; ii < offset ; ii++)
                tmpdata[ii] = zeros;
        }            
        memcpy(tmpdata + offset, 
               (fcomplex *) (obs->fft + (lobin - obs->lobin) + offset),
               sizeof(fcomplex) * (numbins - offset));
        return tmpdata;
    } else {
        return read_fcomplex_file(obs->fftfile, lobin - obs->lobin, numbins);
    }
}
예제 #3
0
void max_rz_file_harmonics(FILE * fftfile, int num_harmonics,
                             int lobin,
                             double rin, double zin,
                             double *rout, double *zout, rderivs derivs[],
                             double maxpow[])
/* Return the Fourier frequency and Fourier f-dot that      */
/* maximizes the power of the candidate in 'fftfile'.       */
/* WARNING: not tested */
{
   int i;
   double maxz, rin_int, rin_frac;
   int kern_half_width, filedatalen, extra = 10;
   int* r_offset;
   fcomplex** filedata;

   r_offset = (int*)malloc(sizeof(int)*num_harmonics);
   filedata = (fcomplex**)malloc(sizeof(fcomplex*)*num_harmonics);
   maxz = fabs(zin*num_harmonics) + 4.0;
   kern_half_width = z_resp_halfwidth(maxz, HIGHACC);
   filedatalen = 2 * kern_half_width + extra;

   for (i=1;i<=num_harmonics;i++) {
       rin_frac = modf(rin*i, &rin_int);
       r_offset[i-1] = (int) rin_int - filedatalen / 2 + lobin;
       filedata[i-1] = read_fcomplex_file(fftfile, r_offset[i-1], filedatalen);
   }
   rin_frac = modf(rin, &rin_int);
   max_rz_arr_harmonics(filedata, num_harmonics,
                        r_offset,
                        filedatalen, rin_frac + filedatalen / 2,
                        zin, rout, zout, derivs,
                        maxpow);

   *rout += r_offset[0];
   for (i=1;i<=num_harmonics;i++) {
       vect_free(filedata[i-1]);
   }
   free(r_offset);
   free(filedata);
}
예제 #4
0
double max_rz_file(FILE * fftfile, double rin, double zin,
                   double *rout, double *zout, rderivs * derivs)
/* Return the Fourier frequency and Fourier f-dot that      */
/* maximizes the power of the candidate in 'fftfile'.       */
{
   double maxz, maxpow, rin_int, rin_frac;
   int kern_half_width, filedatalen, startbin, extra = 10;
   fcomplex *filedata;

   maxz = fabs(zin) + 4.0;
   rin_frac = modf(rin, &rin_int);
   kern_half_width = z_resp_halfwidth(maxz, HIGHACC);
   filedatalen = 2 * kern_half_width + extra;
   startbin = (int) rin_int - filedatalen / 2;

   filedata = read_fcomplex_file(fftfile, startbin, filedatalen);
   maxpow = max_rz_arr(filedata, filedatalen, rin_frac + filedatalen / 2,
                       zin, rout, zout, derivs);
   *rout += startbin;
   vect_free(filedata);
   return maxpow;
}
예제 #5
0
int main(int argc, char *argv[])
/* dftfold:  Does complex plane vector addition of a DFT freq */
/* Written by Scott Ransom on 31 Aug 00 based on Ransom and   */
/* Eikenberry paper I (to be completed sometime...).          */
{
   FILE *infile;
   char infilenm[200], outfilenm[200];
   int dataperread;
   unsigned long N;
   double T, rr = 0.0, norm = 1.0;
   dftvector dftvec;
   infodata idata;
   Cmdline *cmd;

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

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

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

   cmd = parseCmdline(argc, argv);

#ifdef DEBUG
   showOptionValues();
#endif

   printf("\n\n");
   printf("        DFT Vector Folding Routine\n");
   printf("            by Scott M. Ransom\n");
   printf("              31 August, 2000\n\n");

   /* Open the datafile and read the info file */

   sprintf(infilenm, "%s.dat", cmd->argv[0]);
   infile = chkfopen(infilenm, "rb");
   readinf(&idata, cmd->argv[0]);

   /* The number of points in datafile */

   N = chkfilelen(infile, sizeof(float));
   dataperread = N / cmd->numvect;
/*   N = cmd->numvect * dataperread; */
   T = N * idata.dt;

   /* Calculate the Fourier frequency */

   if (!cmd->rrP) {
      if (cmd->ffP)
         rr = cmd->ff;
      else if (cmd->ppP)
         rr = T / cmd->pp;
      else {
         printf("\n  You must specify a frequency to fold!  Exiting.\n\n");
      }
   } else
      rr = cmd->rr;

   /* Calculate the amplitude normalization if required */

   if (cmd->normP)
      norm = 1.0 / sqrt(cmd->norm);
   else if (cmd->fftnormP) {
      FILE *fftfile;
      int kern_half_width, fftdatalen, startbin;
      double rrfrac, rrint;
      char fftfilenm[200];
      fcomplex *fftdata;

      sprintf(fftfilenm, "%s.fft", cmd->argv[0]);
      fftfile = chkfopen(fftfilenm, "rb");
      kern_half_width = r_resp_halfwidth(HIGHACC);
      fftdatalen = 2 * kern_half_width + 10;
      rrfrac = modf(rr, &rrint);
      startbin = (int) rrint - fftdatalen / 2;
      fftdata = read_fcomplex_file(fftfile, startbin, fftdatalen);
      norm = 1.0 / sqrt(get_localpower3d(fftdata, fftdatalen,
                                         rrfrac + fftdatalen / 2, 0.0, 0.0));
      vect_free(fftdata);
      fclose(fftfile);
   }

   /* Initialize the dftvector */

   init_dftvector(&dftvec, dataperread, cmd->numvect, idata.dt, rr, norm, T);

   /* Show our folding values */

   printf("\nFolding data from '%s':\n", infilenm);
   printf("   Folding Fourier Freq = %.5f\n", rr);
   printf("      Folding Freq (Hz) = %-.11f\n", rr / T);
   printf("     Folding Period (s) = %-.14f\n", T / rr);
   printf("  Points per sub-vector = %d\n", dftvec.n);
   printf("  Number of sub-vectors = %d\n", dftvec.numvect);
   printf(" Normalization constant = %g\n", norm * norm);

   /* Perform the actual vector addition */

   {
      int ii, jj;
      float *data;
      double real, imag, sumreal = 0.0, sumimag = 0.0;
      double theta, aa, bb, cc, ss, dtmp;
      double powargr, powargi, phsargr, phsargi, phstmp;

      data = gen_fvect(dftvec.n);
      theta = -TWOPI * rr / (double) N;
      dtmp = sin(0.5 * theta);
      aa = -2.0 * dtmp * dtmp;
      bb = sin(theta);
      cc = 1.0;
      ss = 0.0;
      for (ii = 0; ii < dftvec.numvect; ii++) {
         chkfread(data, sizeof(float), dftvec.n, infile);
         real = 0.0;
         imag = 0.0;
         for (jj = 0; jj < dftvec.n; jj++) {
            real += data[jj] * cc;
            imag += data[jj] * ss;
            cc = aa * (dtmp = cc) - bb * ss + cc;
            ss = aa * ss + bb * dtmp + ss;
         }
         dftvec.vector[ii].r = norm * real;
         dftvec.vector[ii].i = norm * imag;
         sumreal += dftvec.vector[ii].r;
         sumimag += dftvec.vector[ii].i;
      }
      vect_free(data);
      printf("\nDone:\n");
      printf("             Vector sum = %.3f + %.3fi\n", sumreal, sumimag);
      printf("      Total phase (deg) = %.2f\n", PHASE(sumreal, sumimag));
      printf("            Total power = %.2f\n", POWER(sumreal, sumimag));
      printf("\n");
   }
   fclose(infile);

   /* Write the output structure */

   sprintf(outfilenm, "%s_%.3f.dftvec", cmd->argv[0], rr);
   write_dftvector(&dftvec, outfilenm);

   /* Free our vector and return */

   free_dftvector(&dftvec);
   return (0);
}
예제 #6
0
int main(int argc, char *argv[])
{
    FILE *fftfile, *candfile = NULL, *psfile = NULL;
    char filenm[100], candnm[100], psfilenm[120];
    float locpow, norm, powargr, powargi;
    float *powr, *spreadpow, *minizoompow, *freqs;
    fcomplex *data, *minifft, *minizoom, *spread;
    fcomplex *resp, *kernel;
    double T, dr, ftobinp;
    int ii, nbins, ncands, candnum, lofreq = 0, nzoom, numsumpow = 1;
    int numbetween, numkern, kern_half_width;
    binaryprops binprops;
    infodata idata;

    if (argc < 3 || argc > 6) {
        usage();
        exit(1);
    }
    printf("\n\n");
    printf("         Binary Candidate Display Routine\n");
    printf("              by Scott M. Ransom\n\n");

    /* Initialize the filenames: */

    sprintf(filenm, "%s.fft", argv[1]);
    sprintf(candnm, "%s_bin.cand", argv[1]);

    /* Read the info file */

    readinf(&idata, argv[1]);
    if (idata.object) {
        printf("Plotting a %s candidate from '%s'.\n", idata.object, filenm);
    } else {
        printf("Plotting a candidate from '%s'.\n", filenm);
    }
    T = idata.N * idata.dt;

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

    fftfile = chkfopen(filenm, "rb");
    nbins = chkfilelen(fftfile, sizeof(fcomplex));

    /* Open the candidate file and get its length */

    candfile = chkfopen(candnm, "rb");
    ncands = chkfilelen(candfile, sizeof(binaryprops));

    /* The candidate number to examine */

    candnum = atoi(argv[2]);

    /* Check that candnum is in range */

    if ((candnum < 1) || (candnum > ncands)) {
        printf("\nThe candidate number is out of range.\n\n");
        exit(1);
    }
    /* The lowest freq present in the FFT file */

    if (argc >= 4) {
        lofreq = atoi(argv[3]);
        if ((lofreq < 0) || (lofreq > nbins - 1)) {
            printf("\n'lofreq' is out of range.\n\n");
            exit(1);
        }
    }
    /* Is the original FFT a sum of other FFTs with the amplitudes added */
    /* in quadrature?  (i.e. an incoherent sum)                          */

    if (argc >= 5) {
        numsumpow = atoi(argv[4]);
        if (numsumpow < 1) {
            printf("\nNumber of summed powers must be at least one.\n\n");
            exit(1);
        }
    }
    /* Initialize PGPLOT using Postscript if requested  */

    if ((argc == 6) && (!strcmp(argv[5], "ps"))) {
        sprintf(psfilenm, "%s_bin_cand_%d.ps", argv[1], candnum);
        cpgstart_ps(psfilenm, "landscape");
    } else {
        cpgstart_x("landscape");
    }

    /* Read the binary candidate */

    chkfileseek(candfile, (long) (candnum - 1), sizeof(binaryprops), SEEK_SET);
    chkfread(&binprops, sizeof(binaryprops), 1, candfile);
    fclose(candfile);

    /* Output the binary candidate */

    print_bin_candidate(&binprops, 2);

    /* Allocate some memory */

    powr = gen_fvect(binprops.nfftbins);
    minifft = gen_cvect(binprops.nfftbins / 2);
    spread = gen_cvect(binprops.nfftbins);
    spreadpow = gen_fvect(binprops.nfftbins);
    nzoom = 2 * ZOOMFACT * ZOOMNEIGHBORS;
    minizoom = gen_cvect(nzoom);
    minizoompow = gen_fvect(nzoom);

    /* Allocate and initialize our interpolation kernel */

    numbetween = 2;
    kern_half_width = r_resp_halfwidth(LOWACC);
    numkern = 2 * numbetween * kern_half_width;
    resp = gen_r_response(0.0, numbetween, numkern);
    kernel = gen_cvect(binprops.nfftbins);
    place_complex_kernel(resp, numkern, kernel, binprops.nfftbins);
    COMPLEXFFT(kernel, binprops.nfftbins, -1);

    /* Read the data from the FFT file */

    data = read_fcomplex_file(fftfile, binprops.lowbin - lofreq, binprops.nfftbins);

    /* Turn the Fourier amplitudes into powers */

    for (ii = 0; ii < binprops.nfftbins; ii++)
        powr[ii] = POWER(data[ii].r, data[ii].i);

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

    prune_powers(powr, binprops.nfftbins, numsumpow);

    /* Perform the minifft */

    memcpy((float *) minifft, powr, sizeof(float) * binprops.nfftbins);
    realfft((float *) minifft, binprops.nfftbins, -1);

    /* Calculate the normalization constant */

    norm = sqrt((double) binprops.nfftbins * (double) numsumpow) / minifft[0].r;
    locpow = minifft[0].r / binprops.nfftbins;

    /* Divide the original power spectrum by the local power level */

    for (ii = 0; ii < binprops.nfftbins; ii++)
        powr[ii] /= locpow;

    /* Now normalize the miniFFT */

    minifft[0].r = 1.0;
    minifft[0].i = 1.0;
    for (ii = 1; ii < binprops.nfftbins / 2; ii++) {
        minifft[ii].r *= norm;
        minifft[ii].i *= norm;
    }

    /* Interpolate the minifft and convert to power spectrum */

    corr_complex(minifft, binprops.nfftbins / 2, RAW,
                 kernel, binprops.nfftbins, FFT,
                 spread, binprops.nfftbins, kern_half_width,
                 numbetween, kern_half_width, CORR);
    for (ii = 0; ii < binprops.nfftbins; ii++)
        spreadpow[ii] = POWER(spread[ii].r, spread[ii].i);

    /* Plot the initial data set */

    freqs = gen_freqs(binprops.nfftbins, binprops.lowbin / T, 1.0 / T);
    xyline(binprops.nfftbins, freqs, powr, "Pulsar Frequency (hz)",
           "Power / Local Power", 1);
    vect_free(freqs);
    printf("The initial data set (with high power outliers removed):\n\n");

    /* Plot the miniFFT */

    freqs = gen_freqs(binprops.nfftbins, 0.0, T / (2 * binprops.nfftbins));
    xyline(binprops.nfftbins, freqs, spreadpow, "Binary Period (sec)",
           "Normalized Power", 1);
    vect_free(freqs);
    printf("The miniFFT:\n\n");

    /* Interpolate and plot the actual candidate peak */

    ftobinp = T / binprops.nfftbins;
    freqs = gen_freqs(nzoom, (binprops.rdetect - ZOOMNEIGHBORS) *
                      ftobinp, ftobinp / (double) ZOOMFACT);
    for (ii = 0; ii < nzoom; ii++) {
        dr = -ZOOMNEIGHBORS + (double) ii / ZOOMFACT;
        rz_interp(minifft, binprops.nfftbins / 2, binprops.rdetect + dr,
                  0.0, kern_half_width, &minizoom[ii]);
        minizoompow[ii] = POWER(minizoom[ii].r, minizoom[ii].i);
    }
    xyline(nzoom, freqs, minizoompow, "Binary Period (sec)", "Normalized Power", 1);
    vect_free(freqs);
    printf("The candidate itself:\n\n");
    printf("Done.\n\n");

    /* Cleanup */

    cpgend();
    vect_free(data);
    vect_free(powr);
    vect_free(resp);
    vect_free(kernel);
    vect_free(minifft);
    vect_free(spread);
    vect_free(spreadpow);
    vect_free(minizoom);
    vect_free(minizoompow);
    fclose(fftfile);
    if ((argc == 6) && (!strcmp(argv[5], "ps"))) {
        fclose(psfile);
    }
    return (0);
}
예제 #7
0
파일: quicklook.c 프로젝트: aarchiba/presto
int main(int argc, char *argv[])
{
   FILE *fftfile;
   double flook, dt, nph, t, maxz, pwr, hipow = 0.0;
   double zlo = -30.0, zhi = 30.0, dr, dz = 2.0;
   double hir = 0.0, hiz = 0.0, newhir, newhiz;
   fcomplex **ffdotplane, *data;
   float powargr, powargi;
   int startbin, numdata, nextbin, nr, nz, numkern;
   int i, j, realpsr, kernel_half_width, numbetween = 4;
   int n, corrsize = 1024;
   char filenm[80], compare[200];
   rderivs derivs;
   fourierprops props;
   infodata idata;
   struct tms runtimes;
   double ttim, utim, stim, tott;


   tott = times(&runtimes) / (double) CLK_TCK;
   if (argc != 3) {
      printf("\nUsage:  'quicklook filename fftfreq dt'\n\n");
      printf("   'filename' = a string containing the FFT file's name.\n");
      printf("                (do not include the '.fft' suffix)\n");
      printf("    'fftfreq' = the central fourier frequency to examine.\n");
      printf("  Quicklook will search a region of the f-fdot plane\n");
      printf("  of a file containing a long, single precision FFT\n");
      printf("  using the Correlation method (i.e. Ransom and \n");
      printf("  Eikenberry, 1997, unpublished as of yet).\n");
      printf("  The search uses a spacing of 0.5 frequency bins in\n");
      printf("  the fourier frequency (r) direction, and 2 'bins' in\n");
      printf("  the fdot (z) direction.  The routine will output\n");
      printf("  statistics for the best candidate in the region.\n\n");
      printf("  The routine was written as a quick but useful hack\n");
      printf("  to show the power of the Correlation method, and the\n");
      printf("  forthcoming power of Scott Ransom's Pulsar Finder\n");
      printf("  Software.\n");
      printf("                                        2 March 2001\n\n");
      exit(0);
   }
   printf("\n\n");
   printf("  Quick-Look Pulsation Search\n");
   printf("     With database lookup.\n");
   printf("      by Scott M. Ransom\n");
   printf("         2 March, 2001\n\n");

   /*  Initialize our data: */

   sprintf(filenm, "%s.fft", argv[1]);
   readinf(&idata, argv[1]);
   flook = atof(argv[2]);
   dt = idata.dt;
   dr = 1.0 / (double) numbetween;
   fftfile = chkfopen(filenm, "r");
   nph = get_numphotons(fftfile);
   n = chkfilelen(fftfile, sizeof(float));
   t = n * dt;
   nz = (int) ((zhi - zlo) / dz) + 1;

   /* Determine our starting frequency and get the data */

   maxz = (fabs(zlo) < fabs(zhi)) ? zhi : zlo;
   kernel_half_width = z_resp_halfwidth(maxz, HIGHACC);
   numkern = 2 * numbetween * kernel_half_width;
   while (numkern > 2 * corrsize)
      corrsize *= 2;
   startbin = (int) (flook) - corrsize / (2 * numbetween);
   numdata = corrsize / numbetween;
   data = read_fcomplex_file(fftfile, startbin, numdata);

   /*  Do the f-fdot plane correlations: */

   ffdotplane = corr_rz_plane(data, numdata, numbetween, kernel_half_width,
                              zlo, zhi, nz, corrsize, LOWACC, &nextbin);
   nr = corrsize - 2 * kernel_half_width * numbetween;

   /*  Search the resulting data set: */

   for (i = 0; i < nz; i++) {
      for (j = 0; j < nr; j++) {
         pwr = POWER(ffdotplane[i][j].r, ffdotplane[i][j].i);
         if (pwr > hipow) {
            hir = j * dr + kernel_half_width;
            hiz = i * dz + zlo;
            hipow = pwr;
         }
      }
   }

   /*  Maximize the best candidate: */

   hipow = max_rz_arr(data, numdata, hir, hiz, &newhir, &newhiz, &derivs);
   newhir += startbin;
   calc_props(derivs, newhir, newhiz, 0.0, &props);

   printf("Searched %d pts ", nz * nr);
   printf("(r: %.1f to %.1f, ", (double) startbin + kernel_half_width,
          (double) startbin + kernel_half_width + dr * (nr - 1));
   printf("z: %.1f to %.1f)\n\n", zlo, zhi);

   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("The best candidate is:\n");

   print_candidate(&props, dt, n, nph, 2);
   realpsr = comp_psr_to_cand(&props, &idata, compare, 1);
   printf("%s\n", compare);
   fclose(fftfile);

   /* Cleanup and exit */

   free(ffdotplane[0]);
   free(ffdotplane);
   free(data);
   exit(0);
}
예제 #8
0
파일: search_bin.c 프로젝트: bretonr/presto
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);
}