コード例 #1
0
ファイル: psrfits.c プロジェクト: nextgen-astrodata/presto
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;
}
コード例 #2
0
ファイル: readpar.c プロジェクト: aarchiba/presto
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;
}