Example #1
0
void read_PSRFITS_files(struct spectra_info *s)
// Read and convert PSRFITS information from a group of files 
// and place the resulting info into a spectra_info structure.
{
    int IMJD, SMJD, itmp, ii, status = 0;
    double OFFS, dtmp;
    long double MJDf;
    char ctmp[80], comment[120];
    
    s->datatype = PSRFITS;
    s->fitsfiles = (fitsfile **)malloc(sizeof(fitsfile *) * s->num_files);
    s->start_subint = gen_ivect(s->num_files);
    s->num_subint = gen_ivect(s->num_files);
    s->start_spec = (long long *)malloc(sizeof(long long) * s->num_files);
    s->num_spec = (long long *)malloc(sizeof(long long) * s->num_files);
    s->num_pad = (long long *)malloc(sizeof(long long) * s->num_files);
    s->start_MJD = (long double *)malloc(sizeof(long double) * s->num_files);
    s->N = 0;
    s->num_beams = 1;
    s->get_rawblock = &get_PSRFITS_rawblock;
    s->offset_to_spectra = &offset_to_PSRFITS_spectra;

    // By default, don't flip the band.  But don't change
    // the input value if it is aleady set to flip the band always
    if (s->apply_flipband==-1) s->apply_flipband = 0;

    // Step through the other files
    for (ii = 0 ; ii < s->num_files ; ii++) {

        // Is the file a PSRFITS file?
        if (!is_PSRFITS(s->filenames[ii])) {
            fprintf(stderr, 
                    "\nError!  File '%s' does not appear to be PSRFITS!\n", 
                    s->filenames[ii]);
            exit(1);
        }
        
        // Open the PSRFITS file
        fits_open_file(&(s->fitsfiles[ii]), s->filenames[ii], READONLY, &status);

        // Is the data in search mode?
        fits_read_key(s->fitsfiles[ii], TSTRING, "OBS_MODE", ctmp, comment, &status);
        // Quick fix for Parkes DFB data (SRCH?  why????)...
        if (strcmp("SRCH", ctmp)==0) {
            strncpy(ctmp, "SEARCH", 40);
        }
        if (strcmp(ctmp, "SEARCH")) {
            fprintf(stderr, 
                    "\nError!  File '%s' does not contain SEARCH-mode data!\n", 
                    s->filenames[ii]);
            exit(1);
        }

        // Now get the stuff we need from the primary HDU header
        fits_read_key(s->fitsfiles[ii], TSTRING, "TELESCOP", ctmp, comment, &status); \
        // Quick fix for MockSpec data...
        if (strcmp("ARECIBO 305m", ctmp)==0) {
            strncpy(ctmp, "Arecibo", 40);
        }
        // Quick fix for Parkes DFB data...
        {
            char newctmp[80];

            // Copy ctmp first since strlower() is in-place
            strcpy(newctmp, ctmp);
            if (strcmp("parkes", strlower(remove_whitespace(newctmp)))==0) {
                strncpy(ctmp, "Parkes", 40);
            }
        }
        if (status) {
            printf("Error %d reading key %s\n", status, "TELESCOP");
            if (ii==0) s->telescope[0]='\0';
            if (status==KEY_NO_EXIST) status=0;
        } else {
            if (ii==0) strncpy(s->telescope, ctmp, 40);
            else if (strcmp(s->telescope, ctmp)!=0)
                printf("Warning!:  %s values don't match for files 0 and %d!\n",
                       "TELESCOP", ii);
        }

        get_hdr_string("OBSERVER", s->observer);
        get_hdr_string("SRC_NAME", s->source);
        get_hdr_string("FRONTEND", s->frontend);
        get_hdr_string("BACKEND", s->backend);
        get_hdr_string("PROJID", s->project_id);
        get_hdr_string("DATE-OBS", s->date_obs);
        get_hdr_string("FD_POLN", s->poln_type);
        get_hdr_string("RA", s->ra_str);
        get_hdr_string("DEC", s->dec_str);
        get_hdr_double("OBSFREQ", s->fctr);
        get_hdr_int("OBSNCHAN", s->orig_num_chan);
        get_hdr_double("OBSBW", s->orig_df);
        //get_hdr_double("CHAN_DM", s->chan_dm);
        get_hdr_double("BMIN", s->beam_FWHM);

        /* This is likely not in earlier versions of PSRFITS so */
        /* treat it a bit differently                           */
        fits_read_key(s->fitsfiles[ii], TDOUBLE, "CHAN_DM", 
                      &(s->chan_dm), comment, &status);
        if (status==KEY_NO_EXIST) {
            status = 0;
            s->chan_dm = 0.0;
        }

        // Don't use the macros unless you are using the struct!
        fits_read_key(s->fitsfiles[ii], TINT, "STT_IMJD", &IMJD, comment, &status);
        s->start_MJD[ii] = (long double) IMJD;
        fits_read_key(s->fitsfiles[ii], TINT, "STT_SMJD", &SMJD, comment, &status);
        fits_read_key(s->fitsfiles[ii], TDOUBLE, "STT_OFFS", &OFFS, comment, &status);
        s->start_MJD[ii] += ((long double) SMJD + (long double) OFFS) / SECPERDAY;

        // Are we tracking?
        fits_read_key(s->fitsfiles[ii], TSTRING, "TRK_MODE", ctmp, comment, &status);
        itmp = (strcmp("TRACK", ctmp)==0) ? 1 : 0;
        if (ii==0) s->tracking = itmp;
        else if (s->tracking != itmp)
            printf("Warning!:  TRK_MODE values don't match for files 0 and %d!\n", ii);

        // Now switch to the SUBINT HDU header
        fits_movnam_hdu(s->fitsfiles[ii], BINARY_TBL, "SUBINT", 0, &status);
        get_hdr_double("TBIN", s->dt);
        get_hdr_int("NCHAN", s->num_channels);
        get_hdr_int("NPOL", s->num_polns);
        get_hdr_string("POL_TYPE", s->poln_order);
        fits_read_key(s->fitsfiles[ii], TINT, "NCHNOFFS", &itmp, comment, &status);
        if (itmp > 0)
            printf("Warning!:  First freq channel is not 0 in file %d!\n", ii);
        get_hdr_int("NSBLK", s->spectra_per_subint);
        get_hdr_int("NBITS", s->bits_per_sample);
        fits_read_key(s->fitsfiles[ii], TINT, "NAXIS2", 
                      &(s->num_subint[ii]), comment, &status);
        fits_read_key(s->fitsfiles[ii], TINT, "NSUBOFFS", 
                      &(s->start_subint[ii]), comment, &status);
        s->time_per_subint = s->dt * s->spectra_per_subint;

        /* This is likely not in earlier versions of PSRFITS so */
        /* treat it a bit differently                           */
        fits_read_key(s->fitsfiles[ii], TFLOAT, "ZERO_OFF", 
                      &(s->zero_offset), comment, &status);
        if (status==KEY_NO_EXIST) {
            status = 0;
            s->zero_offset = 0.0;
        }
        s->zero_offset = fabs(s->zero_offset);

        // Get the time offset column info and the offset for the 1st row
        {
            double offs_sub;
            int colnum, anynull, numrows;

            // Identify the OFFS_SUB column number
            fits_get_colnum(s->fitsfiles[ii], 0, "OFFS_SUB", &colnum, &status);
            if (status==COL_NOT_FOUND) {
                printf("Warning!:  Can't find the OFFS_SUB column!\n");
                status = 0; // Reset status
            } else {
                if (ii==0) {
                    s->offs_sub_col = colnum;
                } else if (colnum != s->offs_sub_col) {
                    printf("Warning!:  OFFS_SUB column changes between files!\n");
                }
            }

            // Read the OFFS_SUB column value for the 1st row
            fits_read_col(s->fitsfiles[ii], TDOUBLE,
                          s->offs_sub_col, 1L, 1L, 1L,
                          0, &offs_sub, &anynull, &status);

            numrows = (int)((offs_sub - 0.5 * s->time_per_subint) /
                            s->time_per_subint + 1e-7);
            // Check to see if any rows have been deleted or are missing
            if (numrows > s->start_subint[ii]) {
                printf("Warning: NSUBOFFS reports %d previous rows\n"
                       "         but OFFS_SUB implies %d.  Using OFFS_SUB.\n"
                       "         Will likely be able to correct for this.\n",
                       s->start_subint[ii], numrows);
            }
            s->start_subint[ii] = numrows;
        }

        // This is the MJD offset based on the starting subint number
        MJDf = (s->time_per_subint * s->start_subint[ii]) / SECPERDAY;
        // The start_MJD values should always be correct
        s->start_MJD[ii] += MJDf;

        // Compute the starting spectra from the times
        MJDf = s->start_MJD[ii] - s->start_MJD[0];
        if (MJDf < 0.0) {
            fprintf(stderr, "Error!: File %d seems to be from before file 0!\n", ii); 
            exit(1);
        }
        s->start_spec[ii] = (long long)(MJDf * SECPERDAY / s->dt + 0.5);

        // Now pull stuff from the other columns
        {
            float ftmp;
            long repeat, width;
            int colnum, anynull;
            
            // Identify the data column and the data type
            fits_get_colnum(s->fitsfiles[ii], 0, "DATA", &colnum, &status);
            if (status==COL_NOT_FOUND) {
                printf("Warning!:  Can't find the DATA column!\n");
                status = 0; // Reset status
            } else {
                if (ii==0) {
                    s->data_col = colnum;
                    fits_get_coltype(s->fitsfiles[ii], colnum, &(s->FITS_typecode), 
                                     &repeat, &width, &status);
                } else if (colnum != s->data_col) {
                    printf("Warning!:  DATA column changes between files!\n");
                }
            }
            
            // Telescope azimuth
            fits_get_colnum(s->fitsfiles[ii], 0, "TEL_AZ", &colnum, &status);
            if (status==COL_NOT_FOUND) {
                s->azimuth = 0.0;
                status = 0; // Reset status
            } else {
                fits_read_col(s->fitsfiles[ii], TFLOAT, colnum, 
                              1L, 1L, 1L, 0, &ftmp, &anynull, &status);
                if (ii==0) s->azimuth = (double) ftmp;
            }
            
            // Telescope zenith angle
            fits_get_colnum(s->fitsfiles[ii], 0, "TEL_ZEN", &colnum, &status);
            if (status==COL_NOT_FOUND) {
                s->zenith_ang = 0.0;
                status = 0; // Reset status
            } else {
                fits_read_col(s->fitsfiles[ii], TFLOAT, colnum, 
                              1L, 1L, 1L, 0, &ftmp, &anynull, &status);
                if (ii==0) s->zenith_ang = (double) ftmp;
            }
            
            // Observing frequencies
            fits_get_colnum(s->fitsfiles[ii], 0, "DAT_FREQ", &colnum, &status);
            if (status==COL_NOT_FOUND) {
                printf("Warning!:  Can't find the channel freq column!\n");
                status = 0; // Reset status
            } else {
                int jj;
                float *freqs = (float *)malloc(sizeof(float) * s->num_channels);
                fits_read_col(s->fitsfiles[ii], TFLOAT, colnum, 1L, 1L, 
                              s->num_channels, 0, freqs, &anynull, &status);
                
                if (ii==0) {
                    s->df = freqs[1]-freqs[0];
                    s->lo_freq = freqs[0];
                    s->hi_freq = freqs[s->num_channels-1];
                    // Now check that the channel spacing is the same throughout
                    for (jj = 0 ; jj < s->num_channels - 1 ; jj++) {
                        ftmp = freqs[jj+1] - freqs[jj];
                        if (fabs(ftmp - s->df) > 1e-7)
                            printf("Warning!:  Channel spacing changes in file %d!\n", ii);
                    }
                } else {
                    ftmp = fabs(s->df-(freqs[1]-freqs[0]));
                    if (ftmp > 1e-7)
                        printf("Warning!:  Channel spacing changes between files!\n");
                    ftmp = fabs(s->lo_freq-freqs[0]);
                    if (ftmp > 1e-7)
                        printf("Warning!:  Low channel changes between files!\n");
                    ftmp = fabs(s->hi_freq-freqs[s->num_channels-1]);
                    if (ftmp > 1e-7)
                        printf("Warning!:  High channel changes between files!\n");
                }
                free(freqs);
            }
            
            // Data weights
            fits_get_colnum(s->fitsfiles[ii], 0, "DAT_WTS", &colnum, &status);
            if (status==COL_NOT_FOUND) {
                printf("Warning!:  Can't find the channel weights!\n");
                status = 0; // Reset status
            } else {
                if (s->apply_weight < 0) { // Use the data to decide
                    int jj;
                    if (ii==0) {
                        s->dat_wts_col = colnum;
                    } else if (colnum != s->dat_wts_col) {
                        printf("Warning!:  DAT_WTS column changes between files!\n");
                    }
                    float *fvec = (float *)malloc(sizeof(float) * s->num_channels);
                    fits_read_col(s->fitsfiles[ii], TFLOAT, s->dat_wts_col, 1L, 1L, 
                                  s->num_channels, 0, fvec, &anynull, &status);
                    for (jj = 0 ; jj < s->num_channels ; jj++) {
                        // If the weights are not 1, apply them
                        if (fvec[jj] != 1.0) {
                            s->apply_weight = 1;
                            break;
                        }
                    }
                    free(fvec);
                }
                if (s->apply_weight < 0) s->apply_weight = 0;  // not needed
            }
            
            // Data offsets
            fits_get_colnum(s->fitsfiles[ii], 0, "DAT_OFFS", &colnum, &status);
            if (status==COL_NOT_FOUND) {
                printf("Warning!:  Can't find the channel offsets!\n");
                status = 0; // Reset status
            } else {
                if (s->apply_offset < 0) { // Use the data to decide
                    int jj;
                    if (ii==0) {
                        s->dat_offs_col = colnum;
                    } else if (colnum != s->dat_offs_col) {
                        printf("Warning!:  DAT_OFFS column changes between files!\n");
                    }
                    float *fvec = (float *)malloc(sizeof(float) * 
                                                  s->num_channels * s->num_polns);
                    fits_read_col(s->fitsfiles[ii], TFLOAT, s->dat_offs_col, 1L, 1L, 
                                  s->num_channels * s->num_polns, 
                                  0, fvec, &anynull, &status);
                    for (jj = 0 ; jj < s->num_channels * s->num_polns ; jj++) {
                        // If the offsets are not 0, apply them
                        if (fvec[jj] != 0.0) {
                            s->apply_offset = 1;
                            break;
                        }
                    }
                    free(fvec);
                }
                if (s->apply_offset < 0) s->apply_offset = 0; // not needed
            }
            
            // Data scalings
            fits_get_colnum(s->fitsfiles[ii], 0, "DAT_SCL", &colnum, &status);
            if (status==COL_NOT_FOUND) {
                printf("Warning!:  Can't find the channel scalings!\n");
                status = 0; // Reset status
            } else {
                if (s->apply_scale < 0) { // Use the data to decide
                    int jj;
                    if (ii==0) {
                        s->dat_scl_col = colnum;
                    } else if (colnum != s->dat_scl_col) {
                        printf("Warning!:  DAT_SCL column changes between files!\n");
                    }
                    float *fvec = (float *)malloc(sizeof(float) * 
                                                  s->num_channels * s->num_polns);
                    fits_read_col(s->fitsfiles[ii], TFLOAT, colnum, 1L, 1L, 
                                  s->num_channels * s->num_polns, 
                                  0, fvec, &anynull, &status);
                    for (jj = 0 ; jj < s->num_channels * s->num_polns ; jj++) {
                        // If the scales are not 1, apply them
                        if (fvec[jj] != 1.0) {
                            s->apply_scale = 1;
                            break;
                        }
                    }
                    free(fvec);
                }
                if (s->apply_scale < 0) s->apply_scale = 0; // not needed
            }
        }
        
        // Compute the samples per file and the amount of padding
        // that the _previous_ file has
        s->num_pad[ii] = 0;
        s->num_spec[ii] = s->spectra_per_subint * s->num_subint[ii];
        if (ii > 0) {
            if (s->start_spec[ii] > s->N) { // Need padding
                s->num_pad[ii-1] = s->start_spec[ii] - s->N;
                s->N += s->num_pad[ii-1];
            }
        }
        s->N += s->num_spec[ii];
    }

    // Convert the position strings into degrees
    {
        int d, h, m;
        double sec;
        ra_dec_from_string(s->ra_str, &h, &m, &sec);
        s->ra2000 = hms2rad(h, m, sec) * RADTODEG;
        ra_dec_from_string(s->dec_str, &d, &m, &sec);
        s->dec2000 = dms2rad(d, m, sec) * RADTODEG;
    }

    // Are the polarizations summed?
    if ((strncmp("AA+BB", s->poln_order, 5)==0) ||
        (strncmp("INTEN", s->poln_order, 5)==0))
        s->summed_polns = 1;
    else
        s->summed_polns = 0;

    // Calculate some others
    s->T = s->N * s->dt;
    s->orig_df /= (double) s->orig_num_chan;
    s->samples_per_spectra = s->num_polns * s->num_channels;
    // Note:  the following is the number of bytes that will be in
    //        the returned array from CFITSIO.
    //        CFITSIO turns bits into bytes when FITS_typecode=1
    //        and we turn 2-bits or 4-bits into bytes if bits_per_sample < 8
    if (s->bits_per_sample < 8)
        s->bytes_per_spectra = s->samples_per_spectra;
    else
        s->bytes_per_spectra = (s->bits_per_sample * s->samples_per_spectra) / 8;
    s->samples_per_subint = s->samples_per_spectra * s->spectra_per_subint;
    s->bytes_per_subint = s->bytes_per_spectra * s->spectra_per_subint;
    
    // Flip the band?
    if (s->hi_freq < s->lo_freq) {
        float ftmp = s->hi_freq;
        s->hi_freq = s->lo_freq;
        s->lo_freq = ftmp;
        s->df *= -1.0;
        s->apply_flipband = 1;
    }
    // Compute the bandwidth
    s->BW = s->num_channels * s->df;

    // Flip the bytes for Parkes FB_1BIT data
    if (s->bits_per_sample==1 &&
        strcmp(s->telescope, "Parkes")==0 &&
        strcmp(s->backend, "FB_1BIT")==0) {
        printf("Flipping bit ordering since Parkes FB_1BIT data.\n");
        s->flip_bytes = 1;
    } else {
        s->flip_bytes = 0;
    }

    // Allocate the buffers
    cdatabuffer = gen_bvect(s->bytes_per_subint);
    // Following is twice as big because we use it as a ringbuffer too
    fdatabuffer = gen_fvect(2 * s->spectra_per_subint * s->num_channels);
    s->padvals = gen_fvect(s->num_channels);
    for (ii = 0 ; ii < s->num_channels ; ii++)
        s->padvals[ii] = 0.0;
    offsets = gen_fvect(s->num_channels * s->num_polns);
    scales = gen_fvect(s->num_channels * s->num_polns);
    weights = gen_fvect(s->num_channels);
    // Initialize these if we won't be reading them from the file
    if (s->apply_offset==0) 
        for (ii = 0 ; ii < s->num_channels * s->num_polns ; ii++)
            offsets[ii] = 0.0;
    if (s->apply_scale==0)
        for (ii = 0 ; ii < s->num_channels * s->num_polns ; ii++)
            scales[ii] = 1.0;
    if (s->apply_weight==0)
        for (ii = 0 ; ii < s->num_channels ; ii++)
            weights[ii] = 1.0;
}
Example #2
0
void output_fundamentals(fourierprops * props, GSList * list,
                         accelobs * obs, infodata * idata)
{
   double accel = 0.0, accelerr = 0.0, coherent_pow;
   int ii, jj, numcols = 12, numcands, *width, *error;
   int widths[12] = { 4, 5, 6, 8, 4, 16, 15, 15, 15, 11, 15, 20 };
   int errors[12] = { 0, 0, 0, 0, 0, 1, 1, 2, 1, 2, 2, 0 };
   char tmpstr[30], ctrstr[30], *notes;
   accelcand *cand;
   GSList *listptr;
   rzwerrs errs;
   static char **title;
   static char *titles1[] = { "", "", "Summed", "Coherent", "Num", "Period",
      "Frequency", "FFT 'r'", "Freq Deriv", "FFT 'z'",
      "Accel", ""
   };
   static char *titles2[] = { "Cand", "Sigma", "Power", "Power", "Harm", "(ms)",
      "(Hz)", "(bin)", "(Hz/s)", "(bins)",
      "(m/s^2)", "Notes"
   };

   numcands = g_slist_length(list);
   listptr = list;

   /* Close the old work file and open the cand file */

   if (!obs->dat_input)
      fclose(obs->workfile); /* Why is this here? -A */
   obs->workfile = chkfopen(obs->accelnm, "w");

   /* Set our candidate notes to all spaces */

   notes = (char *) malloc(numcands * widths[numcols - 1]);
   memset(notes, ' ', numcands * widths[numcols - 1]);

   /* Compare the candidates with the pulsar database */

   if (dms2rad(idata->ra_h, idata->ra_m, idata->ra_s) != 0.0 &&
       hms2rad(idata->dec_d, idata->dec_m, idata->dec_s) != 0.0) {
      for (ii = 0; ii < numcands; ii++) {
         comp_psr_to_cand(props + ii, idata, notes + ii * 20, 0);
      }
   }

   /* Compare the candidates with themselves */

   compare_rzw_cands(props, numcands, notes);

   /* Print the header */

   width = widths;
   title = titles1;
   for (ii = 0; ii < numcols - 1; ii++) {
      center_string(ctrstr, *title++, *width++);
      fprintf(obs->workfile, "%s  ", ctrstr);
   }
   center_string(ctrstr, *title++, *width++);
   fprintf(obs->workfile, "%s\n", ctrstr);

   width = widths;
   title = titles2;
   for (ii = 0; ii < numcols - 1; ii++) {
      center_string(ctrstr, *title++, *width++);
      fprintf(obs->workfile, "%s  ", ctrstr);
   }
   center_string(ctrstr, *title++, *width++);
   fprintf(obs->workfile, "%s\n", ctrstr);

   width = widths;
   for (ii = 0; ii < numcols - 1; ii++) {
      memset(tmpstr, '-', *width);
      tmpstr[*width++] = '\0';
      fprintf(obs->workfile, "%s--", tmpstr);
   }
   memset(tmpstr, '-', *width++);
   tmpstr[widths[ii]] = '\0';
   fprintf(obs->workfile, "%s\n", tmpstr);

   /* Print the fundamentals */

   for (ii = 0; ii < numcands; ii++) {
      width = widths;
      error = errors;
      cand = (accelcand *) (listptr->data);
      calc_rzwerrs(props + ii, obs->T, &errs);

      {                         /* Calculate the coherently summed power */
         double coherent_r = 0.0, coherent_i = 0.0;
         double phs0, phscorr, amp;
         rderivs harm;

         /* These phase calculations assume the fundamental is best */
         /* Better to irfft them and check the amplitude */
         phs0 = cand->derivs[0].phs;
         for (jj = 0; jj < cand->numharm; jj++) {
            harm = cand->derivs[jj];
            if (obs->nph > 0.0)
               amp = sqrt(harm.pow / obs->nph);
            else
               amp = sqrt(harm.pow / harm.locpow);
            phscorr = phs0 - fmod((jj + 1.0) * phs0, TWOPI);
            coherent_r += amp * cos(harm.phs + phscorr);
            coherent_i += amp * sin(harm.phs + phscorr);
         }
         coherent_pow = coherent_r * coherent_r + coherent_i * coherent_i;
      }

      sprintf(tmpstr, "%-4d", ii + 1);
      center_string(ctrstr, tmpstr, *width++);
      error++;
      fprintf(obs->workfile, "%s  ", ctrstr);

      sprintf(tmpstr, "%.2f", cand->sigma);
      center_string(ctrstr, tmpstr, *width++);
      error++;
      fprintf(obs->workfile, "%s  ", ctrstr);

      sprintf(tmpstr, "%.2f", cand->power);
      center_string(ctrstr, tmpstr, *width++);
      error++;
      fprintf(obs->workfile, "%s  ", ctrstr);

      sprintf(tmpstr, "%.2f", coherent_pow);
      center_string(ctrstr, tmpstr, *width++);
      error++;
      fprintf(obs->workfile, "%s  ", ctrstr);

      sprintf(tmpstr, "%d", cand->numharm);
      center_string(ctrstr, tmpstr, *width++);
      error++;
      fprintf(obs->workfile, "%s  ", ctrstr);

      write_val_with_err(obs->workfile, errs.p * 1000.0, errs.perr * 1000.0,
                         *error++, *width++);
      write_val_with_err(obs->workfile, errs.f, errs.ferr, *error++, *width++);
      write_val_with_err(obs->workfile, props[ii].r, props[ii].rerr,
                         *error++, *width++);
      write_val_with_err(obs->workfile, errs.fd, errs.fderr, *error++, *width++);
      write_val_with_err(obs->workfile, props[ii].z, props[ii].zerr,
                         *error++, *width++);
      accel = props[ii].z * SOL / (obs->T * obs->T * errs.f);
      accelerr = props[ii].zerr * SOL / (obs->T * obs->T * errs.f);
      write_val_with_err(obs->workfile, accel, accelerr, *error++, *width++);
      fprintf(obs->workfile, "  %.20s\n", notes + ii * 20);
      fflush(obs->workfile);
      listptr = listptr->next;
   }
   fprintf(obs->workfile, "\n\n");
   free(notes);
}
Example #3
0
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];
   long totnumtowrite, totwrote = 0, padwrote = 0, datawrote = 0;
   int *idispdt, **offsets;
   int ii, jj, numadded = 0, numremoved = 0, padding = 0, good_inputs = 1;
   int numbarypts = 0, numread = 0, numtowrite = 0;
   int 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);
