Example #1
0
void guppi_psrfits_thread(void *_args) {
    
    /* Get args */
    struct guppi_thread_args *args = (struct guppi_thread_args *)_args;
    pthread_cleanup_push((void *)guppi_thread_set_finished, args);
    
    /* Set cpu affinity */
    cpu_set_t cpuset, cpuset_orig;
    sched_getaffinity(0, sizeof(cpu_set_t), &cpuset_orig);
    CPU_ZERO(&cpuset);
    CPU_SET(1, &cpuset);
    int rv = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
    if (rv<0) { 
        guppi_error("guppi_psrfits_thread", "Error setting cpu affinity.");
        perror("sched_setaffinity");
    }

    /* Set priority */
    rv = setpriority(PRIO_PROCESS, 0, args->priority);
    if (rv<0) {
        guppi_error("guppi_psrfits_thread", "Error setting priority level.");
        perror("set_priority");
    }
    
    /* Attach to status shared mem area */
    struct guppi_status st;
    rv = guppi_status_attach(&st);
    if (rv!=GUPPI_OK) {
        guppi_error("guppi_psrfits_thread", 
                    "Error attaching to status shared memory.");
        pthread_exit(NULL);
    }
    pthread_cleanup_push((void *)guppi_status_detach, &st);
    pthread_cleanup_push((void *)set_exit_status, &st);
    
    /* Init status */
    guppi_status_lock_safe(&st);
    hputs(st.buf, STATUS_KEY, "init");
    guppi_status_unlock_safe(&st);
    
    /* Initialize some key parameters */
    struct guppi_params gp;
    struct psrfits pf;
    pf.sub.data = NULL;
    pf.sub.dat_freqs = pf.sub.dat_weights = NULL;
    pf.sub.dat_offsets = pf.sub.dat_scales = NULL;
    pf.hdr.chan_dm = 0.0;
    pf.filenum = 0; // This is crucial
    pthread_cleanup_push((void *)guppi_free_psrfits, &pf);
    pthread_cleanup_push((void *)psrfits_close, &pf);
    //pf.multifile = 0;  // Use a single file for fold mode
    pf.multifile = 1;  // Use a multiple files for fold mode
    pf.quiet = 0;      // Print a message per each subint written
    
    /* Attach to databuf shared mem */
    struct guppi_databuf *db;
    db = guppi_databuf_attach(args->input_buffer);
    if (db==NULL) {
        guppi_error("guppi_psrfits_thread",
                    "Error attaching to databuf shared memory.");
        pthread_exit(NULL);
    }
    pthread_cleanup_push((void *)guppi_databuf_detach, db);
    
    /* Loop */
    int curblock=0, total_status=0, firsttime=1, run=1, got_packet_0=0;
    int mode=SEARCH_MODE;
    char *ptr;
    char tmpstr[256];
    struct foldbuf fb;
    struct polyco pc[64];  
    memset(pc, 0, sizeof(pc));
    int n_polyco_written=0;
    float *fold_output_array = NULL;
    int scan_finished=0;
    signal(SIGINT, cc);
    do {
        /* Note waiting status */
        guppi_status_lock_safe(&st);
        if (got_packet_0)
            sprintf(tmpstr, "waiting(%d)", curblock);
        else
            sprintf(tmpstr, "ready");
        hputs(st.buf, STATUS_KEY, tmpstr);
        guppi_status_unlock_safe(&st);
        
        /* Wait for buf to have data */
        rv = guppi_databuf_wait_filled(db, curblock);
        if (rv!=0) {
            // This is a big ol' kludge to avoid this process hanging
            // due to thread synchronization problems.
            sleep(1);
            continue; 
        }

        /* Note current block */
        guppi_status_lock_safe(&st);
        hputi4(st.buf, "CURBLOCK", curblock);
        guppi_status_unlock_safe(&st);

        /* See how full databuf is */
        total_status = guppi_databuf_total_status(db);
        
        /* Read param structs for this block */
        ptr = guppi_databuf_header(db, curblock);
        if (firsttime) {
            guppi_read_obs_params(ptr, &gp, &pf);
            firsttime = 0;
        } else {
            guppi_read_subint_params(ptr, &gp, &pf);
        }

        /* Find out what mode this data is in */
        mode = psrfits_obs_mode(pf.hdr.obs_mode);

        /* Check if we got both packet 0 and a valid observation
         * start time.  If so, flag writing to start.
         */
        if (got_packet_0==0 && gp.packetindex==0 && gp.stt_valid==1) {
            got_packet_0 = 1;
            guppi_read_obs_params(ptr, &gp, &pf);
            guppi_update_ds_params(&pf);
            memset(pc, 0, sizeof(pc));
            n_polyco_written=0;
        }

        /* If actual observation has started, write the data */
        if (got_packet_0) { 

            /* Note waiting status */
            guppi_status_lock_safe(&st);
            hputs(st.buf, STATUS_KEY, "writing");
            guppi_status_unlock_safe(&st);
            
            /* Get the pointer to the current data */
            if (mode==FOLD_MODE) {
                fb.nchan = pf.hdr.nchan;
                fb.npol = pf.hdr.npol;
                fb.nbin = pf.hdr.nbin;
                fb.data = (float *)guppi_databuf_data(db, curblock);
                fb.count = (unsigned *)(guppi_databuf_data(db, curblock)
                        + foldbuf_data_size(&fb));
                fold_output_array = (float *)realloc(fold_output_array,
                        sizeof(float) * pf.hdr.nbin * pf.hdr.nchan * 
                        pf.hdr.npol);
                pf.sub.data = (unsigned char *)fold_output_array;
                pf.fold.pc = (struct polyco *)(guppi_databuf_data(db,curblock)
                        + foldbuf_data_size(&fb) + foldbuf_count_size(&fb));
            } else 
                pf.sub.data = (unsigned char *)guppi_databuf_data(db, curblock);
            
            /* Set the DC and Nyquist channels explicitly to zero */
            /* because of the "FFT Problem" that splits DC power  */
            /* into those two bins.                               */
            zero_end_chans(&pf);

            /* Output only Stokes I (in place) */
            if (pf.hdr.onlyI && pf.hdr.npol==4)
                get_stokes_I(&pf);

            /* Downsample in frequency (in place) */
            if (pf.hdr.ds_freq_fact > 1)
                downsample_freq(&pf);

            /* Downsample in time (in place) */
            if (pf.hdr.ds_time_fact > 1)
                downsample_time(&pf);

            /* Folded data needs a transpose */
            if (mode==FOLD_MODE)
                normalize_transpose_folds(fold_output_array, &fb);

            /* Write the data */
            int last_filenum = pf.filenum;
            psrfits_write_subint(&pf);

            /* Any actions that need to be taken when a new file
             * is created.
             */
            if (pf.filenum!=last_filenum) {
                /* No polycos yet written to the new file */
                n_polyco_written=0;
            }

            /* Write the polycos if needed */
            int write_pc=0, i, j;
            for (i=0; i<pf.fold.n_polyco_sets; i++) {
                if (pf.fold.pc[i].used==0) continue; 
                int new_pc=1;
                for (j=0; j<n_polyco_written; j++) {
                    if (polycos_differ(&pf.fold.pc[i], &pc[j])==0) {
                        new_pc=0;
                        break;
                    }
                }
                if (new_pc || n_polyco_written==0) {
                    pc[n_polyco_written] = pf.fold.pc[i];
                    n_polyco_written++;
                    write_pc=1;
                } else {
                    pf.fold.pc[i].used = 0; // Already have this one
                }
            }
            if (write_pc) 
                psrfits_write_polycos(&pf, pf.fold.pc, pf.fold.n_polyco_sets);

            /* Is the scan complete? */
            if ((pf.hdr.scanlen > 0.0) && 
                (pf.T > pf.hdr.scanlen)) scan_finished = 1;
            
            /* For debugging... */
            if (gp.drop_frac > 0.0) {
               printf("Block %d dropped %.3g%% of the packets\n", 
                      pf.tot_rows, gp.drop_frac*100.0);
            }

        }

        /* Mark as free */
        guppi_databuf_set_free(db, curblock);
        
        /* Go to next block */
        curblock = (curblock + 1) % db->n_block;
        
        /* Check for cancel */
        pthread_testcancel();
        
    } while (run && !scan_finished);
    
    /* Cleanup */
    
    if (fold_output_array!=NULL) free(fold_output_array);

    pthread_exit(NULL);
    
    pthread_cleanup_pop(0); /* Closes psrfits_close */
    pthread_cleanup_pop(0); /* Closes guppi_free_psrfits */
    pthread_cleanup_pop(0); /* Closes set_exit_status */
    pthread_cleanup_pop(0); /* Closes set_finished */
    pthread_cleanup_pop(0); /* Closes guppi_status_detach */
    pthread_cleanup_pop(0); /* Closes guppi_databuf_detach */
}
int psrfits_create(struct psrfits *pf) {
    int itmp, *status;
    long long lltmp;
    long double ldtmp;
    double dtmp;
    char ctmp[40];
    struct hdrinfo *hdr;
    struct foldinfo *fld;

    hdr = &(pf->hdr);        // dereference the ptr to the header struct
    status = &(pf->status);  // dereference the ptr to the CFITSIO status
    fld = &(pf->fold);       // ptr to foldinfo struct

    // Figure out what mode this is 
    int mode=0;
    mode = psrfits_obs_mode(hdr->obs_mode);
    if (mode==fold) {
        if (hdr->onlyI)
            printf("Warning!  In folding mode and ONLY_I is set!\n");
        if (hdr->ds_time_fact > 1)
            printf("Warning!  In folding mode and DS_TIME is > 1!\n");
        if (hdr->ds_freq_fact > 1)
            printf("Warning!  In folding mode and DS_FREQ is > 1!\n");
    }

    // Initialize the key variables if needed
    if (pf->filenum == 0) {  // first time writing to the file
        pf->status = 0;
        pf->tot_rows = 0;
        pf->N = 0L;
        pf->T = 0.0;
        hdr->offset_subint = 0;
        pf->mode = 'w';

        // Create the output directory if needed
        char datadir[1024];
        strncpy(datadir, pf->basefilename, 1023);
        char *last_slash = strrchr(datadir, '/');
        if (last_slash!=NULL && last_slash!=datadir) {
            *last_slash = '\0';
            printf("Using directory '%s' for output.\n", datadir);
            char cmd[1024];
            sprintf(cmd, "mkdir -m 1777 -p %s", datadir);
            system(cmd);
        }
    }
    pf->filenum++;
    pf->rownum = 1;
    hdr->offset_subint = pf->tot_rows;

    // Update the filename - don't include filenum for fold mode
    // TODO : use rf/cf extensions for psr/cals?
    if (mode==fold && pf->multifile!=1)
        sprintf(pf->filename, "%s.fits", pf->basefilename);
    else
        sprintf(pf->filename, "%s_%04d.fits", pf->basefilename, pf->filenum);

    // Create basic FITS file from our template
    // Fold mode template has additional tables (polyco, ephem)
    char template_dir[1024];
    char template_file[1024];
#ifdef PSRFITS_TEMPLATE_DIR
    sprintf(template_dir, "%s", PSRFITS_TEMPLATE_DIR);
#else
    char *guppi_dir = getenv("GUPPI_DIR");
    if (guppi_dir==NULL) {
        fprintf(stderr, 
                "Error: GUPPI_DIR environment variable not set, exiting.\n");
        exit(1);
    }
    sprintf(template_dir, "%s/src", guppi_dir);
#endif
    printf("Opening file '%s' ", pf->filename);
    if (mode==search) { 
        printf("in search mode.\n");
        sprintf(template_file, "%s/%s", template_dir, PSRFITS_SEARCH_TEMPLATE);
    } else if (mode==fold) { 
        printf("in fold mode.\n");
        sprintf(template_file, "%s/%s", template_dir, PSRFITS_FOLD_TEMPLATE);
    }
    fits_create_template(&(pf->fptr), pf->filename, template_file, status);

    // Check to see if file was successfully created
    if (*status) {
        fprintf(stderr, "Error creating psrfits file from template.\n");
        fits_report_error(stderr, *status);
        exit(1);
    }

    // Go to the primary HDU
    fits_movabs_hdu(pf->fptr, 1, NULL, status);

    // Update the keywords that need it
    fits_get_system_time(ctmp, &itmp, status);
    // Note:  this is the date the file was _written_, not the obs start date
    fits_update_key(pf->fptr, TSTRING, "DATE", ctmp, NULL, status);
    fits_update_key(pf->fptr, TSTRING, "TELESCOP", hdr->telescope,NULL, status);
    fits_update_key(pf->fptr, TSTRING, "OBSERVER", hdr->observer, NULL, status);
    fits_update_key(pf->fptr, TSTRING, "PROJID", hdr->project_id, NULL, status);
    fits_update_key(pf->fptr, TSTRING, "FRONTEND", hdr->frontend, NULL, status);
    fits_update_key(pf->fptr, TSTRING, "BACKEND", hdr->backend, NULL, status);
    if (hdr->onlyI || hdr->summed_polns) {
        if (!hdr->onlyI && hdr->npol > 1) {
            printf("Warning!:  Can't have %d polarizations _and_ be summed!\n", 
                   hdr->npol);
        }
        itmp = 2;
        fits_update_key(pf->fptr, TINT, "NRCVR", &itmp, NULL, status);
    } else {
        if (hdr->npol > 2) { // Can't have more than 2 real polns (i.e. NRCVR)
            itmp = 2;
            fits_update_key(pf->fptr, TINT, "NRCVR", &itmp, NULL, status);
        } else {
            fits_update_key(pf->fptr, TINT, "NRCVR", &(hdr->npol), NULL, status);
        }
    }
    fits_update_key(pf->fptr, TSTRING, "FD_POLN", hdr->poln_type, NULL, status);
    fits_update_key(pf->fptr, TINT, "FD_HAND", &(hdr->fd_hand), NULL, status);
    fits_update_key(pf->fptr, TDOUBLE, "FD_SANG", &(hdr->fd_sang), NULL, status);
    fits_update_key(pf->fptr, TDOUBLE, "FD_XYPH", &(hdr->fd_xyph), NULL, status);
    fits_update_key(pf->fptr, TINT, "BE_PHASE", &(hdr->be_phase), NULL, status);
    fits_update_key(pf->fptr, TSTRING, "DATE-OBS", hdr->date_obs, NULL, status);
    if (mode==fold && !strcmp("CAL",hdr->obs_mode)) 
        fits_update_key(pf->fptr, TSTRING, "OBS_MODE", hdr->obs_mode, 
                NULL, status);
    fits_update_key(pf->fptr, TDOUBLE, "OBSFREQ", &(hdr->fctr), NULL, status);
    fits_update_key(pf->fptr, TDOUBLE, "OBSBW", &(hdr->BW), NULL, status);
    fits_update_key(pf->fptr, TINT, "OBSNCHAN", &(hdr->orig_nchan), NULL, status);
    fits_update_key(pf->fptr, TDOUBLE, "CHAN_DM", &(hdr->chan_dm), NULL, status);
    fits_update_key(pf->fptr, TSTRING, "SRC_NAME", hdr->source, NULL, status);
    if (!strcmp("UNKNOWN", hdr->track_mode)) {
        printf("Warning!:  Unknown telescope tracking mode!\n");
    }
    fits_update_key(pf->fptr, TSTRING, "TRK_MODE", hdr->track_mode, NULL, status);
    // TODO: will need to change the following if we aren't tracking!
    fits_update_key(pf->fptr, TSTRING, "RA", hdr->ra_str, NULL, status);
    fits_update_key(pf->fptr, TSTRING, "DEC", hdr->dec_str, NULL, status);
    fits_update_key(pf->fptr, TSTRING, "STT_CRD1", hdr->ra_str, NULL, status);
    fits_update_key(pf->fptr, TSTRING, "STP_CRD1", hdr->ra_str, NULL, status);
    // TODO: update these at the end of the file or obs
    fits_update_key(pf->fptr, TSTRING, "STT_CRD2", hdr->dec_str, NULL, status);
    fits_update_key(pf->fptr, TSTRING, "STP_CRD2", hdr->dec_str, NULL, status);
    fits_update_key(pf->fptr, TDOUBLE, "BMAJ", &(hdr->beam_FWHM), NULL, status);
    fits_update_key(pf->fptr, TDOUBLE, "BMIN", &(hdr->beam_FWHM), NULL, status);
    if (strcmp("OFF", hdr->cal_mode)) {
        fits_update_key(pf->fptr, TDOUBLE, "CAL_FREQ", &(hdr->cal_freq), NULL, status);
        fits_update_key(pf->fptr, TDOUBLE, "CAL_DCYC", &(hdr->cal_dcyc), NULL, status);
        fits_update_key(pf->fptr, TDOUBLE, "CAL_PHS", &(hdr->cal_phs), NULL, status);
    }
    fits_update_key(pf->fptr, TDOUBLE, "SCANLEN", &(hdr->scanlen), NULL, status);
    itmp = (int) hdr->MJD_epoch;
    fits_update_key(pf->fptr, TINT, "STT_IMJD", &itmp, NULL, status);
    ldtmp = (hdr->MJD_epoch - (long double) itmp) * 86400.0L;   // in sec
    itmp = (int) ldtmp;
    fits_update_key(pf->fptr, TINT, "STT_SMJD", &itmp, NULL, status);
    ldtmp -= (long double) itmp;
    dtmp = (double) ldtmp;
    fits_update_key(pf->fptr, TDOUBLE, "STT_OFFS", &dtmp, NULL, status);
    fits_update_key(pf->fptr, TDOUBLE, "STT_LST", &(hdr->start_lst), NULL, status);

    // If fold mode, copy the parfile into the PSRFITS EPHEM table
    if (mode==fold) {
        if (strcmp("CAL",hdr->obs_mode)==0) {
            // CAL mode has no par file, or no par file given
            psrfits_remove_ephem(pf);
        } else if (fld->parfile[0]=='\0') {
            // No par file given
            fprintf(stderr, 
                    "psrfits_create warning:  "
                    "Fold mode selected, but no parfile given - "
                    "EPHEM table will be removed.\n"
                    );
            psrfits_remove_ephem(pf);
        } else {
            FILE *parfile = fopen(fld->parfile, "r");
            if (parfile==NULL) {
                fprintf(stderr, 
                        "psrfits_create warning:  "
                        "Error opening parfile %s - "
                        "EPHEM table will be removed.\n", fld->parfile
                        );
                psrfits_remove_ephem(pf);
            } else {
                psrfits_write_ephem(pf, parfile);
                fclose(parfile);
            }
        }
    }

    // Go to the SUBINT HDU
    fits_movnam_hdu(pf->fptr, BINARY_TBL, "SUBINT", 0, status);

    // Update the keywords that need it
    if (hdr->onlyI) {
        itmp = 1;
        fits_update_key(pf->fptr, TINT, "NPOL", &itmp, NULL, status);
    } else {
        fits_update_key(pf->fptr, TINT, "NPOL", &(hdr->npol), NULL, status);
    }
    if (!hdr->onlyI && !hdr->summed_polns) {
        // TODO:  These need to be updated for the real machine.
        if (hdr->npol==1)
            strcpy(ctmp, "AA");
        else if (hdr->npol==2)
            strcpy(ctmp, "AABB");
        else if (hdr->npol==4) {
            if (strncmp(hdr->poln_order, "AABBCRCI", 8)==0)
                strcpy(ctmp, hdr->poln_order);
            else
                strcpy(ctmp, "IQUV");
        }
        fits_update_key(pf->fptr, TSTRING, "POL_TYPE", ctmp, NULL, status);
    } else {
        fits_update_key(pf->fptr, TSTRING, "POL_TYPE", "AA+BB", NULL, status);
    }
    // TODO what does TBIN mean in fold mode?
    dtmp = hdr->dt * hdr->ds_time_fact;
    fits_update_key(pf->fptr, TDOUBLE, "TBIN", &dtmp, NULL, status);
    fits_update_key(pf->fptr, TINT, "NSUBOFFS", &(hdr->offset_subint), NULL, status);
    itmp = hdr->nchan / hdr->ds_freq_fact;
    fits_update_key(pf->fptr, TINT, "NCHAN", &itmp, NULL, status);
    dtmp = hdr->df * hdr->ds_freq_fact;
    fits_update_key(pf->fptr, TDOUBLE, "CHAN_BW", &dtmp, NULL, status);
    if (mode==search) {
        int out_nsblk = hdr->nsblk / hdr->ds_time_fact;
        itmp = 1;
        fits_update_key(pf->fptr, TINT, "NSBLK", &out_nsblk, NULL, status);
        fits_update_key(pf->fptr, TINT, "NBITS", &(hdr->nbits), NULL, status);
        fits_update_key(pf->fptr, TINT, "NBIN", &itmp, NULL, status);
    } else if (mode==fold) {
        itmp = 1;
        fits_update_key(pf->fptr, TINT, "NSBLK", &itmp, NULL, status);
        fits_update_key(pf->fptr, TINT, "NBITS", &itmp, NULL, status);
        fits_update_key(pf->fptr, TINT, "NBIN", &(hdr->nbin), NULL, status);
        fits_update_key(pf->fptr, TSTRING, "EPOCHS", "MIDTIME", NULL, status);
    }

    // Update the column sizes for the colums containing arrays
    {
        int out_npol = hdr->npol;
        int out_nchan = hdr->nchan / hdr->ds_freq_fact;
        if (hdr->onlyI) out_npol = 1;
        int out_nsblk = hdr->nsblk / hdr->ds_time_fact;

        fits_modify_vector_len(pf->fptr, 13, out_nchan, status); // DAT_FREQ
        fits_modify_vector_len(pf->fptr, 14, out_nchan, status); // DAT_WTS
        itmp = out_nchan * out_npol;
        fits_modify_vector_len(pf->fptr, 15, itmp, status); // DAT_OFFS
        fits_modify_vector_len(pf->fptr, 16, itmp, status); // DAT_SCL
        
        if (mode==search) {
            lltmp = out_nsblk;
            lltmp = (lltmp * hdr->nbits * out_nchan * out_npol) / 8L;
        } else if (mode==fold)
            lltmp = (hdr->nbin * out_nchan * out_npol);
        fits_modify_vector_len(pf->fptr, 17, lltmp, status); // DATA
        // Update the TDIM field for the data column
        if (mode==search)
            sprintf(ctmp, "(1,%d,%d,%d)", out_nchan, out_npol, out_nsblk);
        else if (mode==fold) 
            sprintf(ctmp, "(%d,%d,%d,1)", hdr->nbin, out_nchan, out_npol);
        fits_update_key(pf->fptr, TSTRING, "TDIM17", ctmp, NULL, status);
    }

    fits_flush_file(pf->fptr, status);
    
    return *status;
}
int psrfits_write_subint(struct psrfits *pf) {
    int row, *status, nchan, nivals, mode, out_nbytes;
    float ftmp;
    struct hdrinfo *hdr;
    struct subint *sub;

    hdr = &(pf->hdr);        // dereference the ptr to the header struct
    sub = &(pf->sub);        // dereference the ptr to the subint struct
    status = &(pf->status);  // dereference the ptr to the CFITSIO status
    nchan = hdr->nchan / hdr->ds_freq_fact;
    if (hdr->onlyI)
        nivals = nchan;
    else
        nivals = nchan * hdr->npol;
    mode = psrfits_obs_mode(hdr->obs_mode);
    if (mode==fold)
        out_nbytes = sub->bytes_per_subint / hdr->ds_freq_fact;
    else {
        out_nbytes = sub->bytes_per_subint / (hdr->ds_freq_fact * hdr->ds_time_fact);
        if (hdr->onlyI)
            out_nbytes /= hdr->npol;
    }

    // Create the initial file or change to a new one if needed.
    // Stay with a single file for fold mode.
    if (pf->filenum==0 || 
            ( (mode==search || pf->multifile==1) 
              && pf->rownum > pf->rows_per_file)) {
        if (pf->filenum) {
            printf("Closing file '%s'\n", pf->filename);
            fits_close_file(pf->fptr, status);
        }
        psrfits_create(pf);
    }

    row = pf->rownum;
    fits_write_col(pf->fptr, TDOUBLE, 1, row, 1, 1, &(sub->tsubint), status);
    fits_write_col(pf->fptr, TDOUBLE, 2, row, 1, 1, &(sub->offs), status);
    fits_write_col(pf->fptr, TDOUBLE, 3, row, 1, 1, &(sub->lst), status);
    fits_write_col(pf->fptr, TDOUBLE, 4, row, 1, 1, &(sub->ra), status);
    fits_write_col(pf->fptr, TDOUBLE, 5, row, 1, 1, &(sub->dec), status);
    fits_write_col(pf->fptr, TDOUBLE, 6, row, 1, 1, &(sub->glon), status);
    fits_write_col(pf->fptr, TDOUBLE, 7, row, 1, 1, &(sub->glat), status);
    ftmp = (float) sub->feed_ang;
    fits_write_col(pf->fptr, TFLOAT, 8, row, 1, 1, &ftmp, status);
    ftmp = (float) sub->pos_ang;
    fits_write_col(pf->fptr, TFLOAT, 9, row, 1, 1, &ftmp, status);
    ftmp = (float) sub->par_ang;
    fits_write_col(pf->fptr, TFLOAT, 10, row, 1, 1, &ftmp, status);
    ftmp = (float) sub->tel_az;
    fits_write_col(pf->fptr, TFLOAT, 11, row, 1, 1, &ftmp, status);
    ftmp = (float) sub->tel_zen;
    fits_write_col(pf->fptr, TFLOAT, 12, row, 1, 1, &ftmp, status);
    fits_write_col(pf->fptr, TDOUBLE, 13, row, 1, nchan, sub->dat_freqs, status);
    fits_write_col(pf->fptr, TFLOAT, 14, row, 1, nchan, sub->dat_weights, status);
    fits_write_col(pf->fptr, TFLOAT, 15, row, 1, nivals, sub->dat_offsets, status);
    fits_write_col(pf->fptr, TFLOAT, 16, row, 1, nivals, sub->dat_scales, status);
    if (mode==search) {
        if (hdr->nbits==4) pf_8bit_to_4bit(pf);
        fits_write_col(pf->fptr, TBYTE, 17, row, 1, out_nbytes, 
                       sub->rawdata, status);
    } else if (mode==fold) { 
        // Fold mode writes floats for now..
        fits_write_col(pf->fptr, TFLOAT, 17, row, 1, out_nbytes/sizeof(float), 
                       sub->data, status);
    }

    // Flush the buffers if not finished with the file
    // Note:  this use is not entirely in keeping with the CFITSIO
    //        documentation recommendations.  However, manually 
    //        correcting NAXIS2 and using fits_flush_buffer()
    //        caused occasional hangs (and extrememly large
    //        files due to some infinite loop).
    fits_flush_file(pf->fptr, status);

    // Print status if bad
    if (*status) {
        fprintf(stderr, "Error writing subint %d:\n", pf->rownum);
        fits_report_error(stderr, *status);
        fflush(stderr);
    }

    // Now update some key values if no CFITSIO errors
    if (!(*status)) {
        pf->rownum++;
        pf->tot_rows++;
        pf->N += hdr->nsblk / hdr->ds_time_fact;
        pf->T += sub->tsubint;

        // For fold mode, print info each subint written
        if (mode==fold && pf->quiet!=1) {
            printf("Wrote subint %d (total time %.1fs)\n", pf->rownum-1, pf->T);
            fflush(stdout);
        }

    }

    return *status;
}
Example #4
0
/* This function is similar to psrfits_create, except it
 * deals with reading existing files.  It is assumed that
 * basename and filenum are filled in correctly to point to 
 * the first file in the set OR that filename already contains
 * the correct file name.
 */
