コード例 #1
0
ファイル: accel_utils.c プロジェクト: ariofrio/presto
static inline int calc_required_z(double harm_fract, double zfull)
/* Calculate the 'z' you need for subharmonic     */
/* 'harmnum' out of 'numharm' subharmonics if the */
/* 'z' at the fundamental harmonic is 'zfull'.    */
{
   return NEAREST_INT(ACCEL_RDZ * zfull * harm_fract) * ACCEL_DZ;
}
コード例 #2
0
ファイル: prepfold_utils.c プロジェクト: bretonr/presto
void correct_subbands_for_DM(double dm, prepfoldinfo * search,
                             double *ddprofs, foldstats * ddstats)
/* Calculate the DM delays and apply them to the subbands */
/* to create de-dispersed profiles.                      */
{
   int ii, *dmdelays;
   double *subbanddelays, hif, dopplerhif, hifdelay, rdphase;

   rdphase = search->fold.p1 * search->proflen;
   hif = search->lofreq + (search->numchan - 1.0) * search->chan_wid;
   dopplerhif = doppler(hif, search->avgvoverc);
   hifdelay = delay_from_dm(dm, dopplerhif);
   subbanddelays = subband_delays(search->numchan, search->nsub, dm,
                                  search->lofreq, search->chan_wid,
                                  search->avgvoverc);
   dmdelays = gen_ivect(search->nsub);
   for (ii = 0; ii < search->nsub; ii++)
      dmdelays[ii] =
          NEAREST_INT((subbanddelays[ii] - hifdelay) * rdphase) % search->proflen;
   vect_free(subbanddelays);
   combine_subbands(search->rawfolds, search->stats, search->npart,
                    search->nsub, search->proflen, dmdelays, ddprofs, ddstats);
   vect_free(dmdelays);
}
コード例 #3
0
ファイル: mpiprepsubband.c プロジェクト: cptwin/presto
int main(int argc, char *argv[])
{
   /* Any variable that begins with 't' means topocentric */
   /* Any variable that begins with 'b' means barycentric */
   FILE **outfiles = NULL;
   float **outdata;
   double dtmp, *dms, avgdm = 0.0, dsdt = 0, maxdm;
   double *dispdt, tlotoa = 0.0, blotoa = 0.0, BW_ddelay = 0.0;
   double max = -9.9E30, min = 9.9E30, var = 0.0, avg = 0.0;
   double *btoa = NULL, *ttoa = NULL, avgvoverc = 0.0;
   char obs[3], ephem[10], rastring[50], decstring[50];
   int totnumtowrite, *idispdt, **offsets;
   int ii, jj, numadded = 0, numremoved = 0, padding = 0, good_inputs = 1;
   int numbarypts = 0, numread = 0, numtowrite = 0, totwrote = 0, datawrote = 0;
   int padwrote = 0, padtowrite = 0, statnum = 0;
   int numdiffbins = 0, *diffbins = NULL, *diffbinptr = NULL, good_padvals = 0;
   double local_lodm;
   char *datafilenm, *outpath, *outfilenm, *hostname;
   struct spectra_info s;
   infodata idata;
   mask obsmask;

   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);
   set_using_MPI();
   {
      FILE *hostfile;
      char tmpname[100];
      int retval;

      hostfile = chkfopen("/etc/hostname", "r");
      retval = fscanf(hostfile, "%s\n", tmpname);
      if (retval==0) {
          printf("Warning:  error reading /etc/hostname on proc %d\n", myid);
      }
      hostname = (char *) calloc(strlen(tmpname) + 1, 1);
      memcpy(hostname, tmpname, strlen(tmpname));
      fclose(hostfile);
   }

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

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

   make_maskbase_struct();
   make_spectra_info_struct();

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

   cmd = parseCmdline(argc, argv);
   spectra_info_set_defaults(&s);
   // If we are zeroDMing, make sure that clipping is off.
   if (cmd->zerodmP) cmd->noclipP = 1;
   s.clip_sigma = cmd->clip;
   if (cmd->noclipP) {
       cmd->clip = 0.0;
       s.clip_sigma = 0.0;
   }
   if (cmd->ifsP) {
       // 0 = default or summed, 1-4 are possible also
       s.use_poln = cmd->ifs + 1;
   }
   if (!cmd->numoutP)
      cmd->numout = INT_MAX;

#ifdef DEBUG
   showOptionValues();