#ifdef _OPENMP
   omp_set_num_threads(1); // Explicitly turn off OpenMP
#endif
   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 = LONG_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 = (long) 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_LONG(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_LONG((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 DE405) */
      strcpy(ephem, "DE405");

      /* 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_LONG(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_LONG((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_LONG(btoa[numbarypts - 1])) + 1;
         diffbins = gen_ivect(numdiffbins);
         diffbinptr = diffbins;
         for (ii = 1; ii < numbarypts; ii++) {
            currentbin = NEAREST_LONG(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_LONG(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:  %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));
      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);
}
Example #4
0
int comp_rawbin_to_cand(rawbincand * cand, infodata * idata, char *output, int full)
/* Compares a binary PSR candidate defined by its props found in    */
/*   *cand, and *idata with all of the pulsars in the pulsar        */
/*   database.  It returns a string (verbose if full==1) describing */
/*   the results of the search in *output.                          */
{
   int ii, jj, kk;
   static int np;
   double theop, ra, dec, beam2, difft = 0.0, epoch;
   double bmod, pmod, orbperr, psrperr;
   char tmp1[80], tmp2[80], tmp3[80];

   /* Read the database if needed */

   if (!have_database)
      np = read_database();

   /* Convert the beam width to radians */

   beam2 = 2.0 * ARCSEC2RAD * idata->fov;

   /* Convert RA and DEC to radians  (Use J2000) */

   ra = hms2rad(idata->ra_h, idata->ra_m, idata->ra_s);
   dec = dms2rad(idata->dec_d, idata->dec_m, idata->dec_s);

   /* Calculate the time related variables  */

   epoch = (double) idata->mjd_i + idata->mjd_f;

   /* Calculate the approximate error in our value of orbital period */

   orbperr = 0.5 * cand->full_T / cand->mini_N;

   /* Calculate the approximate error in our value of spin period */

   if (cand->full_lo_r == 0.0)
      psrperr = cand->psr_p;
   else
      psrperr = fabs(cand->full_T /
                     (cand->full_lo_r + 0.5 * cand->mini_N) -
                     cand->full_T / cand->full_lo_r);

   /* Run through RAs in database looking for things close  */
   /* If find one, check the DEC as well (the angle between */
   /* the sources < 2*beam diam).  If find one, check its   */
   /* period.  If this matches within 2*perr, return the    */
   /* number of the pulsar.  If no matches, return 0.       */

   for (ii = 0; ii < np; ii++) {

      /* See if we're close in RA */

      if (fabs(pulsardata[ii].ra2000 - ra) < 5.0 * beam2) {

         /* See if we're close in RA and DEC */

         if (sphere_ang_diff(pulsardata[ii].ra2000, pulsardata[ii].dec2000,
                             ra, dec) < 5.0 * beam2) {

            /* Check that the psr in the database is in a binary   */

            if (pulsardata[ii].orb.p != 0.0) {

               /* Predict the period of the pulsar at the observation MJD */

               difft = SECPERDAY * (epoch - pulsardata[ii].timepoch);
               theop = pulsardata[ii].p + pulsardata[ii].pd * difft;

               /* Check the predicted period and its harmonics against the */
               /* measured period.  Use both pulsar and binary periods.    */

               for (jj = 1; jj < 41; jj++) {
                  pmod = 1.0 / (double) jj;
                  if (fabs(theop * pmod - cand->psr_p) < psrperr) {
                     for (kk = 1; kk < 10; kk++) {
                        bmod = (double) kk;
                        if (fabs
                            (pulsardata[ii].orb.p * bmod - cand->orb_p / SECPERDAY) <
                            orbperr) {
                           if (strlen(pulsardata[ii].bname) == 0) {
                              if (jj > 1) {
                                 if (full) {
                                    sprintf(tmp1,
                                            "Possibly the %s phasemod harmonic ",
                                            num[kk]);
                                    sprintf(tmp2, "of the %s harmonic of PSR ",
                                            num[jj]);
                                    sprintf(tmp3,
                                            "J%s (p = %11.7f s, pbin = %9.4f d).\n",
                                            pulsardata[ii].jname, theop,
                                            pulsardata[ii].orb.p);
                                    sprintf(output, "%s%s%s", tmp1, tmp2, tmp3);
                                 } else {
                                    sprintf(output, "%s H J%.12s", num[kk],
                                            pulsardata[ii].jname);
                                 }
                              } else {
                                 if (full) {
                                    sprintf(tmp1,
                                            "Possibly the %s phasemod harmonic ",
                                            num[kk]);
                                    sprintf(tmp2,
                                            "of PSR J%s (p = %11.7f s, pbin = %9.4f d).\n",
                                            pulsardata[ii].jname, theop,
                                            pulsardata[ii].orb.p);
                                    sprintf(output, "%s%s", tmp1, tmp2);
                                 } else {
                                    sprintf(output, "PSR J%.12s",
                                            pulsardata[ii].jname);
                                 }
                              }
                           } else {
                              if (jj > 1) {
                                 if (full) {
                                    sprintf(tmp1,
                                            "Possibly the %s modulation harmonic ",
                                            num[kk]);
                                    sprintf(tmp2, "of the %s harmonic of PSR ",
                                            num[jj]);
                                    sprintf(tmp3,
                                            "B%s (p = %11.7f s, pbin = %9.4f d).\n",
                                            pulsardata[ii].bname, theop,
                                            pulsardata[ii].orb.p);
                                    sprintf(output, "%s%s%s", tmp1, tmp2, tmp3);
                                 } else {
                                    sprintf(output, "%s H B%s", num[kk],
                                            pulsardata[ii].bname);
                                 }
                              } else {
                                 if (full) {
                                    sprintf(tmp1,
                                            "Possibly the %s phasemod harmonic ",
                                            num[kk]);
                                    sprintf(tmp2,
                                            "of PSR B%s (p = %11.7f s, pbin = %9.4f d).\n",
                                            pulsardata[ii].bname, theop,
                                            pulsardata[ii].orb.p);
                                    sprintf(output, "%s%s", tmp1, tmp2);
                                 } else {
                                    sprintf(output, "PSR B%s", pulsardata[ii].bname);
                                 }
                              }
                           }
                        }
                        return ii + 1;
                     }
                  }
               }
            }
         }
      }
   }

   /* Didn't find a match */

   if (full) {
      sprintf(output, "I don't recognize this candidate in the pulsar database.\n");
   } else {
      sprintf(output, "                  ");
   }
   return 0;
}
Example #5
0
int comp_psr_to_cand(fourierprops * cand, infodata * idata, char *output, int full)
/* Compares a pulsar candidate defined by its properties found in   */
/*   *cand, and *idata with all of the pulsars in the pulsar        */
/*   database.  It returns a string (verbose if full==1) describing */
/*   the results of the search in *output.                          */
{
   int ii, jj;
   static infodata *old_idata;
   double theor, theoz, sidedr = 20.0;
   double r_criteria, z_criteria, rdiff, zdiff, difft = 0;
   static double T, beam2, ra, dec, epoch;
   char tmp1[80], tmp2[80], tmp3[80], shortout[30], psrname[20];
   rzwerrs rzws;

   /* Read the database if needed */

   if (!have_database)
      np = read_database();

   /* If calling for the first time for a certain data set, */
   /* initialize some values.                               */

   if (idata != old_idata) {
      /* Convert the beam width to radians */

      beam2 = 2.0 * ARCSEC2RAD * idata->fov;

      /* Convert RA and DEC to radians  (Use J2000) */

      ra = hms2rad(idata->ra_h, idata->ra_m, idata->ra_s);
      dec = dms2rad(idata->dec_d, idata->dec_m, idata->dec_s);
      T = idata->N * idata->dt;
      epoch = (double) idata->mjd_i + idata->mjd_f + T / (2.0 * SECPERDAY);

      /* Set up old_idata for next time */

      old_idata = idata;
   }
   /* Calculate the measured r, z, w's and their derivatives */

   calc_rzwerrs(cand, T, &rzws);

   /* Run through RAs in database looking for things close  */
   /* If find one, check the DEC as well (the angle between */
   /* the sources < 2*beam diam).  If find one, check its   */
   /* period.  If this matches within 2*perr, return the    */
   /* number of the pulsar.  If no matches, return 0.       */

   for (ii = 0; ii < np; ii++) {

      /* See if we're close in RA */

      if (fabs(pulsardata[ii].ra2000 - ra) < 5 * beam2) {

         /* See if we're close in RA and DEC */

         if (sphere_ang_diff(pulsardata[ii].ra2000, pulsardata[ii].dec2000,
                             ra, dec) < 5 * beam2) {

            /* Predict the period of the pulsar at the observation MJD */

            difft = SECPERDAY * (epoch - pulsardata[ii].timepoch);
            theor = T / (pulsardata[ii].p + pulsardata[ii].pd * difft);
            theoz = -pulsardata[ii].pd * theor * theor;

            /* Check the predicted period and its harmonics against the */
            /* measured period.                                         */

            for (jj = 1; jj < 41; jj++) {

               /* If the psr from the database is in a             */
               /* binary orbit, loosen the match criteria.         */
               /* This accounts for Doppler variations in period.  */

               if (pulsardata[ii].orb.p != 0.0) {
                  r_criteria = 0.001 * theor * jj;      /* 0.1% fractional error   */
                  z_criteria = 9999999999.0;    /* Always match for binary */
                  strcpy(tmp1, "?");
                  if (full) {
                     strcpy(tmp3, "Possibly (large error) ");
                  }
               } else {
                  r_criteria = 5.0;     /* 5 bin error matching... */
                  z_criteria = 9999999999.0;    /* Always match for binary */
                  /* z_criteria = 2.5 * cand->zerr; */
                  strcpy(tmp1, "");
                  if (full) {
                     strcpy(tmp3, "Looks like ");
                  }
               }

               if (theor * jj > 1.5 * cand->r)
                  break;

               rdiff = fabs(theor * jj - cand->r);
               zdiff = fabs(theoz * jj - cand->z);

               if (rdiff < r_criteria && zdiff < z_criteria) {
                  if (strlen(pulsardata[ii].bname) == 0)
                     sprintf(psrname, "J%s", pulsardata[ii].jname);
                  else
                     sprintf(psrname, "B%s", pulsardata[ii].bname);
                  if (jj == 1) {
                     if (full) {
                        sprintf(tmp1, "the fundamental of ");
                        sprintf(tmp2, "PSR %s. (predicted p = %11.7f s).\n",
                                psrname, T / theor);
                        sprintf(output, "%s%s\n     %s", tmp3, tmp1, tmp2);
                     } else {
                        sprintf(shortout, "PSR %s%s", psrname, tmp1);
                        strncpy(output, shortout, 20);
                     }
                  } else {
                     if (full) {
                        sprintf(tmp1, "the %s harmonic of ", num[jj]);
                        sprintf(tmp2, "PSR %s. (predicted p = %11.7f s).\n",
                                psrname, T / theor);
                        sprintf(output, "%s%s\n     %s", tmp3, tmp1, tmp2);
                     } else {
                        sprintf(shortout, "%s H %s%s", num[jj], psrname, tmp1);
                        strncpy(output, shortout, 20);
                     }
                  }
                  return ii + 1;
               } else if (rdiff < sidedr) {
                  if (strlen(pulsardata[ii].bname) == 0)
                     sprintf(psrname, "J%s", pulsardata[ii].jname);
                  else
                     sprintf(psrname, "B%s", pulsardata[ii].bname);
                  if (full) {
                     sprintf(tmp1, "a sidelobe of the %s harmonic of ", num[jj]);
                     sprintf(tmp2, "PSR %s. (predicted p = %11.7f s).\n",
                             psrname, T / theor);
                     sprintf(output, "%s%s\n     %s", tmp3, tmp1, tmp2);
                  } else {
                     sprintf(shortout, "SL H%d %s", jj, psrname);
                     strncpy(output, shortout, 20);
                  }
                  return ii + 1;
               }
            }
         }
      }
   }

   /* Didn't find a match */

   if (full) {
      sprintf(output, "I don't recognize this candidate in the pulsar database.\n");
   } else {
      strncpy(output, "                       ", 20);
   }
   return 0;
}
Example #6
0
int get_psr_from_parfile(char *parfilenm, double epoch, psrparams * psr)
/* Converts info from a "par" file to the "current" epoch.  */
/* Returned values go in *psr.  The name of the parfile is  */
/* in *parfilenm. epoch is the time in question in MJD.     */
/* The int returned is 1 if successful, 0 otherwise.        */
{
   FILE *parfile;
   int binary = 0;
   double orbdifft = 0.0, difft = 0.0, f = 0.0, fd = 0.0;
   double eps1 = 0.0, eps2 = 0.0, eps1d = 0.0, eps2d = 0.0, ed = 0.0, xd = 0.0;
   char line[80], *keyword, *value;

   psr->f = psr->fd = psr->fdd = psr->p = psr->pd = psr->pdd = psr->dm = 0.0;
   psr->orb.p = psr->orb.pd = psr->orb.x = psr->orb.e = 0.0;
   psr->orb.w = psr->orb.wd = psr->orb.t = 0.0;

   parfile = chkfopen(parfilenm, "r");
   while (fgets(line, 80, parfile)) {
      keyword = strtok(line, " \t\n");
      if (keyword != NULL) {
         if (strncmp("PSR", keyword, 80) == 0 || strncmp("PSRJ", keyword, 80) == 0) {
            strncpy(psr->jname, strtok(NULL, " \t\n"), 20);
            if (psr->jname[0] == 'J' || psr->jname[0] == 'B') {
               int ii = 0;
               do {
                  ii++;
                  psr->jname[ii - 1] = psr->jname[ii];
               } while (psr->jname[ii] != '\0');
            }
            if (DEBUGOUT)
               printf("The pulsar is '%s'\n", psr->jname);
         } else if (strncmp("RAJ", keyword, 80) == 0 ||
                    strncmp("RA", keyword, 80) == 0) {
            int h, m;
            double s;
            ra_dec_from_string(strtok(NULL, " \t\n"), &h, &m, &s);
            psr->ra2000 = hms2rad(h, m, s);
            if (DEBUGOUT)
               printf("The RA  is %d %d %f (%f)\n", h, m, s, psr->ra2000);
         } else if (strncmp("DECJ", keyword, 80) == 0 ||
                    strncmp("DEC", keyword, 80) == 0) {
            int d, m;
            double s;
            ra_dec_from_string(strtok(NULL, " \t\n"), &d, &m, &s);
            psr->dec2000 = dms2rad(d, m, s);
            if (DEBUGOUT)
               printf("The DEC is %d %d %f (%f)\n", d, m, s, psr->dec2000);
         } else if (strncmp("F0", keyword, 80) == 0 ||
                    strncmp("F", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            f = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("The freq is %.15g\n", f);
         } else if (strncmp("P0", keyword, 80) == 0 ||
                    strncmp("P", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            f = 1.0 / strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("The period is %.15g\n", 1.0 / f);
         } else if (strncmp("F1", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            fd = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("The f-dot is %.15g\n", fd);
         } else if (strncmp("P1", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            fd = -strtod(fortran_double_convert(value), &value) * f * f;
            if (DEBUGOUT)
               printf("The p-dot is %.15g\n", -fd / (f * f));
         } else if (strncmp("F2", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->fdd = strtod(fortran_double_convert(value), &value);
            psr->pdd = (2.0 * (fd * fd) / f - psr->fdd) / (f * f);
            if (DEBUGOUT)
               printf("The f-dotdot is %.15g\n", psr->fdd);
         } else if (strncmp("PEPOCH", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->timepoch = strtod(fortran_double_convert(value), &value);
            difft = (epoch - psr->timepoch) * SECPERDAY;
            if (DEBUGOUT)
               printf("The PEPOCH is %.15g\n", psr->timepoch);
         } else if (strncmp("DM", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->dm = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("The DM is %.15g\n", psr->dm);
         } else if (strncmp("BINARY", keyword, 80) == 0) {
            binary = 1;
            value = strtok(NULL, " \t\n");
            if (DEBUGOUT)
               printf("This is a binary PSR ('%s')...\n", value);
         } else if (strncmp("PB", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->orb.p = strtod(fortran_double_convert(value), &value) * SECPERDAY;
            if (DEBUGOUT)
               printf("  P_orb  = %.15g\n", psr->orb.p);
         } else if (strncmp("PBDOT", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->orb.pd = strtod(fortran_double_convert(value), &value) * 1.0E-12;
            if (DEBUGOUT)
               printf("  P_orb-dot  = %.15g\n", psr->orb.pd);
         } else if (strncmp("OM", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->orb.w = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("  w_orb  = %.15g\n", psr->orb.w);
         } else if (strncmp("OMDOT", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->orb.wd =
                strtod(fortran_double_convert(value), &value) / SECPERJULYR;
            if (DEBUGOUT)
               printf("  w_orb-dot  = %.15g\n", psr->orb.wd);
         } else if (strncmp("A1", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->orb.x = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("  x_orb  = %.15g\n", psr->orb.x);
         } else if (strncmp("XDOT", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            xd = strtod(fortran_double_convert(value), &value) * 1.0E-12;
            if (DEBUGOUT)
               printf("  x_orb-dot  = %.15g\n", xd);
         } else if (strncmp("E", keyword, 80) == 0 ||
                    strncmp("ECC", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->orb.e = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("  e_orb  = %.15g\n", psr->orb.e);
         } else if (strncmp("EDOT", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            ed = strtod(fortran_double_convert(value), &value) * 1.0E-12;
            if (DEBUGOUT)
               printf("  e_orb-dot  = %.15g\n", ed);
         } else if (strncmp("T0", keyword, 80) == 0 ||
                    strncmp("TASC", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            psr->orb.t = strtod(fortran_double_convert(value), &value);
            /* TEMPO bases the orbital params on T0, not PEPOCH */
            orbdifft = (epoch - psr->orb.t) * SECPERDAY;
            if (DEBUGOUT)
               printf("  T_orb  = %.15g\n", psr->orb.t);
         } else if (strncmp("EPS1", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            eps1 = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("  EPS1  = %.15g\n", eps1);
         } else if (strncmp("EPS2", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            eps2 = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("  EPS2  = %.15g\n", eps2);
         } else if (strncmp("EPS1DOT", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            eps1d = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("  EPS1DOT  = %.15g\n", eps1d);
         } else if (strncmp("EPS2DOT", keyword, 80) == 0) {
            value = strtok(NULL, " \t\n");
            eps2d = strtod(fortran_double_convert(value), &value);
            if (DEBUGOUT)
               printf("  EPS2DOT  = %.15g\n", eps2d);
         } else if (strncmp("OM2DOT", keyword, 80) == 0 ||
                    strncmp("X2DOT", keyword, 80) == 0 ||
                    strncmp("F3", keyword, 80) == 0 ||
                    strncmp("F4", keyword, 80) == 0 ||
                    strncmp("F5", keyword, 80) == 0) {
            printf("  readpar:  Warning!  '%s' is currently unused!\n", keyword);
         }
      }
   }
   /* Update the spin parameters */
   psr->f = f + fd * difft + 0.5 * psr->fdd * difft * difft;
   psr->fd = fd + psr->fdd * difft;
   psr->p = 1.0 / psr->f;
   psr->pd = -psr->fd * psr->p * psr->p;
   psr->pdd = (2.0 * (fd * fd) / f - psr->fdd) / (f * f);
   if (binary) {
      psr->orb.p += psr->orb.pd * orbdifft;
      psr->orb.w += psr->orb.wd * orbdifft;
      psr->orb.x += xd * orbdifft;
      psr->orb.e += ed * orbdifft;
      eps1 += eps1d * orbdifft;
      eps2 += eps1d * orbdifft;
      if (eps1 != 0.0 || eps2 != 0.0) {
         /* Convert Laplace-Lagrange params to e and w */
         /* Warning!  This is presently untested!      */
         psr->orb.e = sqrt(eps1 * eps1 + eps2 * eps2);
         psr->orb.w = atan2(eps1, eps2);
         psr->orb.t += psr->orb.p / SECPERDAY * (psr->orb.w / TWOPI);
         psr->orb.w *= RADTODEG;
      }
      /* psr->orb.t is in seconds, _not_ MJD.  It represents the */
      /* time in sec _since_ the last periastron passage, _not_  */
      /* when the next periastron will occur....                 */
      psr->orb.t = fmod((epoch - psr->orb.t) * SECPERDAY, psr->orb.p);
      if (psr->orb.t < 0.0)
         psr->orb.t += psr->orb.p;
      psr->orb.w = fmod(psr->orb.w, 360.0);
   }
   fclose(parfile);
   return 1;
}