int psrfits_open(struct psrfits *pf) {

    int itmp;
    double dtmp;
    char ctmp[256];

    struct hdrinfo *hdr = &(pf->hdr);
    struct subint  *sub = &(pf->sub);
    struct foldinfo *fold = &(pf->fold);
    int *status = &(pf->status);

    if (pf->numfiles==0) {
        // Dynamically generated file names
        sprintf(pf->filename, "%s_%04d.fits", pf->basefilename, pf->filenum);
    } else {
        // Using explicit filenames
        if (pf->filenum < pf->numfiles) {
            strncpy(pf->filename, pf->filenames[pf->filenum], 200);
        } else {
            *status = FILE_NOT_OPENED;
            return *status;
        }
    }

    fits_open_file(&(pf->fptr), pf->filename, READONLY, status);
    pf->mode = 'r';

    // If file no exist, exit now
    if (*status) {
        return *status; 
    } else {
        printf("Opened file '%s'\n", pf->filename);
    }

    // Move to main HDU
    fits_movabs_hdu(pf->fptr, 1, NULL, status);

    // Figure out obs mode
    fits_read_key(pf->fptr, TSTRING, "OBS_MODE", hdr->obs_mode, NULL, status);
    int mode = psrfits_obs_mode(hdr->obs_mode);

    // Set the downsampling stuff to default values
    hdr->onlyI = 0;
    hdr->ds_time_fact = 1;
    hdr->ds_freq_fact = 1;

    // Blank parfile name, folding params
    fold->parfile[0] = '\0';
    fold->n_polyco_sets = 0;
    fold->pc = NULL;

    // Read some stuff
    fits_read_key(pf->fptr, TSTRING, "TELESCOP", hdr->telescope, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "OBSERVER", hdr->observer, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "PROJID", hdr->project_id, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "FRONTEND", hdr->frontend, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "BACKEND", hdr->backend, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "FD_POLN", hdr->poln_type, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "DATE-OBS", hdr->date_obs, NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "OBSFREQ", &(hdr->fctr), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "OBSBW", &(hdr->BW), NULL, status);
    fits_read_key(pf->fptr, TINT, "OBSNCHAN", &(hdr->orig_nchan), NULL, status);
    hdr->orig_df = hdr->BW / hdr->orig_nchan;
    fits_read_key(pf->fptr, TDOUBLE, "CHAN_DM", &(hdr->chan_dm), NULL, status);
    if (*status==KEY_NO_EXIST) { hdr->chan_dm=0.0; *status=0; }
    fits_read_key(pf->fptr, TSTRING, "SRC_NAME", hdr->source, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "TRK_MODE", hdr->track_mode, NULL, status);
    // TODO warn if not TRACK?
    fits_read_key(pf->fptr, TSTRING, "RA", hdr->ra_str, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "DEC", hdr->dec_str, NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "BMAJ", &(hdr->beam_FWHM), NULL, status);
    fits_read_key(pf->fptr, TSTRING, "CAL_MODE", hdr->cal_mode, NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "CAL_FREQ", &(hdr->cal_freq), NULL, 
            status);
    fits_read_key(pf->fptr, TDOUBLE, "CAL_DCYC", &(hdr->cal_dcyc), NULL, 
            status);
    fits_read_key(pf->fptr, TDOUBLE, "CAL_PHS", &(hdr->cal_phs), NULL, status);
    fits_read_key(pf->fptr, TSTRING, "FD_MODE", hdr->feed_mode, NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "FA_REQ", &(hdr->feed_angle), NULL, 
            status);
    fits_read_key(pf->fptr, TDOUBLE, "SCANLEN", &(hdr->scanlen), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "FD_SANG", &(hdr->fd_sang), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "FD_XYPH", &(hdr->fd_xyph), NULL, status);
    fits_read_key(pf->fptr, TINT, "FD_HAND", &(hdr->fd_hand), NULL, status);
    fits_read_key(pf->fptr, TINT, "BE_PHASE", &(hdr->be_phase), NULL, status);

    fits_read_key(pf->fptr, TINT, "STT_IMJD", &itmp, NULL, status);
    hdr->MJD_epoch = (long double)itmp;
    hdr->start_day = itmp;
    fits_read_key(pf->fptr, TDOUBLE, "STT_SMJD", &dtmp, NULL, status);
    hdr->MJD_epoch += dtmp/86400.0L;
    hdr->start_sec = dtmp;
    fits_read_key(pf->fptr, TDOUBLE, "STT_OFFS", &dtmp, NULL, status);
    hdr->MJD_epoch += dtmp/86400.0L;
    hdr->start_sec += dtmp;

    fits_read_key(pf->fptr, TDOUBLE, "STT_LST", &(hdr->start_lst), NULL, 
            status);

    // Move to first subint
    fits_movnam_hdu(pf->fptr, BINARY_TBL, "SUBINT", 0, status);

    // Read some more stuff
    fits_read_key(pf->fptr, TINT, "NPOL", &(hdr->npol), NULL, status);
    fits_read_key(pf->fptr, TSTRING, "POL_TYPE", &(hdr->poln_order), NULL, status);
    if (strncmp(hdr->poln_order, "AA+BB", 6)==0) hdr->summed_polns=1;
    else hdr->summed_polns=0;
    fits_read_key(pf->fptr, TDOUBLE, "TBIN", &(hdr->dt), NULL, status);
    fits_read_key(pf->fptr, TINT, "NBIN", &(hdr->nbin), NULL, status);
    fits_read_key(pf->fptr, TINT, "NSUBOFFS", &(hdr->offset_subint), NULL, 
            status);
    fits_read_key(pf->fptr, TINT, "NCHAN", &(hdr->nchan), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "CHAN_BW", &(hdr->df), NULL, status);
    fits_read_key(pf->fptr, TINT, "NSBLK", &(hdr->nsblk), NULL, status);
    fits_read_key(pf->fptr, TINT, "NBITS", &(hdr->nbits), NULL, status);

    if (mode==SEARCH_MODE) {
        long long lltmp = hdr->nsblk;  // Prevents a possible overflow in numerator below
        lltmp = (lltmp * hdr->nbits * hdr->nchan * hdr->npol) / 8L;
        sub->bytes_per_subint = (int) lltmp;
    } else if (mode==FOLD_MODE) {
        sub->bytes_per_subint = 
            (hdr->nbin * hdr->nchan * hdr->npol); // XXX data type??
    }

    // Init counters
    pf->rownum = 1;
    fits_read_key(pf->fptr, TINT, "NAXIS2", &(pf->rows_per_file), NULL, status);

    return *status;
}
Example #5
0
/* Read next subint from the set of files described
 * by the psrfits struct.  It is assumed that all files
 * form a consistent set.  Read automatically goes to the
 * next file when one ends.  Arrays should be allocated
 * outside this routine.
 */