#endif

   if (myid == 0) {             /* Master node only */
      printf("\n\n");
      printf("      Parallel Pulsar Subband De-dispersion Routine\n");
      printf("                 by Scott M. Ransom\n\n");

      s.filenames = cmd->argv;
      s.num_files = cmd->argc;
      s.clip_sigma = cmd->clip;
      // -1 causes the data to determine if we use weights, scales, & 
      // offsets for PSRFITS or flip the band for any data type where
      // we can figure that out with the data
      s.apply_flipband = (cmd->invertP) ? 1 : -1;
      s.apply_weight = (cmd->noweightsP) ? 0 : -1;
      s.apply_scale  = (cmd->noscalesP) ? 0 : -1;
      s.apply_offset = (cmd->nooffsetsP) ? 0 : -1;
      s.remove_zerodm = (cmd->zerodmP) ? 1 : 0;

      if (RAWDATA) {
          if (cmd->filterbankP) s.datatype = SIGPROCFB;
          else if (cmd->psrfitsP) s.datatype = PSRFITS;
          else if (cmd->pkmbP) s.datatype = SCAMP;
          else if (cmd->bcpmP) s.datatype = BPP;
          else if (cmd->wappP) s.datatype = WAPP;
          else if (cmd->spigotP) s.datatype = SPIGOT;
      } else {  // Attempt to auto-identify the data
          identify_psrdatatype(&s, 1);
          if (s.datatype==SIGPROCFB) cmd->filterbankP = 1;
          else if (s.datatype==PSRFITS) cmd->psrfitsP = 1;
          else if (s.datatype==SCAMP) cmd->pkmbP = 1;
          else if (s.datatype==BPP) cmd->bcpmP = 1;
          else if (s.datatype==WAPP) cmd->wappP = 1;
          else if (s.datatype==SPIGOT) cmd->spigotP = 1;
          else if (s.datatype==SUBBAND) insubs = 1;
          else {
              printf("\nError:  Unable to identify input data files.  Please specify type.\n\n");
              good_inputs = 0;
          }
      }
      // So far we can only handle PSRFITS, filterbank, and subbands
      if (s.datatype!=PSRFITS && 
          s.datatype!=SIGPROCFB && 
          s.datatype!=SUBBAND) good_inputs = 0;

      // For subbanded data
      if (!RAWDATA) s.files = (FILE **)malloc(sizeof(FILE *) * s.num_files);

      if (good_inputs && (RAWDATA || insubs)) {
          char description[40];
          psrdatatype_description(description, s.datatype);
          if (s.num_files > 1)
              printf("Reading %s data from %d files:\n", description, s.num_files);
          else
              printf("Reading %s data from 1 file:\n", description);
          for (ii = 0; ii < s.num_files; ii++) {
              printf("  '%s'\n", cmd->argv[ii]);
              if (insubs) s.files[ii] = chkfopen(s.filenames[ii], "rb");
          }
          printf("\n");
          if (RAWDATA) {
              read_rawdata_files(&s);
              print_spectra_info_summary(&s);
              spectra_info_to_inf(&s, &idata);
          } else { // insubs
              char *root, *suffix;
              cmd->nsub = s.num_files;
              s.N = chkfilelen(s.files[0], sizeof(short));
              s.start_subint = gen_ivect(1);
              s.num_subint = gen_ivect(1);
              s.start_MJD = (long double *)malloc(sizeof(long double));
              s.start_spec = (long long *)malloc(sizeof(long long));
              s.num_spec = (long long *)malloc(sizeof(long long));
              s.num_pad = (long long *)malloc(sizeof(long long));
              s.start_spec[0] = 0L;
              s.start_subint[0] = 0;
              s.num_spec[0] = s.N;
              s.num_subint[0] = s.N / SUBSBLOCKLEN;
              s.num_pad[0] = 0L;
              s.padvals = gen_fvect(s.num_files);
              for (ii = 0 ; ii < ii ; ii++)
                  s.padvals[ii] = 0.0;
              if (split_root_suffix(s.filenames[0], &root, &suffix) == 0) {
                  printf("\nError:  The input filename (%s) must have a suffix!\n\n", s.filenames[0]);
                  exit(1);
              }
              if (strncmp(suffix, "sub", 3) == 0) {
                  char *tmpname;
                  tmpname = calloc(strlen(root) + 10, 1);
                  sprintf(tmpname, "%s.sub", root);
                  readinf(&idata, tmpname);
                  free(tmpname);
                  strncpy(s.telescope, idata.telescope, 40);
                  strncpy(s.backend, idata.instrument, 40);
                  strncpy(s.observer, idata.observer, 40);
                  strncpy(s.source, idata.object, 40);
                  s.ra2000 = hms2rad(idata.ra_h, idata.ra_m,
                                     idata.ra_s) * RADTODEG;
                  s.dec2000 = dms2rad(idata.dec_d, idata.dec_m,
                                      idata.dec_s) * RADTODEG;
                  ra_dec_to_string(s.ra_str,
                                   idata.ra_h, idata.ra_m, idata.ra_s);
                  ra_dec_to_string(s.dec_str,
                                   idata.dec_d, idata.dec_m, idata.dec_s);
                  s.num_channels = idata.num_chan;
                  s.start_MJD[0] = idata.mjd_i + idata.mjd_f;
                  s.dt = idata.dt;
                  s.T = s.N * s.dt;
                  s.lo_freq = idata.freq;
                  s.df = idata.chan_wid;
                  s.hi_freq = s.lo_freq + (s.num_channels - 1.0) * s.df;
                  s.BW = s.num_channels * s.df;
                  s.fctr = s.lo_freq - 0.5 * s.df + 0.5 * s.BW;
                  s.beam_FWHM = idata.fov / 3600.0;
                  s.spectra_per_subint = SUBSBLOCKLEN;
                  print_spectra_info_summary(&s);
              } else {
                  printf("\nThe input files (%s) must be subbands!  (i.e. *.sub##)\n\n",
                         cmd->argv[0]);
                  MPI_Finalize();
                  exit(1);
              }
              free(root);
              free(suffix);
          }
      }
   }

   //  If we don't have good input data, exit
   MPI_Bcast(&good_inputs, 1, MPI_INT, 0, MPI_COMM_WORLD);
   if (!good_inputs) {
       MPI_Finalize();
       exit(1);
   }
   
   MPI_Bcast(&insubs, 1, MPI_INT, 0, MPI_COMM_WORLD);
   if (insubs)
       cmd->nsub = cmd->argc;

   /* Determine the output file names and open them */

   local_numdms = cmd->numdms / (numprocs - 1);
   dms = gen_dvect(local_numdms);
   if (cmd->numdms % (numprocs - 1)) {
       if (myid == 0)
           printf
               ("\nThe number of DMs must be divisible by (the number of processors - 1).\n\n");
       MPI_Finalize();
       exit(1);
   }
   local_lodm = cmd->lodm + (myid - 1) * local_numdms * cmd->dmstep;
   
   split_path_file(cmd->outfile, &outpath, &outfilenm);
   datafilenm = (char *) calloc(strlen(outfilenm) + 20, 1);
   if (myid > 0) {
       if (chdir(outpath) == -1) {
           printf("\nProcess %d on %s cannot chdir() to '%s'.  Exiting.\n\n", 
                  myid, hostname, outpath);
           MPI_Finalize();
           exit(1);
       }
       outfiles = (FILE **) malloc(local_numdms * sizeof(FILE *));
       for (ii = 0; ii < local_numdms; ii++) {
           dms[ii] = local_lodm + ii * cmd->dmstep;
           avgdm += dms[ii];
           sprintf(datafilenm, "%s_DM%.2f.dat", outfilenm, dms[ii]);
           outfiles[ii] = chkfopen(datafilenm, "wb");
       }
       avgdm /= local_numdms;
   }
   
   // Broadcast the raw data information

   broadcast_spectra_info(&s, myid);
   if (myid > 0) {
       spectra_info_to_inf(&s, &idata);
       if (s.datatype==SIGPROCFB) cmd->filterbankP = 1;
       else if (s.datatype==PSRFITS) cmd->psrfitsP = 1;
       else if (s.datatype==SCAMP) cmd->pkmbP = 1;
       else if (s.datatype==BPP) cmd->bcpmP = 1;
       else if (s.datatype==WAPP) cmd->wappP = 1;
       else if (s.datatype==SPIGOT) cmd->spigotP = 1;
       else if (s.datatype==SUBBAND) insubs = 1;
   }
   s.filenames = cmd->argv;

   /* Read an input mask if wanted */
   
   if (myid > 0) {
       int numpad = s.num_channels;
       if (insubs)
           numpad = s.num_files;
       s.padvals = gen_fvect(numpad);
       for (ii = 0 ; ii < numpad ; ii++)
           s.padvals[ii] = 0.0;
   }
   if (cmd->maskfileP) {
       if (myid == 0) {
           read_mask(cmd->maskfile, &obsmask);
           printf("Read mask information from '%s'\n\n", cmd->maskfile);
           good_padvals = determine_padvals(cmd->maskfile, &obsmask, s.padvals);
       }
       broadcast_mask(&obsmask, myid);
       MPI_Bcast(&good_padvals, 1, MPI_INT, 0, MPI_COMM_WORLD);
       MPI_Bcast(s.padvals, obsmask.numchan, MPI_FLOAT, 0, MPI_COMM_WORLD);
   } else {
       obsmask.numchan = obsmask.numint = 0;
       MPI_Bcast(&good_padvals, 1, MPI_INT, 0, MPI_COMM_WORLD);
   }

   // The number of topo to bary time points to generate with TEMPO
   numbarypts = (int) (s.T * 1.1 / TDT + 5.5) + 1;

   // Identify the TEMPO observatory code
   {
       char *outscope = (char *) calloc(40, sizeof(char));
       telescope_to_tempocode(idata.telescope, outscope, obs);
       free(outscope);
   }

   // Broadcast or calculate a few extra important values
   if (insubs) avgdm = idata.dm;
   idata.dm = avgdm;
   dsdt = cmd->downsamp * idata.dt;
   maxdm = cmd->lodm + cmd->numdms * cmd->dmstep;
   BW_ddelay = delay_from_dm(maxdm, idata.freq) - 
       delay_from_dm(maxdm, idata.freq + (idata.num_chan-1) * idata.chan_wid);
   blocksperread = ((int) (BW_ddelay / idata.dt) / s.spectra_per_subint + 1);
   worklen = s.spectra_per_subint * blocksperread;
   
   if (cmd->nsub > s.num_channels) {
      printf
          ("Warning:  The number of requested subbands (%d) is larger than the number of channels (%d).\n",
           cmd->nsub, s.num_channels);
      printf("          Re-setting the number of subbands to %d.\n\n", s.num_channels);
      cmd->nsub = s.num_channels;
   }

   if (s.spectra_per_subint % cmd->downsamp) {
       if (myid == 0) {
           printf
               ("\nError:  The downsample factor (%d) must be a factor of the\n",
                cmd->downsamp);
           printf("        blocklength (%d).  Exiting.\n\n", s.spectra_per_subint);
       }
       MPI_Finalize();
       exit(1);
   }

   tlotoa = idata.mjd_i + idata.mjd_f;  /* Topocentric epoch */

   if (cmd->numoutP)
      totnumtowrite = cmd->numout;
   else
      totnumtowrite = (int) idata.N / cmd->downsamp;

   if (cmd->nobaryP) {          /* Main loop if we are not barycentering... */

      /* Dispersion delays (in bins).  The high freq gets no delay   */
      /* All other delays are positive fractions of bin length (dt)  */

      dispdt = subband_search_delays(s.num_channels, cmd->nsub, avgdm,
                                     idata.freq, idata.chan_wid, 0.0);
      idispdt = gen_ivect(s.num_channels);
      for (ii = 0; ii < s.num_channels; ii++)
          idispdt[ii] = NEAREST_INT(dispdt[ii] / idata.dt);
      vect_free(dispdt);

      /* The subband dispersion delays (see note above) */

      offsets = gen_imatrix(local_numdms, cmd->nsub);
      for (ii = 0; ii < local_numdms; ii++) {
         double *subdispdt;

         subdispdt = subband_delays(s.num_channels, cmd->nsub, dms[ii],
                                    idata.freq, idata.chan_wid, 0.0);
         dtmp = subdispdt[cmd->nsub - 1];
         for (jj = 0; jj < cmd->nsub; jj++)
            offsets[ii][jj] = NEAREST_INT((subdispdt[jj] - dtmp) / dsdt);
         vect_free(subdispdt);
      }

      /* Allocate our data array and start getting data */

      if (myid == 0) {
         printf("De-dispersing using %d subbands.\n", cmd->nsub);
         if (cmd->downsamp > 1)
            printf("Downsampling by a factor of %d (new dt = %.10g)\n",
                   cmd->downsamp, dsdt);
         printf("\n");
      }
      
      /* Print the nodes and the DMs they are handling */
      print_dms(hostname, myid, numprocs, local_numdms, dms);

      outdata = gen_fmatrix(local_numdms, worklen / cmd->downsamp);
      numread = get_data(outdata, blocksperread, &s,
                         &obsmask, idispdt, offsets, &padding);

      while (numread == worklen) {

         numread /= cmd->downsamp;
         if (myid == 0)
            print_percent_complete(totwrote, totnumtowrite);

         /* Write the latest chunk of data, but don't   */
         /* write more than cmd->numout points.         */

         numtowrite = numread;
         if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout)
            numtowrite = cmd->numout - totwrote;
         if (myid > 0) {
            write_data(outfiles, local_numdms, outdata, 0, numtowrite);
            /* Update the statistics */
            if (!padding) {
               for (ii = 0; ii < numtowrite; ii++)
                  update_stats(statnum + ii, outdata[0][ii], &min, &max, &avg, &var);
               statnum += numtowrite;
            }
         }
         totwrote += numtowrite;

         /* Stop if we have written out all the data we need to */

         if (cmd->numoutP && (totwrote == cmd->numout))
            break;

         numread = get_data(outdata, blocksperread, &s,
                            &obsmask, idispdt, offsets, &padding);
      }
      datawrote = totwrote;

   } else {                     /* Main loop if we are barycentering... */

      /* What ephemeris will we use?  (Default is DE200) */

      if (cmd->de405P)
         strcpy(ephem, "DE405");
      else
         strcpy(ephem, "DE200");

      /* Define the RA and DEC of the observation */

      ra_dec_to_string(rastring, idata.ra_h, idata.ra_m, idata.ra_s);
      ra_dec_to_string(decstring, idata.dec_d, idata.dec_m, idata.dec_s);

      /* Allocate some arrays */

      btoa = gen_dvect(numbarypts);
      ttoa = gen_dvect(numbarypts);
      for (ii = 0; ii < numbarypts; ii++)
         ttoa[ii] = tlotoa + TDT * ii / SECPERDAY;

      /* Call TEMPO for the barycentering */

      if (myid == 0) {
         double maxvoverc = -1.0, minvoverc = 1.0, *voverc = NULL;

         printf("\nGenerating barycentric corrections...\n");
         voverc = gen_dvect(numbarypts);
         barycenter(ttoa, btoa, voverc, numbarypts, rastring, decstring, obs, ephem);
         for (ii = 0; ii < numbarypts; ii++) {
            if (voverc[ii] > maxvoverc)
               maxvoverc = voverc[ii];
            if (voverc[ii] < minvoverc)
               minvoverc = voverc[ii];
            avgvoverc += voverc[ii];
         }
         avgvoverc /= numbarypts;
         vect_free(voverc);

         printf("   Average topocentric velocity (c) = %.7g\n", avgvoverc);
         printf("   Maximum topocentric velocity (c) = %.7g\n", maxvoverc);
         printf("   Minimum topocentric velocity (c) = %.7g\n\n", minvoverc);
         printf("De-dispersing using %d subbands.\n", cmd->nsub);
         if (cmd->downsamp > 1) {
             printf("     Downsample = %d\n", cmd->downsamp);
             printf("  New sample dt = %.10g\n", dsdt);
         }
         printf("\n");
      }

      /* Print the nodes and the DMs they are handling */
      print_dms(hostname, myid, numprocs, local_numdms, dms);

      MPI_Bcast(btoa, numbarypts, MPI_DOUBLE, 0, MPI_COMM_WORLD);
      MPI_Bcast(&avgvoverc, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
      blotoa = btoa[0];

      /* Dispersion delays (in bins).  The high freq gets no delay   */
      /* All other delays are positive fractions of bin length (dt)  */

      dispdt = subband_search_delays(s.num_channels, cmd->nsub, avgdm,
                                     idata.freq, idata.chan_wid, avgvoverc);
      idispdt = gen_ivect(s.num_channels);
      for (ii = 0; ii < s.num_channels; ii++)
          idispdt[ii] = NEAREST_INT(dispdt[ii] / idata.dt);
      vect_free(dispdt);

      /* The subband dispersion delays (see note above) */

      offsets = gen_imatrix(local_numdms, cmd->nsub);
      for (ii = 0; ii < local_numdms; ii++) {
         double *subdispdt;

         subdispdt = subband_delays(s.num_channels, cmd->nsub, dms[ii],
                                    idata.freq, idata.chan_wid, avgvoverc);
         dtmp = subdispdt[cmd->nsub - 1];
         for (jj = 0; jj < cmd->nsub; jj++)
            offsets[ii][jj] = NEAREST_INT((subdispdt[jj] - dtmp) / dsdt);
         vect_free(subdispdt);
      }

      /* Convert the bary TOAs to differences from the topo TOAs in */
      /* units of bin length (dt) rounded to the nearest integer.   */

      dtmp = (btoa[0] - ttoa[0]);
      for (ii = 0; ii < numbarypts; ii++)
         btoa[ii] = ((btoa[ii] - ttoa[ii]) - dtmp) * SECPERDAY / dsdt;

      /* Find the points where we need to add or remove bins */
      {
         int oldbin = 0, currentbin;
         double lobin, hibin, calcpt;

         numdiffbins = abs(NEAREST_INT(btoa[numbarypts - 1])) + 1;
         diffbins = gen_ivect(numdiffbins);
         diffbinptr = diffbins;
         for (ii = 1; ii < numbarypts; ii++) {
            currentbin = NEAREST_INT(btoa[ii]);
            if (currentbin != oldbin) {
               if (currentbin > 0) {
                  calcpt = oldbin + 0.5;
                  lobin = (ii - 1) * TDT / dsdt;
                  hibin = ii * TDT / dsdt;
               } else {
                  calcpt = oldbin - 0.5;
                  lobin = -((ii - 1) * TDT / dsdt);
                  hibin = -(ii * TDT / dsdt);
               }
               while (fabs(calcpt) < fabs(btoa[ii])) {
                  /* Negative bin number means remove that bin */
                  /* Positive bin number means add a bin there */
                  *diffbinptr =
                      NEAREST_INT(LININTERP
                                  (calcpt, btoa[ii - 1], btoa[ii], lobin, hibin));
                  diffbinptr++;
                  calcpt = (currentbin > 0) ? calcpt + 1.0 : calcpt - 1.0;
               }
               oldbin = currentbin;
            }
         }
         *diffbinptr = cmd->numout; /* Used as a marker */
      }
      diffbinptr = diffbins;

      /* Now perform the barycentering */

      outdata = gen_fmatrix(local_numdms, worklen / cmd->downsamp);
      numread = get_data(outdata, blocksperread, &s, 
                         &obsmask, idispdt, offsets, &padding);

      while (numread == worklen) {      /* Loop to read and write the data */
         int numwritten = 0;
         double block_avg, block_var;

         numread /= cmd->downsamp;
         /* Determine the approximate local average */
         avg_var(outdata[0], numread, &block_avg, &block_var);
         if (myid == 0)
            print_percent_complete(totwrote, totnumtowrite);

         /* Simply write the data if we don't have to add or */
         /* remove any bins from this batch.                 */
         /* OR write the amount of data up to cmd->numout or */
         /* the next bin that will be added or removed.      */

         numtowrite = abs(*diffbinptr) - datawrote;
         if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout)
            numtowrite = cmd->numout - totwrote;
         if (numtowrite > numread)
            numtowrite = numread;
         if (myid > 0) {
            write_data(outfiles, local_numdms, outdata, 0, numtowrite);
            /* Update the statistics */
            if (!padding) {
               for (ii = 0; ii < numtowrite; ii++)
                  update_stats(statnum + ii, outdata[0][ii], &min, &max, &avg, &var);
               statnum += numtowrite;
            }
         }
         datawrote += numtowrite;
         totwrote += numtowrite;
         numwritten += numtowrite;

         if ((datawrote == abs(*diffbinptr)) && 
             (numwritten != numread) && 
             (totwrote < cmd->numout)) {  /* Add/remove a bin */
            int skip, nextdiffbin;

            skip = numtowrite;

            /* Write the rest of the data after adding/removing a bin  */
            do {

               if (*diffbinptr > 0) {
                  /* Add a bin */
                  if (myid > 0)
                     write_padding(outfiles, local_numdms, block_avg, 1);
                  numadded++;
                  totwrote++;
               } else {
                  /* Remove a bin */
                  numremoved++;
                  datawrote++;
                  numwritten++;
                  skip++;
               }
               diffbinptr++;

               /* Write the part after the diffbin */

               numtowrite = numread - numwritten;
               if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout)
                  numtowrite = cmd->numout - totwrote;
               nextdiffbin = abs(*diffbinptr) - datawrote;
               if (numtowrite > nextdiffbin)
                  numtowrite = nextdiffbin;
               if (myid > 0) {
                  write_data(outfiles, local_numdms, outdata, skip, numtowrite);
                  /* Update the statistics and counters */
                  if (!padding) {
                     for (ii = 0; ii < numtowrite; ii++)
                        update_stats(statnum + ii,
                                     outdata[0][skip + ii], &min, &max, &avg, &var);
                     statnum += numtowrite;
                  }
               }
               numwritten += numtowrite;
               datawrote += numtowrite;
               totwrote += numtowrite;
               skip += numtowrite;

               /* Stop if we have written out all the data we need to */

               if (cmd->numoutP && (totwrote == cmd->numout))
                  break;
            } while (numwritten < numread);
         }
         /* Stop if we have written out all the data we need to */

         if (cmd->numoutP && (totwrote == cmd->numout))
            break;

         numread = get_data(outdata, blocksperread, &s,
                            &obsmask, idispdt, offsets, &padding);
      }
   }

   if (myid > 0) {

      /* Calculate the amount of padding we need  */

      if (cmd->numoutP && (cmd->numout > totwrote))
         padwrote = padtowrite = cmd->numout - totwrote;

      /* Write the new info file for the output data */

      idata.dt = dsdt;
      update_infodata(&idata, totwrote, padtowrite, diffbins,
                      numdiffbins, cmd->downsamp);
      for (ii = 0; ii < local_numdms; ii++) {
         idata.dm = dms[ii];
         if (!cmd->nobaryP) {
            double baryepoch, barydispdt, baryhifreq;

            baryhifreq = idata.freq + (s.num_channels - 1) * idata.chan_wid;
            barydispdt = delay_from_dm(dms[ii], doppler(baryhifreq, avgvoverc));
            baryepoch = blotoa - (barydispdt / SECPERDAY);
            idata.bary = 1;
            idata.mjd_i = (int) floor(baryepoch);
            idata.mjd_f = baryepoch - idata.mjd_i;
         }
         sprintf(idata.name, "%s_DM%.2f", outfilenm, dms[ii]);
         writeinf(&idata);
      }

      /* Set the padded points equal to the average data point */

      if (idata.numonoff >= 1) {
         int index, startpad, endpad;

         for (ii = 0; ii < local_numdms; ii++) {
            fclose(outfiles[ii]);
            sprintf(datafilenm, "%s_DM%.2f.dat", outfilenm, dms[ii]);
            outfiles[ii] = chkfopen(datafilenm, "rb+");
         }
         for (ii = 0; ii < idata.numonoff; ii++) {
            index = 2 * ii;
            startpad = idata.onoff[index + 1];
            if (ii == idata.numonoff - 1)
               endpad = idata.N - 1;
            else
               endpad = idata.onoff[index + 2];
            for (jj = 0; jj < local_numdms; jj++)
               chkfseek(outfiles[jj], (startpad + 1) * sizeof(float), SEEK_SET);
            padtowrite = endpad - startpad;
            write_padding(outfiles, local_numdms, avg, padtowrite);
         }
      }
   }

   /* Print simple stats and results */

   var /= (datawrote - 1);
   if (myid == 0)
      print_percent_complete(1, 1);
   if (myid == 1) {
      printf("\n\nDone.\n\nSimple statistics of the output data:\n");
      printf("             Data points written:  %d\n", totwrote);
      if (padwrote)
         printf("          Padding points written:  %d\n", padwrote);
      if (!cmd->nobaryP) {
         if (numadded)
            printf("    Bins added for barycentering:  %d\n", numadded);
         if (numremoved)
            printf("  Bins removed for barycentering:  %d\n", numremoved);
      }
      printf("           Maximum value of data:  %.2f\n", max);
      printf("           Minimum value of data:  %.2f\n", min);
      printf("              Data average value:  %.2f\n", avg);
      printf("         Data standard deviation:  %.2f\n", sqrt(var));
      printf("\n");
   }

   /* Close the files and cleanup */

   if (cmd->maskfileP)
      free_mask(obsmask);
   if (myid > 0) {
      for (ii = 0; ii < local_numdms; ii++)
         fclose(outfiles[ii]);
      free(outfiles);
   }
   vect_free(outdata[0]);
   vect_free(outdata);
   vect_free(dms);
   free(hostname);
   vect_free(idispdt);
   vect_free(offsets[0]);
   vect_free(offsets);
   free(datafilenm);
   free(outfilenm);
   free(outpath);
   if (!cmd->nobaryP) {
      vect_free(btoa);
      vect_free(ttoa);
      vect_free(diffbins);
   }
   MPI_Finalize();
   return (0);
}
コード例 #4
0
ファイル: prepdata.c プロジェクト: nextgen-astrodata/presto
int main(int argc, char *argv[])
{
   /* Any variable that begins with 't' means topocentric */
   /* Any variable that begins with 'b' means barycentric */
   FILE *outfile;
   float *outdata = NULL;
   double tdf = 0.0, dtmp = 0.0, barydispdt = 0.0, dsdt = 0.0;
   double *dispdt, *tobsf = NULL, tlotoa = 0.0, blotoa = 0.0;
   double max = -9.9E30, min = 9.9E30, var = 0.0, avg = 0.0;
   char obs[3], ephem[10], *datafilenm, *outinfonm;
   char rastring[50], decstring[50];
   int numchan = 1, newper = 0, oldper = 0, nummasked = 0, useshorts = 0;
   int numadded = 0, numremoved = 0, padding = 0, *maskchans = NULL, offset = 0;
   long slen, ii, numbarypts = 0, worklen = 65536;
   long numread = 0, numtowrite = 0, totwrote = 0, datawrote = 0;
   long padwrote = 0, padtowrite = 0, statnum = 0;
   int numdiffbins = 0, *diffbins = NULL, *diffbinptr = NULL, good_padvals = 0;
   int *idispdt;
   struct spectra_info s;
   infodata idata;
   Cmdline *cmd;
   mask obsmask;

   /* Call usage() if we have no command line arguments */
   if (argc == 1) {
      Program = argv[0];
      printf("\n");
      usage();
      exit(0);
   }

   /* Parse the command line using the excellent program Clig */
   cmd = parseCmdline(argc, argv);
   spectra_info_set_defaults(&s);
   s.filenames = cmd->argv;
   s.num_files = cmd->argc;
   s.clip_sigma = cmd->clip;
   // -1 causes the data to determine if we use weights, scales, & 
   // offsets for PSRFITS or flip the band for any data type where
   // we can figure that out with the data
   s.apply_flipband = (cmd->invertP) ? 1 : -1;
   s.apply_weight = (cmd->noweightsP) ? 0 : -1;
   s.apply_scale  = (cmd->noscalesP) ? 0 : -1;
   s.apply_offset = (cmd->nooffsetsP) ? 0 : -1;
   s.remove_zerodm = (cmd->zerodmP) ? 1 : 0;
   if (cmd->noclipP) {
       cmd->clip = 0.0;
       s.clip_sigma = 0.0;
   }
   if (cmd->ifsP) {
       // 0 = default or summed, 1-4 are possible also
       s.use_poln = cmd->ifs;
   }

#ifdef DEBUG
   showOptionValues();
#endif

   printf("\n\n");
   printf("           Pulsar Data Preparation Routine\n");
   printf("    Type conversion, de-dispersion, barycentering.\n");
   printf("                 by Scott M. Ransom\n\n");

   if (RAWDATA) {
       if (cmd->filterbankP) s.datatype = SIGPROCFB;
       else if (cmd->psrfitsP) s.datatype = PSRFITS;
       else if (cmd->pkmbP) s.datatype = SCAMP;
       else if (cmd->bcpmP) s.datatype = BPP;
       else if (cmd->wappP) s.datatype = WAPP;
       else if (cmd->spigotP) s.datatype = SPIGOT;
   } else {  // Attempt to auto-identify the data
       identify_psrdatatype(&s, 1);
       if (s.datatype==SIGPROCFB) cmd->filterbankP = 1;
       else if (s.datatype==PSRFITS) cmd->psrfitsP = 1;
       else if (s.datatype==SCAMP) cmd->pkmbP = 1;
       else if (s.datatype==BPP) cmd->bcpmP = 1;
       else if (s.datatype==WAPP) cmd->wappP = 1;
       else if (s.datatype==SPIGOT) cmd->spigotP = 1;
       else if (s.datatype==SDAT) useshorts = 1;
       else {
           printf("Error:  Unable to identify input data files.  Please specify type.\n\n");
           exit(1);
       }
   }

   if (!RAWDATA) {
       char *root, *suffix;
       /* Split the filename into a rootname and a suffix */
       if (split_root_suffix(s.filenames[0], &root, &suffix) == 0) {
           printf("\nThe input filename (%s) must have a suffix!\n\n", s.filenames[0]);
           exit(1);
       }
       printf("Reading input data from '%s'.\n", s.filenames[0]);
       printf("Reading information from '%s.inf'.\n\n", root);
       /* Read the info file if available */
       readinf(&idata, root);
       free(root);
       free(suffix);
       s.files = (FILE **)malloc(sizeof(FILE *));
       s.files[0] = chkfopen(s.filenames[0], "rb");
   } else {
       char description[40];
       psrdatatype_description(description, s.datatype);
       if (s.num_files > 1)
           printf("Reading %s data from %d files:\n", description, s.num_files);
       else
           printf("Reading %s data from 1 file:\n", description);
       for (ii = 0; ii < s.num_files; ii++) {
           printf("  '%s'\n", cmd->argv[ii]);
       }
       printf("\n");
   }

   /* Determine the other file names and open the output data file */
   slen = strlen(cmd->outfile) + 8;
   datafilenm = (char *) calloc(slen, 1);
   sprintf(datafilenm, "%s.dat", cmd->outfile);
   outfile = chkfopen(datafilenm, "wb");
   sprintf(idata.name, "%s", cmd->outfile);
   outinfonm = (char *) calloc(slen, 1);
   sprintf(outinfonm, "%s.inf", cmd->outfile);

   if (RAWDATA) {
       read_rawdata_files(&s);
       print_spectra_info_summary(&s);
       spectra_info_to_inf(&s, &idata);
       
       /* Finish setting up stuff common to all raw formats */
       idata.dm = cmd->dm;
       worklen = s.spectra_per_subint;
       if (cmd->maskfileP)
           maskchans = gen_ivect(idata.num_chan);
       /* Compare the size of the data to the size of output we request */
       if (cmd->numoutP) {
           dtmp = idata.N;
           idata.N = cmd->numout;
           writeinf(&idata);
           idata.N = dtmp;
       } else {
           cmd->numout = INT_MAX;
           writeinf(&idata);
       }
       /* The number of topo to bary time points to generate with TEMPO */
       numbarypts = (long) (idata.dt * idata.N * 1.1 / TDT + 5.5) + 1;
       
       // Identify the TEMPO observatory code
       {
           char *outscope = (char *) calloc(40, sizeof(char));
           telescope_to_tempocode(idata.telescope, outscope, obs);
           free(outscope);
       }
   }

   /* Read an input mask if wanted */
   if (cmd->maskfileP) {
      read_mask(cmd->maskfile, &obsmask);
      printf("Read mask information from '%s'\n\n", cmd->maskfile);
      good_padvals = determine_padvals(cmd->maskfile, &obsmask, s.padvals);
   } else {
      obsmask.numchan = obsmask.numint = 0;
   }

   /* Determine our initialization data if we do _not_ have Parkes, */
   /* Green Bank BCPM, or Arecibo WAPP data sets.                   */
   if (!RAWDATA) {

      /* If we will be barycentering... */
      if (!cmd->nobaryP) {

         /* The number of topo to bary time points to generate with TEMPO */
         numbarypts = (long) (idata.dt * idata.N * 1.1 / TDT + 5.5) + 1;
         
         // Identify the TEMPO observatory code
         {
             char *outscope = (char *) calloc(40, sizeof(char));
             telescope_to_tempocode(idata.telescope, outscope, obs);
             free(outscope);
         }

      }

      /* The number of data points to work with at a time */
      if (worklen > idata.N)
          worklen = idata.N;
      worklen = (long) (worklen / 1024) * 1024;

      /* Compare the size of the data to the size of output we request */
      if (!cmd->numoutP)
         cmd->numout = INT_MAX;
   }
   
   /* Check if we are downsampling */
   dsdt = idata.dt * cmd->downsamp;
   if (cmd->downsamp > 1) {
      printf("Downsampling by a factor of %d\n", cmd->downsamp);
      printf("New sample dt = %.10g\n\n", dsdt);
      if (worklen % cmd->downsamp) {
         printf("Error:  The downsample factor (%d) must be a factor of the\n",
                cmd->downsamp);
         printf("        worklength (%ld).  Exiting.\n\n", worklen);
         exit(1);
      }
   }
   printf("Writing output data to '%s'.\n", datafilenm);
   printf("Writing information to '%s'.\n\n", outinfonm);

   /* The topocentric epoch of the start of the data */
   tlotoa = (double) idata.mjd_i + idata.mjd_f;

   if (!strcmp(idata.band, "Radio") && RAWDATA) {

      /* The topocentric spacing between channels */
      tdf = idata.chan_wid;
      numchan = idata.num_chan;

      /* The topocentric observation frequencies */
      tobsf = gen_dvect(numchan);
      tobsf[0] = idata.freq;
      for (ii = 0; ii < numchan; ii++)
         tobsf[ii] = tobsf[0] + ii * tdf;

      /* The dispersion delays (in time bins) */
      dispdt = gen_dvect(numchan);  // full float bins
      idispdt = gen_ivect(numchan); // nearest integer bins

      if (cmd->nobaryP) {

         /* Determine our dispersion time delays for each channel */
         for (ii = 0; ii < numchan; ii++)
            dispdt[ii] = delay_from_dm(cmd->dm, tobsf[ii]);

         /* The highest frequency channel gets no delay                 */
         /* All other delays are positive fractions of bin length (dt)  */
         dtmp = dispdt[numchan - 1];
         for (ii = 0; ii < numchan; ii++) {
            dispdt[ii] = (dispdt[ii] - dtmp) / idata.dt;
            idispdt[ii] = (int) (dispdt[ii] + 0.5);
         }
         worklen *= ((int) (fabs(dispdt[0])) / worklen) + 1;
      }

   } else {                     /* For unknown radio raw data (Why is this here?) */
      tobsf = gen_dvect(numchan);
      dispdt = gen_dvect(numchan);
      idispdt = gen_ivect(numchan);
      dispdt[0] = 0.0;
      idispdt[0] = 0;
      if (!strcmp(idata.band, "Radio")) {
         tobsf[0] = idata.freq + (idata.num_chan - 1) * idata.chan_wid;
         cmd->dm = idata.dm;
      } else {
         tobsf[0] = 0.0;
         cmd->dm = 0.0;
      }
   }

   if (cmd->nobaryP) {          /* Main loop if we are not barycentering... */

      /* Allocate our data array */
      outdata = gen_fvect(worklen);

      printf("Massaging the data ...\n\n");
      printf("Amount Complete = 0%%");

      do {
          if (RAWDATA) 
              numread = read_psrdata(outdata, worklen, &s, idispdt, &padding, 
                                     maskchans, &nummasked, &obsmask);
          else if (useshorts)
              numread = read_shorts(s.files[0], outdata, worklen, numchan);
          else
              numread = read_floats(s.files[0], outdata, worklen, numchan);
          if (numread == 0)
              break;
          
          /* Downsample if requested */
          if (cmd->downsamp > 1)
              numread = downsample(outdata, numread, cmd->downsamp);

          /* Print percent complete */
          if (cmd->numoutP)
              newper = (int) ((float) totwrote / cmd->numout * 100.0) + 1;
          else
              newper = (int) ((float) totwrote * cmd->downsamp * 100.0 / idata.N) + 1;
          if (newper > oldper) {
              printf("\rAmount Complete = %3d%%", newper);
              fflush(stdout);
              oldper = newper;
          }
          
          /* Write the latest chunk of data, but don't   */
          /* write more than cmd->numout points.         */
          numtowrite = numread;
          if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout)
              numtowrite = cmd->numout - totwrote;
          chkfwrite(outdata, sizeof(float), numtowrite, outfile);
          totwrote += numtowrite;
          
          /* Update the statistics */
          if (!padding) {
              for (ii = 0; ii < numtowrite; ii++)
                  update_stats(statnum + ii, outdata[ii], &min, &max, &avg, &var);
              statnum += numtowrite;
          }

          /* Stop if we have written out all the data we need to */
          if (cmd->numoutP && (totwrote == cmd->numout))
              break;
          
      } while (numread);
      
      datawrote = totwrote;
      
   } else {                     /* Main loop if we are barycentering... */

      double avgvoverc = 0.0, maxvoverc = -1.0, minvoverc = 1.0, *voverc = NULL;
      double *bobsf = NULL, *btoa = NULL, *ttoa = NULL;

      /* What ephemeris will we use?  (Default is DE200) */
      if (cmd->de405P)
         strcpy(ephem, "DE405");
      else
         strcpy(ephem, "DE200");

      /* Define the RA and DEC of the observation */
      ra_dec_to_string(rastring, idata.ra_h, idata.ra_m, idata.ra_s);
      ra_dec_to_string(decstring, idata.dec_d, idata.dec_m, idata.dec_s);

      /* Allocate some arrays */
      bobsf = gen_dvect(numchan);
      btoa = gen_dvect(numbarypts);
      ttoa = gen_dvect(numbarypts);
      voverc = gen_dvect(numbarypts);
      for (ii = 0; ii < numbarypts; ii++)
         ttoa[ii] = tlotoa + TDT * ii / SECPERDAY;

      /* Call TEMPO for the barycentering */
      printf("Generating barycentric corrections...\n");
      barycenter(ttoa, btoa, voverc, numbarypts, rastring, decstring, obs, ephem);
      for (ii = 0; ii < numbarypts; ii++) {
         if (voverc[ii] > maxvoverc)
            maxvoverc = voverc[ii];
         if (voverc[ii] < minvoverc)
            minvoverc = voverc[ii];
         avgvoverc += voverc[ii];
      }
      avgvoverc /= numbarypts;
      vect_free(voverc);
      blotoa = btoa[0];

      printf("   Average topocentric velocity (c) = %.7g\n", avgvoverc);
      printf("   Maximum topocentric velocity (c) = %.7g\n", maxvoverc);
      printf("   Minimum topocentric velocity (c) = %.7g\n\n", minvoverc);
      printf("Collecting and barycentering %s...\n\n", cmd->argv[0]);

      /* Determine the initial dispersion time delays for each channel */
      for (ii = 0; ii < numchan; ii++) {
         bobsf[ii] = doppler(tobsf[ii], avgvoverc);
         dispdt[ii] = delay_from_dm(cmd->dm, bobsf[ii]);
      }

      /* The highest frequency channel gets no delay                   */
      /* All other delays are positive fractions of bin length (dt)    */
      barydispdt = dispdt[numchan - 1];
      for (ii = 0; ii < numchan; ii++) {
         dispdt[ii] = (dispdt[ii] - barydispdt) / idata.dt;
         idispdt[ii] = (int) (dispdt[ii] + 0.5);
      }
      if (RAWDATA)
         worklen *= ((int) (dispdt[0]) / worklen) + 1;

      /* If the data is de-dispersed radio data... */
      if (!strcmp(idata.band, "Radio")) {
         printf("The DM of %.2f at the barycentric observing freq of %.3f MHz\n",
                idata.dm, bobsf[numchan - 1]);
         printf("   causes a delay of %f seconds compared to infinite freq.\n",
                barydispdt);
         printf("   This delay is removed from the barycented times.\n\n");
      }
      printf("Topocentric epoch (at data start) is:\n");
      printf("   %17.11f\n\n", tlotoa);
      printf("Barycentric epoch (infinite obs freq at data start) is:\n");
      printf("   %17.11f\n\n", blotoa - (barydispdt / SECPERDAY));

      /* Convert the bary TOAs to differences from the topo TOAs in  */
      /* units of bin length (dsdt) rounded to the nearest integer.  */
      dtmp = (btoa[0] - ttoa[0]);
      for (ii = 0; ii < numbarypts; ii++)
         btoa[ii] = ((btoa[ii] - ttoa[ii]) - dtmp) * SECPERDAY / dsdt;

      {                         /* Find the points where we need to add or remove bins */

         int oldbin = 0, currentbin;
         double lobin, hibin, calcpt;

         numdiffbins = abs(NEAREST_INT(btoa[numbarypts - 1])) + 1;
         diffbins = gen_ivect(numdiffbins);
         diffbinptr = diffbins;
         for (ii = 1; ii < numbarypts; ii++) {
            currentbin = NEAREST_INT(btoa[ii]);
            if (currentbin != oldbin) {
               if (currentbin > 0) {
                  calcpt = oldbin + 0.5;
                  lobin = (ii - 1) * TDT / dsdt;
                  hibin = ii * TDT / dsdt;
               } else {
                  calcpt = oldbin - 0.5;
                  lobin = -((ii - 1) * TDT / dsdt);
                  hibin = -(ii * TDT / dsdt);
               }
               while (fabs(calcpt) < fabs(btoa[ii])) {
                  /* Negative bin number means remove that bin */
                  /* Positive bin number means add a bin there */
                  *diffbinptr = NEAREST_INT(LININTERP(calcpt, btoa[ii - 1],
                                                      btoa[ii], lobin, hibin));
                  diffbinptr++;
                  calcpt = (currentbin > 0) ? calcpt + 1.0 : calcpt - 1.0;
               }
               oldbin = currentbin;
            }
         }
         *diffbinptr = cmd->numout; /* Used as a marker */
      }
      diffbinptr = diffbins;

      /* Now perform the barycentering */

      printf("Massaging the data...\n\n");
      printf("Amount Complete = 0%%");

      /* Allocate our data array */

      outdata = gen_fvect(worklen);

      do {                      /* Loop to read and write the data */
          int numwritten = 0;
          double block_avg, block_var;
          
          if (RAWDATA) 
              numread = read_psrdata(outdata, worklen, &s, idispdt, &padding, 
                                     maskchans, &nummasked, &obsmask);
          else if (useshorts)
              numread = read_shorts(s.files[0], outdata, worklen, numchan);
          else
              numread = read_floats(s.files[0], outdata, worklen, numchan);
          if (numread == 0)
              break;
          
          /* Downsample if requested */
          if (cmd->downsamp > 1)
              numread = downsample(outdata, numread, cmd->downsamp);
          
          /* Determine the approximate local average */
          avg_var(outdata, numread, &block_avg, &block_var);
          
          /* Print percent complete */
          
          if (cmd->numoutP)
              newper = (int) ((float) totwrote / cmd->numout * 100.0) + 1;
          else
              newper = (int) ((float) totwrote * cmd->downsamp * 100.0 / idata.N) + 1;
          if (newper > oldper) {
              printf("\rAmount Complete = %3d%%", newper);
              fflush(stdout);
              oldper = newper;
          }

         /* Simply write the data if we don't have to add or */
         /* remove any bins from this batch.                 */
         /* OR write the amount of data up to cmd->numout or */
         /* the next bin that will be added or removed.      */

         numtowrite = abs(*diffbinptr) - datawrote;
         /* FIXME: numtowrite+totwrote can wrap! */
         if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout)
            numtowrite = cmd->numout - totwrote;
         if (numtowrite > numread)
            numtowrite = numread;
         chkfwrite(outdata, sizeof(float), numtowrite, outfile);
         datawrote += numtowrite;
         totwrote += numtowrite;
         numwritten += numtowrite;

         /* Update the statistics */

         if (!padding) {
            for (ii = 0; ii < numtowrite; ii++)
               update_stats(statnum + ii, outdata[ii], &min, &max, &avg, &var);
            statnum += numtowrite;
         }

         if ((datawrote == abs(*diffbinptr)) && (numwritten != numread) && (totwrote < cmd->numout)) {  /* Add/remove a bin */
            float favg;
            int skip, nextdiffbin;

            skip = numtowrite;

            do {                /* Write the rest of the data after adding/removing a bin  */

               if (*diffbinptr > 0) {

                  /* Add a bin */

                  favg = (float) block_avg;
                  chkfwrite(&favg, sizeof(float), 1, outfile);
                  numadded++;
                  totwrote++;
               } else {

                  /* Remove a bin */

                  numremoved++;
                  datawrote++;
                  numwritten++;
                  skip++;
               }
               diffbinptr++;

               /* Write the part after the diffbin */

               numtowrite = numread - numwritten;
               if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout)
                  numtowrite = cmd->numout - totwrote;
               nextdiffbin = abs(*diffbinptr) - datawrote;
               if (numtowrite > nextdiffbin)
                  numtowrite = nextdiffbin;
               chkfwrite(outdata + skip, sizeof(float), numtowrite, outfile);
               numwritten += numtowrite;
               datawrote += numtowrite;
               totwrote += numtowrite;

               /* Update the statistics and counters */

               if (!padding) {
                  for (ii = 0; ii < numtowrite; ii++)
                     update_stats(statnum + ii, outdata[skip + ii],
                                  &min, &max, &avg, &var);
                  statnum += numtowrite;
               }
               skip += numtowrite;

               /* Stop if we have written out all the data we need to */

               if (cmd->numoutP && (totwrote == cmd->numout))
                  break;
            } while (numwritten < numread);
         }
         /* Stop if we have written out all the data we need to */

         if (cmd->numoutP && (totwrote == cmd->numout))
            break;

      } while (numread);

      /* Free the arrays used in barycentering */

      vect_free(bobsf);
      vect_free(btoa);
      vect_free(ttoa);
   }

   /* Calculate what the amount of padding we need  */

   if (cmd->numoutP && (cmd->numout > totwrote))
      padwrote = padtowrite = cmd->numout - totwrote;


   /* Write the new info file for the output data */

   if (!cmd->nobaryP) {
      idata.bary = 1;
      idata.mjd_i = (int) floor(blotoa - (barydispdt / SECPERDAY));
      idata.mjd_f = blotoa - (barydispdt / SECPERDAY) - idata.mjd_i;
   }
   if (cmd->downsamp > 1)
      idata.dt = dsdt;
   update_infodata(&idata, totwrote, padtowrite, diffbins, numdiffbins);
   writeinf(&idata);

   /* Set the padded points equal to the average data point */

   if (idata.numonoff >= 1) {
      int jj, index, startpad, endpad;

      for (ii = 0; ii < worklen; ii++)
         outdata[ii] = avg;
      fclose(outfile);
      outfile = chkfopen(datafilenm, "rb+");
      for (ii = 0; ii < idata.numonoff; ii++) {
         index = 2 * ii;
         startpad = idata.onoff[index + 1];
         if (ii == idata.numonoff - 1)
            endpad = idata.N - 1;
         else
            endpad = idata.onoff[index + 2];
         chkfseek(outfile, (startpad + 1) * sizeof(float), SEEK_SET);
         padtowrite = endpad - startpad;
         for (jj = 0; jj < padtowrite / worklen; jj++)
            chkfwrite(outdata, sizeof(float), worklen, outfile);
         chkfwrite(outdata, sizeof(float), padtowrite % worklen, outfile);
      }
   }
   vect_free(outdata);

   //  Close all the raw files and free their vectors
   close_rawfiles(&s);

   /* Print simple stats and results */

   var /= (datawrote - 1);

   /* Conver the '.dat' file to '.sdat' if requested */

   if (cmd->shortsP) {
      FILE *infile;
      int safe_convert = 1, bufflen = 65536;
      char *sdatafilenm;
      float *fbuffer;
      short *sbuffer;

      offset = (int) (floor(avg));
      if ((max - min) > (SHRT_MAX - SHRT_MIN)) {
         if ((max - min) < 1.5 * (SHRT_MAX - SHRT_MIN)) {
            printf("Warning:  There is more dynamic range in the data\n"
                   "          than can be handled perfectly:\n"
                   "               max - min = %.2f - %.2f = %.2f\n"
                   "          Clipping the low values...\n\n", max, min, max - min);
            offset = max - SHRT_MAX;
         } else {
            printf("Error:  There is way too much dynamic range in the data:\n"
                   "               max - min = %.2f - %.2f = %.2f\n"
                   "        Not converting to shorts.\n\n", max, min, max - min);
            safe_convert = 0;
         }
      }

      if (safe_convert) {
         fbuffer = gen_fvect(bufflen);
         sbuffer = gen_svect(bufflen);
         sdatafilenm = (char *) calloc(slen, 1);
         sprintf(sdatafilenm, "%s.sdat", cmd->outfile);
         printf("\n\nConverting floats in '%s' to shorts in '%s'.",
                datafilenm, sdatafilenm);
         fflush(NULL);

         infile = chkfopen(datafilenm, "rb");
         outfile = chkfopen(sdatafilenm, "wb");
         while ((numread = chkfread(fbuffer, sizeof(float), bufflen, infile))) {
            for (ii = 0; ii < numread; ii++)
               sbuffer[ii] = (short) (fbuffer[ii] + 1e-20 - offset);
            chkfwrite(sbuffer, sizeof(short), numread, outfile);
         }
         fclose(infile);
         fclose(outfile);
         remove(datafilenm);
         vect_free(fbuffer);
         vect_free(sbuffer);
      }
   }

   printf("\n\nDone.\n\nSimple statistics of the output data:\n");
   printf("             Data points written:  %ld\n", totwrote);
   if (padwrote)
      printf("          Padding points written:  %ld\n", padwrote);
   if (!cmd->nobaryP) {
      if (numadded)
         printf("    Bins added for barycentering:  %d\n", numadded);
      if (numremoved)
         printf("  Bins removed for barycentering:  %d\n", numremoved);
   }
   printf("           Maximum value of data:  %.2f\n", max);
   printf("           Minimum value of data:  %.2f\n", min);
   printf("              Data average value:  %.2f\n", avg);
   printf("         Data standard deviation:  %.2f\n", sqrt(var));
   if (cmd->shortsP && offset != 0)
      printf("          Offset applied to data:  %d\n", -offset);
   printf("\n");

   /* Cleanup */

   if (cmd->maskfileP) {
      free_mask(obsmask);
      vect_free(maskchans);
   }
   vect_free(tobsf);
   vect_free(dispdt);
   vect_free(idispdt);
   free(outinfonm);
   free(datafilenm);
   if (!cmd->nobaryP)
      vect_free(diffbins);
   return (0);
}