int psrfits_read_subint(struct psrfits *pf) {

    struct hdrinfo *hdr = &(pf->hdr);
    struct subint  *sub = &(pf->sub);
    int colnum = 0, *status = &(pf->status);

    // See if we need to move to next file
    if (pf->rownum > pf->rows_per_file) {
        printf("Closing file '%s'\n", pf->filename);
        fits_close_file(pf->fptr, status);
        pf->filenum++;
        psrfits_open(pf);
        if (*status==FILE_NOT_OPENED) {
            printf("Finished with all input files.\n");
            pf->filenum--;
            *status = 1;
            return *status;
        }
    }

    int mode = psrfits_obs_mode(hdr->obs_mode);
    int nchan = hdr->nchan;
    int nivals = hdr->nchan * hdr->npol;
    int row = pf->rownum;

    // TODO: bad! really need to base this on column names
    fits_get_colnum(pf->fptr, 0, "TSUBINT", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->tsubint),
            NULL, status);
    double last_offs = sub->offs;
    fits_get_colnum(pf->fptr, 0, "OFFS_SUB", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->offs),
            NULL, status);
    // Hack to fix wrapping in coherent data
    if (pf->tot_rows > 0) {
        double delta_offs = sub->offs - last_offs;
	double wrap_offs = 4294967296L * hdr->dt;
        if (delta_offs < -0.5*wrap_offs) {
            sub->offs += wrap_offs;
	    fprintf(stderr, "Warning: detected likely counter wrap, attempting to fix it.\n");
        }
    }
    fits_get_colnum(pf->fptr, 0, "LST_SUB", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->lst),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "RA_SUB", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->ra),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "DEC_SUB", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->dec),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "GLON_SUB", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->glon),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "GLAT_SUB", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->glat),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "FD_ANG", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->feed_ang),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "POS_ANG", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->pos_ang),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "PAR_ANG", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->par_ang),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "TEL_AZ", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->tel_az),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "TEL_ZEN", &colnum, status);
    fits_read_col(pf->fptr, TDOUBLE, colnum, row, 1, 1, NULL, &(sub->tel_zen),
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "DAT_FREQ", &colnum, status);
    fits_read_col(pf->fptr, TFLOAT, colnum, row, 1, nchan, NULL, sub->dat_freqs,
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "DAT_WTS", &colnum, status);
    fits_read_col(pf->fptr, TFLOAT, colnum, row, 1, nchan, NULL, sub->dat_weights,
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "DAT_OFFS", &colnum, status);
    fits_read_col(pf->fptr, TFLOAT, colnum, row, 1, nivals, NULL, sub->dat_offsets,
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "DAT_SCL", &colnum, status);
    fits_read_col(pf->fptr, TFLOAT, colnum, row, 1, nivals, NULL, sub->dat_scales,
            NULL, status);
    fits_get_colnum(pf->fptr, 0, "DATA", &colnum, status);
    if (mode==SEARCH_MODE) {
        if (hdr->nbits==32)
            fits_read_col(pf->fptr, TFLOAT, colnum, row, 1, 
                    sub->bytes_per_subint/4,
                    NULL, sub->rawdata, NULL, status);
        else
            fits_read_col(pf->fptr, TBYTE, colnum, row, 1, 
                    sub->bytes_per_subint,
                    NULL, sub->rawdata, NULL, status);
        if (hdr->nbits==4) pf_4bit_to_8bit(pf);
    } else if (mode==FOLD_MODE) {
        fits_read_col(pf->fptr, TFLOAT, colnum, row, 1, sub->bytes_per_subint,
                      NULL, sub->data, NULL, status);
    }

    // Complain on error
    fits_report_error(stderr, *status);

    // Update counters
    if (!(*status)) {
        pf->rownum++;
        pf->tot_rows++;
        pf->N += hdr->nsblk;
        pf->T = pf->N * hdr->dt;
    }

    return *status;
}
int psrfits_write_subint(struct psrfits *pf)
{
    int row, *status, nchan, nivals, mode, out_nbytes, nstat, dummy;
    float ftmp;
    struct hdrinfo *hdr;
    struct subint *sub;

    hdr = &(pf->hdr);           // dereference the ptr to the header struct
    sub = &(pf->sub);           // dereference the ptr to the subint struct
    status = &(pf->status);     // dereference the ptr to the CFITSIO status
    nchan = hdr->nchan / hdr->ds_freq_fact;
    nstat = sub->statbytes_per_subint / 2;      //stat array is shorts
    if (hdr->onlyI)
        nivals = nchan;
    else
        nivals = nchan * hdr->npol;
    mode = psrfits_obs_mode(hdr->obs_mode);
    if (mode == fold)
        out_nbytes = sub->bytes_per_subint / hdr->ds_freq_fact;
    else {
        out_nbytes = sub->bytes_per_subint / (hdr->ds_freq_fact * hdr->ds_time_fact);
        if (hdr->onlyI)
            out_nbytes /= hdr->npol;
    }

    // Create the initial file or change to a new one if needed.
    // Stay with a single file for fold mode.

    //fprintf(stderr,"In psrfits write, pf->filenum: %d pf->multifile: %d\n",pf->filenum,pf->multifile);
    //fprintf(stderr,"In psrfits write, pf->rownum %d pf->rows_per_file: %d\n",pf->rownum,pf->rows_per_file);

    /*
       if (pf->filenum==0 ||
       ( (mode==search || pf->multifile==1)
       && pf->rownum > pf->rows_per_file)) {
       if (pf->filenum) {
       printf("Closing file '%s'\n", pf->filename);
       fits_close_file(pf->fptr, status);
       return *status;
       }
       psrfits_create(pf);
       }
     */

    row = pf->rownum;
    //fprintf(stderr,"In psrfits write, row: %d\n",row);

    //fits_read_key(pf->fptr, TINT, "NAXIS2", &dummy, NULL, status);
    //fprintf(stderr,"In psrfits write, before col writing, NAXIS2: %d status; %d\n",dummy,*status);

    fprintf(stderr, "tsubint: %f  offs_sub: %f\n", sub->tsubint, sub->offs);

    fits_write_col(pf->fptr, TDOUBLE, 1, row, 1, 1, &(sub->tsubint), status);
    fits_write_col(pf->fptr, TDOUBLE, 2, row, 1, 1, &(sub->offs), status);
    fits_write_col(pf->fptr, TDOUBLE, 3, row, 1, 1, &(sub->lst), status);
    fits_write_col(pf->fptr, TDOUBLE, 4, row, 1, 1, &(sub->ra), status);
    fits_write_col(pf->fptr, TDOUBLE, 5, row, 1, 1, &(sub->dec), status);
    fits_write_col(pf->fptr, TDOUBLE, 6, row, 1, 1, &(sub->glon), status);
    fits_write_col(pf->fptr, TDOUBLE, 7, row, 1, 1, &(sub->glat), status);
    ftmp = (float) sub->feed_ang;
    fits_write_col(pf->fptr, TFLOAT, 8, row, 1, 1, &ftmp, status);
    ftmp = (float) sub->pos_ang;
    fits_write_col(pf->fptr, TFLOAT, 9, row, 1, 1, &ftmp, status);
    ftmp = (float) sub->par_ang;
    fits_write_col(pf->fptr, TFLOAT, 10, row, 1, 1, &ftmp, status);
    ftmp = (float) sub->tel_az;
    fits_write_col(pf->fptr, TFLOAT, 11, row, 1, 1, &ftmp, status);
    ftmp = (float) sub->tel_zen;
    fits_write_col(pf->fptr, TFLOAT, 12, row, 1, 1, &ftmp, status);
    fits_write_col(pf->fptr, TFLOAT, 13, row, 1, nchan, sub->dat_freqs, status);
    fits_write_col(pf->fptr, TFLOAT, 14, row, 1, nchan, sub->dat_weights, status);
    fits_write_col(pf->fptr, TFLOAT, 15, row, 1, nivals, sub->dat_offsets, status);
    fits_write_col(pf->fptr, TFLOAT, 16, row, 1, nivals, sub->dat_scales, status);

    if (mode == search) {
        // Need to change this for other data types...
        //fprintf(stderr,"In psrfits write, out_nbytes (data bytes per subint): %d\n",out_nbytes);
        fits_write_col(pf->fptr, TBYTE, 17, row, 1, out_nbytes, sub->data, status);
    } else if (mode == fold) {
        // Fold mode writes floats for now..
        fits_write_col(pf->fptr, TFLOAT, 17, row, 1, out_nbytes / sizeof(float),
                       sub->data, status);
    }

    /*
       fprintf(stderr,"In psrfits write, out_nbytes: %d, nchan: %d nivals: %d nstat: %d status: %d\n",out_nbytes,nchan,nivals,nstat,*status);
       fits_flush_file(pf->fptr, status);
       fits_read_key(pf->fptr, TINT, "NAXIS2", &dummy, NULL, status);
       fprintf(stderr,"In psrfits write after 17 column, NAXIS2: %d status; %d\n",dummy,*status);
     */

    fits_write_col(pf->fptr, TSHORT, 18, row, 1, nstat, sub->stat, status);

    // Flush the buffers if not finished with the file
    // Note:  this use is not entirely in keeping with the CFITSIO
    //        documentation recommendations.  However, manually
    //        correcting NAXIS2 and using fits_flush_buffer()
    //        caused occasional hangs (and extrememly large
    //        files due to some infinite loop).
    fits_flush_file(pf->fptr, status);

    //NOTE: using flush_file resulted in an extra row for some reason

    //fits_flush_buffer(pf->fptr,0,status);

    //fits_read_key(pf->fptr, TINT, "NAXIS2", &dummy, NULL, status);
    //fprintf(stderr,"In psrfits write, after fits flush, NAXIS2: %d status; %d\n",dummy,*status);

    // Print status if bad
    if (*status) {
        fprintf(stderr, "Error writing subint %d:\n", pf->rownum);
        fits_report_error(stderr, *status);
        fflush(stderr);
    }
    // Now update some key values if no CFITSIO errors
    if (!(*status)) {
        pf->rownum++;
        pf->tot_rows++;
        pf->N += hdr->nsblk / hdr->ds_time_fact;
        pf->T += sub->tsubint;

        // For fold mode, print info each subint written
        if (mode == fold && pf->quiet != 1) {
            printf("Wrote subint %d (total time %.1fs)\n", pf->rownum - 1, pf->T);
            fflush(stdout);
        }

    }
    //fits_update_key(pf->fptr,TINT,"NAXIS2",&(pf->tot_rows),NULL,status);

    return *status;
}
/***********************************************************************************
 *  psrfits_subint(struct *psrfits *pf,int first)
 *  first: if true then first call, we need to read all the keys in the subint row.
 *         after the first we just read the data and the status.
 *
 * Read next subint from the set of files described
 * by the psrfits struct.  It is assumed that all files
 * form a consistent set.  Read automatically goes to the
 * next file when one ends.  Arrays should be allocated
 * outside this routine.
 */
int psrfits_read_subint(struct psrfits *pf, int first)
{

    struct hdrinfo *hdr = &(pf->hdr);
    struct subint *sub = &(pf->sub);
    int *status = &(pf->status);

    // See if we need to move to next file
    /*
       if (pf->rownum > pf->rows_per_file) {
       fits_close_file(pf->fptr, status);
       fprintf(stderr,"Closed file '%s'\n", pf->filename);
       pf->filenum++;
       if (psrfits_open(pf) != 0) {
       return *status;
       }
       }
     */

    if (pf->rownum > pf->rows_per_file)
        return 1;


    int mode = psrfits_obs_mode(hdr->obs_mode);
    //   match the args for the cfitsio params
    LONGLONG nchan = hdr->nchan;
    LONGLONG nivals = hdr->nchan * hdr->npol;
    LONGLONG row = pf->rownum;
    LONGLONG firstE = 1;        // first element of row
    LONGLONG oneE = 1;          // one element in row
    SUBINT_COLS *pcol;
    pcol = &pf->subcols;

    //Need to read all columns at every subint in order to copy the fields to
    //converted psrfits data output
    //  if (first) { 
    // modified to use column names. pjp 10jan09 
    fits_read_col(pf->fptr, TDOUBLE, pcol->tsubint, row, firstE, oneE, NULL,
                  &(sub->tsubint), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->offs_sub, row, firstE, oneE, NULL,
                  &(sub->offs), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->lst_sub, row, firstE, oneE, NULL,
                  &(sub->lst), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->ra_sub, row, firstE, oneE, NULL,
                  &(sub->ra), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->dec_sub, row, firstE, oneE, NULL,
                  &(sub->dec), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->glon_sub, row, firstE, oneE, NULL,
                  &(sub->glon), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->glat_sub, row, firstE, oneE, NULL,
                  &(sub->glat), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->fd_ang, row, firstE, oneE, NULL,
                  &(sub->feed_ang), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->pos_ang, row, firstE, oneE, NULL,
                  &(sub->pos_ang), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->par_ang, row, firstE, oneE, NULL,
                  &(sub->par_ang), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->tel_az, row, firstE, oneE, NULL,
                  &(sub->tel_az), NULL, status);
    fits_read_col(pf->fptr, TDOUBLE, pcol->tel_zen, row, firstE, oneE, NULL,
                  &(sub->tel_zen), NULL, status);
    fits_read_col(pf->fptr, TFLOAT, pcol->dat_freq, row, firstE, nchan, NULL,
                  sub->dat_freqs, NULL, status);
    fits_read_col(pf->fptr, TFLOAT, pcol->dat_wts, row, firstE, nchan, NULL,
                  sub->dat_weights, NULL, status);
    fits_read_col(pf->fptr, TFLOAT, pcol->dat_offs, row, firstE, nivals, NULL,
                  sub->dat_offsets, NULL, status);
    fits_read_col(pf->fptr, TFLOAT, pcol->dat_scl, row, firstE, nivals, NULL,
                  sub->dat_scales, NULL, status);
    //  }

    if (mode == SEARCH_MODE) {
        switch (sub->typecode) {
        case TBYTE:
            fits_read_col(pf->fptr, sub->typecode, pcol->data, row, firstE,
                          (LONGLONG) (sub->bytes_per_subint) / sub->bytesPerDatum,
                          NULL, sub->data, NULL, status);
            break;
        case TSHORT:
            fits_read_col(pf->fptr, sub->typecode, pcol->data, row, firstE,
                          (LONGLONG) (sub->bytes_per_subint) / sub->bytesPerDatum,
                          NULL, (short *) sub->data, NULL, status);
            break;
        case TINT:
            fits_read_col(pf->fptr, sub->typecode, pcol->data, row, firstE,
                          (LONGLONG) (sub->bytes_per_subint) / sub->bytesPerDatum,
                          NULL, (int *) sub->data, NULL, status);
            break;
        case TFLOAT:
            fits_read_col(pf->fptr, sub->typecode, pcol->data, row, firstE,
                          (LONGLONG) (sub->bytes_per_subint) / sub->bytesPerDatum,
                          NULL, (float *) sub->data, NULL, status);
            break;
        case TDOUBLE:
            fits_read_col(pf->fptr, sub->typecode, pcol->data, row, firstE,
                          (LONGLONG) (sub->bytes_per_subint) / sub->bytesPerDatum,
                          NULL, (double *) sub->data, NULL, status);
            break;
        default:
            fprintf(stderr, "psrfits_read_subint:unsupported datatype code:%d\n",
                    sub->typecode);
            fprintf(stderr,
                    "Currently supported:TBYTE=11,TSHORT=21,TINT=31,TFLOAT=32,TDOUBLE=82\n");
            fprintf(stderr, "..see fitsio.h include file for the definitions\n");
            exit(-1);
            break;
        }
        fits_read_col(pf->fptr, TSHORT, pcol->stat, row, firstE,
                      (LONGLONG) (sub->statbytes_per_subint) / sizeof(short), NULL,
                      sub->stat, NULL, status);
    } else if (mode == FOLD_MODE) {
        fits_read_col(pf->fptr, sub->typecode, pcol->data, row, firstE,
                      (LONGLONG) (sub->bytes_per_subint) / sub->bytesPerDatum, NULL,
                      sub->data, NULL, status);
    }
    // Complain on error
    fits_report_error(stderr, *status);

    // Update counters
    if (!(*status)) {
        pf->rownum++;
        pf->tot_rows++;

        pf->N += hdr->nsblk;
        pf->T = pf->N * hdr->dt;
    }

    return *status;
}
/* This function is similar to psrfits_create, except it
 * deals with reading existing files.  It is assumed that
 * basename and filenum are filled in correctly to point to 
 * the first file in the set.
 */
int psrfits_open(struct psrfits *pf, int iomode)
{

    int itmp;
    double dtmp;
    char ctmp[256];

    struct hdrinfo *hdr = &(pf->hdr);
    struct subint *sub = &(pf->sub);

    int *status = &(pf->status);

    sprintf(pf->filename, "%s%0*d.fits", pf->basefilename, pf->fnamedigits,
            pf->filenum);
    //fprintf(stderr,"%s\n",pf->filename);
    fits_open_file(&(pf->fptr), pf->filename, iomode, status);

    // If file does not exist, exit now
    if (*status) {
        return *status;
    }
    fprintf(stderr, "Opened file '%s'\n", pf->filename);

    // Move to main HDU
    fits_movabs_hdu(pf->fptr, 1, NULL, status);

    // Figure out obs mode
    fits_read_key(pf->fptr, TSTRING, "OBS_MODE", hdr->obs_mode, NULL, status);
    int mode = psrfits_obs_mode(hdr->obs_mode);

    // Read some stuff
    fits_read_key(pf->fptr, TSTRING, "TELESCOP", hdr->telescope, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "OBSERVER", hdr->observer, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "PROJID", hdr->project_id, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "FRONTEND", hdr->frontend, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "BACKEND", hdr->backend, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "FD_POLN", hdr->poln_type, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "DATE-OBS", hdr->date_obs, NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "OBSFREQ", &(hdr->fctr), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "OBSBW", &(hdr->BW), NULL, status);
    fits_read_key(pf->fptr, TINT, "OBSNCHAN", &(hdr->orig_nchan), NULL, status);
    fits_read_key(pf->fptr, TSTRING, "SRC_NAME", hdr->source, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "TRK_MODE", hdr->track_mode, NULL, status);
    // TODO warn if not TRACK?
    fits_read_key(pf->fptr, TSTRING, "RA", hdr->ra_str, NULL, status);
    fits_read_key(pf->fptr, TSTRING, "DEC", hdr->dec_str, NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "BMAJ", &(hdr->beam_FWHM), NULL, status);
    fits_read_key(pf->fptr, TSTRING, "CAL_MODE", hdr->cal_mode, NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "CAL_FREQ", &(hdr->cal_freq), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "CAL_DCYC", &(hdr->cal_dcyc), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "CAL_PHS", &(hdr->cal_phs), NULL, status);
    fits_read_key(pf->fptr, TSTRING, "FD_MODE", hdr->feed_mode, NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "FA_REQ", &(hdr->feed_angle), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "SCANLEN", &(hdr->scanlen), NULL, status);

    fits_read_key(pf->fptr, TINT, "STT_IMJD", &itmp, NULL, status);
    hdr->MJD_epoch = (long double) itmp;
    fits_read_key(pf->fptr, TDOUBLE, "STT_SMJD", &dtmp, NULL, status);
    hdr->MJD_epoch += dtmp / 86400.0L;
    fits_read_key(pf->fptr, TDOUBLE, "STT_OFFS", &dtmp, NULL, status);
    hdr->MJD_epoch += dtmp / 86400.0L;

    fits_read_key(pf->fptr, TDOUBLE, "STT_LST", &(hdr->start_lst), NULL, status);

    // Move to pdev bintab to see if blanking enabled
    //
    int blankSel, adcThr;
    fits_movnam_hdu(pf->fptr, BINARY_TBL, "PDEV", 0, status);
    fits_read_key(pf->fptr, TINT, "PHBLKSEL", &(blankSel), NULL, status);
    fits_read_key(pf->fptr, TINT, "PHADCTHR", &(adcThr), NULL, status);
    fits_read_key(pf->fptr, TINT, "PHFFTACC", &(hdr->fftAccum), NULL, status);
    hdr->blankingOn = (blankSel != 15) || (adcThr != 65535);

    // Move to first subint
    fits_movnam_hdu(pf->fptr, BINARY_TBL, "SUBINT", 0, status);

    // Read some more stuff
    fits_read_key(pf->fptr, TINT, "NPOL", &(hdr->npol), NULL, status);
    fits_read_key(pf->fptr, TSTRING, "POL_TYPE", ctmp, NULL, status);
    if (strncmp(ctmp, "AA+BB", 6) == 0)
        hdr->summed_polns = 1;
    else
        hdr->summed_polns = 0;
    fits_read_key(pf->fptr, TDOUBLE, "TBIN", &(hdr->dt), NULL, status);
    fits_read_key(pf->fptr, TINT, "NBIN", &(hdr->nbin), NULL, status);
    fits_read_key(pf->fptr, TINT, "NSUBOFFS", &(hdr->offset_subint), NULL, status);
    fits_read_key(pf->fptr, TINT, "NCHAN", &(hdr->nchan), NULL, status);
    fits_read_key(pf->fptr, TDOUBLE, "CHAN_BW", &(hdr->df), NULL, status);
    fits_read_key(pf->fptr, TINT, "NSBLK", &(hdr->nsblk), NULL, status);
    fits_read_key(pf->fptr, TINT, "NBITS", &(hdr->nbits), NULL, status);

    if (mode == SEARCH_MODE) {
        sub->bytes_per_subint =
            (hdr->nbits * hdr->nchan * hdr->npol * hdr->nsblk) / 8;
        sub->statbytes_per_subint = hdr->nsblk * AO_NUM_SH_STAT_1DMP * sizeof(short);
    } else if (mode == FOLD_MODE) {
        sub->bytes_per_subint = (hdr->nbin * hdr->nchan * hdr->npol) * hdr->nbits / 8;  //XXX data type??
    }
    //  to tell us the end of the good data in file.
    pf->hdr.numBlksTot = (pf->hdr.scanlen / pf->hdr.dt + .5);
    // Init counters
    pf->rownum = 1;

    fits_read_key(pf->fptr, TINT, "NAXIS2", &(pf->rows_per_file), NULL, status);
    if (!pf->initialized) {
        fits_get_colnum(pf->fptr, 1, "TSUBINT", &pf->subcols.tsubint, status);
        fits_get_colnum(pf->fptr, 1, "OFFS_SUB", &pf->subcols.offs_sub, status);
        fits_get_colnum(pf->fptr, 1, "LST_SUB", &pf->subcols.lst_sub, status);
        fits_get_colnum(pf->fptr, 1, "RA_SUB", &pf->subcols.ra_sub, status);
        fits_get_colnum(pf->fptr, 1, "DEC_SUB", &pf->subcols.dec_sub, status);
        fits_get_colnum(pf->fptr, 1, "GLON_SUB", &pf->subcols.glon_sub, status);
        fits_get_colnum(pf->fptr, 1, "GLAT_SUB", &pf->subcols.glat_sub, status);
        fits_get_colnum(pf->fptr, 1, "FD_ANG", &pf->subcols.fd_ang, status);
        fits_get_colnum(pf->fptr, 1, "POS_ANG", &pf->subcols.pos_ang, status);
        fits_get_colnum(pf->fptr, 1, "PAR_ANG", &pf->subcols.par_ang, status);
        fits_get_colnum(pf->fptr, 1, "TEL_AZ", &pf->subcols.tel_az, status);
        fits_get_colnum(pf->fptr, 1, "TEL_ZEN", &pf->subcols.tel_zen, status);
        fits_get_colnum(pf->fptr, 1, "DAT_FREQ", &pf->subcols.dat_freq, status);
        fits_get_colnum(pf->fptr, 1, "DAT_WTS", &pf->subcols.dat_wts, status);
        fits_get_colnum(pf->fptr, 1, "DAT_OFFS", &pf->subcols.dat_offs, status);
        fits_get_colnum(pf->fptr, 1, "DAT_SCL", &pf->subcols.dat_scl, status);
        fits_get_colnum(pf->fptr, 1, "DATA", &pf->subcols.data, status);
        fits_get_colnum(pf->fptr, 1, "STAT", &pf->subcols.stat, status);

        long repeat;
        long width;
        fits_get_coltype(pf->fptr, pf->subcols.data, &sub->typecode, &repeat,
                         &width, status);
        sub->bytesPerDatum = width;
        if (sub->typecode == TINT32BIT)
            sub->typecode = TINT;
        sub->data = malloc(sizeof(char) * sub->bytes_per_subint);
        sub->dataBytesAlloced = sub->bytes_per_subint;
        sub->stat = (unsigned short *) malloc(sub->statbytes_per_subint);
        pf->initialized = 1;
    }
    return *status;
}