void get_PSRFITS_subint(float *fdata, unsigned char *cdata, struct spectra_info *s) { unsigned char *ctmp = cdata; int ii, status = 0, anynull; int numtoread = s->samples_per_subint; // The following allows us to read byte-packed data if (s->bits_per_sample < 8) { numtoread = (s->samples_per_subint * s->bits_per_sample) / 8; ctmp = gen_bvect(numtoread); } // or 16-bit data that is listed as being bytes if (s->bits_per_sample == 16 && s->FITS_typecode == 11) numtoread = s->samples_per_subint * 2; // Read the weights, offsets, and scales if required if (s->apply_weight) fits_read_col(s->fitsfiles[cur_file], TFLOAT, s->dat_wts_col, cur_subint, 1L, s->num_channels, 0, weights, &anynull, &status); if (s->apply_offset) fits_read_col(s->fitsfiles[cur_file], TFLOAT, s->dat_offs_col, cur_subint, 1L, s->num_channels * s->num_polns, 0, offsets, &anynull, &status); if (s->apply_scale) fits_read_col(s->fitsfiles[cur_file], TFLOAT, s->dat_scl_col, cur_subint, 1L, s->num_channels * s->num_polns, 0, scales, &anynull, &status); // Now actually read the subint into the temporary buffer fits_read_col(s->fitsfiles[cur_file], s->FITS_typecode, s->data_col, cur_subint, 1L, numtoread, 0, ctmp, &anynull, &status); if (status) { fprintf(stderr, "Error!: Problem reading record from PSRFITS data file\n" "\tfilename = '%s', subint = %d. FITS status = %d. Exiting.\n", s->filenames[cur_file], cur_subint, status); exit(1); } // The following converts that byte-packed data into bytes if (s->bits_per_sample == 4) { #ifdef _OPENMP #pragma omp parallel for default(none) shared(numtoread,cdata,ctmp) #endif for (ii = 0; ii < numtoread; ii++) { const unsigned char uctmp = ctmp[ii]; const int jj = 2 * ii; cdata[jj] = uctmp >> 4; cdata[jj + 1] = uctmp & 0x0F; } } else if (s->bits_per_sample == 2) {
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; }
void fill_psrfits_struct(int numwapps, int numbits, struct HEADERP *h, struct wappinfo *w, struct psrfits *pf) { int slen, ii; char *cptr; pf->filenum = 0; // Crucial for initialization pf->hdr.nsblk = (int) (1.0 / w->dt); // _might_ be a problem... // Now set values for our hdrinfo structure strcpy(pf->hdr.telescope, "Arecibo"); cptr = get_hdr_string(h, "obs_type", &slen); if (strncmp("PULSAR_SEARCH", cptr, slen) == 0) { strcpy(pf->hdr.obs_mode, "SEARCH"); } else { printf("Error: Wapp data is not in search format!\n\n"); exit(1); } strcpy(pf->hdr.backend, "WAPP"); cptr = get_hdr_string(h, "frontend", &slen); if(cptr != NULL) strncpy(pf->hdr.frontend, cptr, slen); else strncpy(pf->hdr.frontend, "alfa", 4); cptr = get_hdr_string(h, "observers", &slen); strncpy(pf->hdr.observer, cptr, slen); cptr = get_hdr_string(h, "project_id", &slen); strncpy(pf->hdr.project_id, cptr, slen); cptr = get_hdr_string(h, "src_name", &slen); strncpy(pf->hdr.source, cptr, slen); strcpy(pf->hdr.date_obs, w->date_obs); pf->hdr.scanlen = get_hdr_double(h, "obs_time"); strcpy(pf->hdr.poln_type, "LIN"); // set based on known receivers if (get_hdr_int(h, "sum")) { strcpy(pf->hdr.poln_order, "AA+BB"); pf->hdr.summed_polns = 1; } else if (w->numifs == 1) { strcpy(pf->hdr.poln_order, "AA"); pf->hdr.summed_polns = 0; } strcpy(pf->hdr.track_mode, "TRACK"); // Potentially not-true? strcpy(pf->hdr.cal_mode, "OFF"); // Potentially not-true? strcpy(pf->hdr.feed_mode, "FA"); // check this... pf->hdr.beamnum = 0; if (get_hdr_int(h, "isalfa")) pf->hdr.beamnum = w->beamnum; pf->hdr.dt = w->dt; pf->hdr.fctr = w->fctr + 0.5 * (numwapps - 1.0) * w->BW; pf->hdr.BW = w->BW * numwapps; pf->hdr.beam_FWHM = beam_FWHM(pf->hdr.fctr, 300.0); pf->hdr.nchan = w->numchans * numwapps; pf->hdr.orig_nchan = w->numchans * numwapps; pf->hdr.orig_df = pf->hdr.df = pf->hdr.BW / pf->hdr.nchan; pf->hdr.nbits = numbits; pf->hdr.npol = w->numifs; pf->hdr.MJD_epoch = w->MJD_epoch; pf->hdr.start_day = (int) (w->MJD_epoch); pf->hdr.start_sec = (w->MJD_epoch - pf->hdr.start_day) * 86400.0; pf->hdr.scan_number = get_hdr_int(h, "scan_number"); pf->hdr.ra2000 = w->ra; dec2hms(pf->hdr.ra_str, pf->hdr.ra2000 / 15.0, 0); pf->hdr.dec2000 = w->dec; dec2hms(pf->hdr.dec_str, pf->hdr.dec2000, 1); pf->hdr.azimuth = get_hdr_double(h, "start_az"); pf->hdr.zenith_ang = get_hdr_double(h, "start_za"); pf->hdr.rcvr_polns = 2; pf->hdr.offset_subint = 0; pf->hdr.onlyI = 0; pf->hdr.ds_time_fact = 1; pf->hdr.ds_freq_fact = 1; pf->hdr.chan_dm = 0.0; pf->hdr.fd_hand = pf->hdr.be_phase = 0; // This is almost certainly not correct pf->hdr.fd_sang = pf->hdr.fd_xyph = 0.0; // This is almost certainly not correct pf->hdr.feed_angle = 0.0; // This is almost certainly not correct pf->hdr.cal_freq = pf->hdr.cal_dcyc = pf->hdr.cal_phs = 0.0; // ditto // Now set values for our subint structure pf->sub.tel_az = get_hdr_double(h, "start_az"); pf->sub.tel_zen = get_hdr_double(h, "start_za"); pf->sub.lst = get_hdr_double(h, "start_lst"); pf->hdr.start_lst = pf->sub.lst; pf->sub.tsubint = pf->hdr.nsblk * pf->hdr.dt; pf->sub.ra = pf->hdr.ra2000; pf->sub.dec = pf->hdr.dec2000; pf->sub.offs = 0.5 * pf->sub.tsubint; slaEqgal(pf->hdr.ra2000 * DEGTORAD, pf->hdr.dec2000 * DEGTORAD, &pf->sub.glon, &pf->sub.glat); pf->sub.glon *= RADTODEG; pf->sub.glat *= RADTODEG; // The following three are unknown or hard to get, I think (SMR) pf->sub.feed_ang = 0.0; pf->sub.pos_ang = 0.0; pf->sub.par_ang = 0.0; pf->sub.bytes_per_subint = (pf->hdr.nbits * pf->hdr.nchan * pf->hdr.npol * pf->hdr.nsblk) / 8; pf->sub.FITS_typecode = TBYTE; // 11 = byte // Create and initialize the subint arrays pf->sub.dat_freqs = gen_fvect(pf->hdr.nchan); pf->sub.dat_weights = gen_fvect(pf->hdr.nchan); for (ii = 0; ii < pf->hdr.nchan; ii++) { pf->sub.dat_freqs[ii] = w->lofreq + ii * pf->hdr.df; pf->sub.dat_weights[ii] = 1.0; } // The following are re-set to try to preserve the band shape later pf->sub.dat_offsets = gen_fvect(pf->hdr.nchan * pf->hdr.npol); pf->sub.dat_scales = gen_fvect(pf->hdr.nchan * pf->hdr.npol); for (ii = 0; ii < pf->hdr.nchan * pf->hdr.npol; ii++) { pf->sub.dat_offsets[ii] = 0.0; pf->sub.dat_scales[ii] = 1.0; } // This is the raw data block that will be updated // for each row of the PSRFITS file pf->sub.data = gen_bvect(pf->sub.bytes_per_subint); }
int prep_subbands(float *fdata, float *rawdata, int *delays, int numsubbands, struct spectra_info *s, int transpose, int *maskchans, int *nummasked, mask * obsmask) // This routine preps a block of raw spectra for subbanding. It uses // dispersion delays in 'delays' to de-disperse the data into // 'numsubbands' subbands. It stores the resulting data in vector // 'fdata' of length 'numsubbands' * 's->spectra_per_subint'. The low // freq subband is stored first, then the next highest subband etc, // with 's->spectra_per_subint' floating points per subband. It // returns the # of points read if succesful, 0 otherwise. // 'maskchans' is an array of length numchans which contains a list of // the number of channels that were masked. The # of channels masked // is returned in 'nummasked'. 'obsmask' is the mask structure to use // for masking. If 'transpose'==0, the data will be kept in time // order instead of arranged by subband as above. { int ii, jj, trtn, offset; double starttime = 0.0; static float *tmpswap, *rawdata1, *rawdata2; static float *currentdata, *lastdata; static unsigned char *move; static int firsttime = 1, move_size = 0, mask = 0; *nummasked = 0; if (firsttime) { if (obsmask->numchan) mask = 1; move_size = (s->spectra_per_subint + numsubbands) / 2; move = gen_bvect(move_size); rawdata1 = gen_fvect(s->spectra_per_subint * s->num_channels); rawdata2 = gen_fvect(s->spectra_per_subint * s->num_channels); currentdata = rawdata1; lastdata = rawdata2; } /* Read and de-disperse */ memcpy(currentdata, rawdata, s->spectra_per_subint * s->num_channels * sizeof(float)); starttime = currentspectra * s->dt; // or -1 subint? if (mask) *nummasked = check_mask(starttime, s->time_per_subint, obsmask, maskchans); /* Clip nasty RFI if requested and we're not masking all the channels*/ if ((s->clip_sigma > 0.0) && !(mask && (*nummasked == -1))) clip_times(currentdata, s->spectra_per_subint, s->num_channels, s->clip_sigma, s->padvals); if (mask) { if (*nummasked == -1) { /* If all channels are masked */ for (ii = 0; ii < s->spectra_per_subint; ii++) memcpy(currentdata + ii * s->num_channels, s->padvals, s->num_channels * sizeof(float)); } else if (*nummasked > 0) { /* Only some of the channels are masked */ int channum; for (ii = 0; ii < s->spectra_per_subint; ii++) { offset = ii * s->num_channels; for (jj = 0; jj < *nummasked; jj++) { channum = maskchans[jj]; currentdata[offset + channum] = s->padvals[channum]; } } } } // In mpiprepsubband, the nodes do not call read_subbands() where // currentspectra gets incremented. if (using_MPI) currentspectra += s->spectra_per_subint; if (firsttime) { SWAP(currentdata, lastdata); firsttime = 0; return 0; } else { dedisp_subbands(currentdata, lastdata, s->spectra_per_subint, s->num_channels, delays, numsubbands, fdata); SWAP(currentdata, lastdata); /* Transpose the data into vectors in the result array */ if (transpose) { if ((trtn = transpose_float(fdata, s->spectra_per_subint, numsubbands, move, move_size)) < 0) printf("Error %d in transpose_float().\n", trtn); } return s->spectra_per_subint; } }
void fill_psrfits_struct(int numbits, struct psrfits *pf, float dt, char* source, int nchantot, float df, int imjd, int smjd, float offs, char* ra, char* dec, float lofreq, char *basename) { int ii; pf->filenum = 0; // Crucial for initialization strcpy(pf->basefilename, basename); pf->hdr.nsblk = (int) (roundf(1.0 / dt)); // Now set values for our hdrinfo structure strcpy(pf->hdr.telescope, "VLA"); strcpy(pf->hdr.obs_mode, "SEARCH"); strcpy(pf->hdr.backend, "YUPPI"); strcpy(pf->hdr.frontend, "HFF"); strcpy(pf->hdr.observer, " "); strcpy(pf->hdr.project_id, " "); strcpy(pf->hdr.source, source); strcpy(pf->hdr.date_obs, " "); //pf->hdr.scanlen = get_hdr_double(h, "obs_time"); strcpy(pf->hdr.poln_type, "LIN"); // set based on known receivers strcpy(pf->hdr.poln_order, "AA"); pf->hdr.summed_polns = 0; strcpy(pf->hdr.track_mode, "TRACK"); // Potentially not-true? strcpy(pf->hdr.cal_mode, "OFF"); // Potentially not-true? strcpy(pf->hdr.feed_mode, "FA"); // check this... pf->hdr.dt = dt; pf->hdr.fctr = lofreq + (nchantot/2.0 - 0.5)*df; pf->hdr.BW = nchantot*df; pf->hdr.beam_FWHM = beam_FWHM(pf->hdr.fctr, 34.0); pf->hdr.nchan = nchantot; pf->hdr.orig_nchan = nchantot; pf->hdr.df = df; pf->hdr.orig_df = df; pf->hdr.nbits = numbits; pf->hdr.npol = 1; pf->hdr.start_day = imjd; pf->hdr.start_sec = smjd; pf->hdr.MJD_epoch = (long double)imjd + ((long double)smjd + (long double)offs)/((long double)(24*3600)); pf->hdr.scan_number = 0; strcpy(pf->hdr.ra_str, ra); strcpy(pf->hdr.dec_str, dec); pf->hdr.ra2000 = 0.0; pf->hdr.dec2000 = 0.0; pf->hdr.azimuth = 0.0; pf->hdr.zenith_ang = 0.0; pf->hdr.rcvr_polns = 1; pf->hdr.offset_subint = 0; pf->hdr.onlyI = 0; pf->hdr.ds_time_fact = 1; pf->hdr.ds_freq_fact = 1; pf->hdr.chan_dm = 0.0; pf->hdr.fd_hand = 1.0; pf->hdr.be_phase = 0; // This is almost certainly not correct pf->hdr.fd_sang = pf->hdr.fd_xyph = 0.0; // This is almost certainly not correct pf->hdr.feed_angle = 0.0; // This is almost certainly not correct pf->hdr.cal_freq = pf->hdr.cal_dcyc = pf->hdr.cal_phs = 0.0; // ditto // Now set values for our subint structure pf->sub.tel_az = 0.0; pf->sub.tel_zen = 0.0; pf->sub.lst = 0.0; pf->sub.tsubint = pf->hdr.nsblk * pf->hdr.dt; pf->sub.ra = pf->hdr.ra2000; pf->sub.dec = pf->hdr.dec2000; pf->sub.offs = 0.5 * pf->sub.tsubint; //slaEqgal(pf->hdr.ra2000 * DEGTORAD, pf->hdr.dec2000 * DEGTORAD, // &pf->sub.glon, &pf->sub.glat); //pf->sub.glon *= RADTODEG; //pf->sub.glat *= RADTODEG; // The following three are unknown or hard to get, I think (SMR) pf->sub.feed_ang = 0.0; pf->sub.pos_ang = 0.0; pf->sub.par_ang = 0.0; pf->sub.bytes_per_subint = (pf->hdr.nbits/8) * pf->hdr.nchan * pf->hdr.npol * pf->hdr.nsblk; pf->sub.FITS_typecode = TBYTE; // newer, back to bytes //pf->sub.FITS_typecode = TFLOAT; // new //pf->sub.FITS_typecode = TBYTE; // 11 = byte // Create and initialize the subint arrays pf->sub.dat_freqs = gen_fvect(pf->hdr.nchan); pf->sub.dat_weights = gen_fvect(pf->hdr.nchan); for (ii = 0; ii < pf->hdr.nchan; ii++) { pf->sub.dat_freqs[ii] = lofreq + ii * pf->hdr.df; pf->sub.dat_weights[ii] = 1.0; } // The following are re-set to try to preserve the band shape later pf->sub.dat_offsets = gen_fvect(pf->hdr.nchan * pf->hdr.npol); pf->sub.dat_scales = gen_fvect(pf->hdr.nchan * pf->hdr.npol); for (ii = 0; ii < pf->hdr.nchan * pf->hdr.npol; ii++) { pf->sub.dat_offsets[ii] = 0.0; pf->sub.dat_scales[ii] = 1.0; } // This is the raw data block that will be updated // for each row of the PSRFITS file pf->sub.data = gen_bvect( pf->sub.bytes_per_subint ); // newest //pf->sub.data = gen_bvect( (pf->sub.bytes_per_subint)/4 ); // newer //pf->sub.data = gen_fvect( (pf->sub.bytes_per_subint)/4 ); // new //pf->sub.data = gen_bvect(pf->sub.bytes_per_subint); }
int main(int argc, char *argv[]) { int numfiles, ii, numrows, rownum, ichan, itsamp, datidx; int spec_per_row, status, maxrows; unsigned long int maxfilesize; float offset, scale, datum, packdatum, maxval, fulltsubint; float *datachunk; FILE **infiles; struct psrfits pfin, pfout; Cmdline *cmd; fitsfile *infits, *outfits; char outfilename[128], templatename[128], tform[8]; char *pc1, *pc2; int first = 1, dummy = 0, nclipped; short int *inrowdata; unsigned char *outrowdata; if (argc == 1) { Program = argv[0]; usage(); exit(1); } // Parse the command line using the excellent program Clig cmd = parseCmdline(argc, argv); numfiles = cmd->argc; infiles = (FILE **) malloc(numfiles * sizeof(FILE *)); //Set the max. total size (in bytes) of all rows in an output file, //leaving some room for PSRFITS header maxfilesize = (unsigned long int)(cmd->numgb * GB); maxfilesize = maxfilesize - 1000*KB; //fprintf(stderr,"cmd->numgb: %f maxfilesize: %ld\n",cmd->numgb,maxfilesize); #ifdef DEBUG showOptionValues(); #endif printf("\n PSRFITS 16-bit to 4-bit Conversion Code\n"); printf(" by J. Deneva, S. Ransom, & S. Chatterjee\n\n"); // Open the input files status = 0; //fits_close segfaults if this is not initialized printf("Reading input data from:\n"); for (ii = 0; ii < numfiles; ii++) { printf(" '%s'\n", cmd->argv[ii]); //Get the file basename and number from command-line argument //(code taken from psrfits2fil) pc2 = strrchr(cmd->argv[ii], '.'); // at .fits *pc2 = 0; // terminate string pc1 = pc2 - 1; while ((pc1 >= cmd->argv[ii]) && isdigit(*pc1)) pc1--; if (pc1 <= cmd->argv[ii]) { // need at least 1 char before filenum puts("Illegal input filename. must have chars before the filenumber"); exit(1); } pc1++; // we were sitting on "." move to first digit pfin.filenum = atoi(pc1); pfin.fnamedigits = pc2 - pc1; // how many digits in filenumbering scheme. *pc1 = 0; // null terminate the basefilename strcpy(pfin.basefilename, cmd->argv[ii]); pfin.initialized = 0; // set to 1 in psrfits_open() pfin.status = 0; //(end of code taken from psrfits2fil) //Open the existing psrfits file if (psrfits_open(&pfin, READONLY) != 0) { fprintf(stderr, "error opening file\n"); fits_report_error(stderr, pfin.status); exit(1); } // Create the subint arrays if (first) { pfin.sub.dat_freqs = (float *) malloc(sizeof(float) * pfin.hdr.nchan); pfin.sub.dat_weights = (float *) malloc(sizeof(float) * pfin.hdr.nchan); pfin.sub.dat_offsets = (float *) malloc(sizeof(float) * pfin.hdr.nchan * pfin.hdr.npol); pfin.sub.dat_scales = (float *) malloc(sizeof(float) * pfin.hdr.nchan * pfin.hdr.npol); //first is set to 0 after data buffer allocation further below } infits = pfin.fptr; spec_per_row = pfin.hdr.nsblk; fits_read_key(infits, TINT, "NAXIS2", &dummy, NULL, &status); pfin.tot_rows = dummy; numrows = dummy; //If dealing with 1st input file, create output template if (ii == 0) { sprintf(templatename, "%s.template.fits",cmd->outfile); fits_create_file(&outfits, templatename, &status); //fprintf(stderr,"pfin.basefilename: %s\n", pfin.basefilename); //fprintf(stderr,"status: %d\n", status); //Instead of copying HDUs one by one, can move to the SUBINT //HDU, and copy all the HDUs preceding it fits_movnam_hdu(infits, BINARY_TBL, "SUBINT", 0, &status); fits_copy_file(infits, outfits, 1, 0, 0, &status); //Copy the SUBINT table header fits_copy_header(infits, outfits, &status); fits_flush_buffer(outfits, 0, &status); //Set NAXIS2 in the output SUBINT table to 0 b/c we haven't //written any rows yet dummy = 0; fits_update_key(outfits, TINT, "NAXIS2", &dummy, NULL, &status); //Edit the NBITS key if (DEBUG) { dummy = 8; fits_update_key(outfits, TINT, "NBITS", &dummy, NULL, &status); } else { fits_update_key(outfits, TINT, "NBITS", &(cmd->numbits), NULL, &status); } //Edit the TFORM17 column: # of data bytes per row //fits_get_colnum(outfits,1,"DATA",&dummy,&status); if (DEBUG) sprintf(tform, "%dB", pfin.hdr.nsblk * pfin.hdr.nchan * pfin.hdr.npol); else sprintf(tform, "%dB", pfin.hdr.nsblk * pfin.hdr.nchan * pfin.hdr.npol * cmd->numbits / 8); fits_update_key(outfits, TSTRING, "TTYPE17", "DATA", NULL, &status); fits_update_key(outfits, TSTRING, "TFORM17", tform, NULL, &status); //Edit NAXIS1: row width in bytes fits_read_key(outfits, TINT, "NAXIS1", &dummy, NULL, &status); if (DEBUG) { dummy = dummy - pfin.hdr.nsblk * pfin.hdr.nchan * pfin.hdr.npol * (pfin.hdr.nbits - 8) / 8; } else { dummy = dummy - pfin.hdr.nsblk * pfin.hdr.nchan * pfin.hdr.npol * (pfin.hdr.nbits - cmd->numbits) / 8; } fits_update_key(outfits, TINT, "NAXIS1", &dummy, NULL, &status); //Set the max # of rows per file, based on the requested //output file size maxrows = maxfilesize / dummy; //fprintf(stderr,"maxrows: %d\n",maxrows); fits_close_file(outfits, &status); rownum = 0; } while (psrfits_read_subint(&pfin, first) == 0) { fprintf(stderr, "Working on row %d\n", ++rownum); //If this is the first row, store the length of a full subint if (ii == 0 && rownum == 1) fulltsubint = pfin.sub.tsubint; //If this is the last row and it's partial, drop it. //(It's pfin.rownum-1 below because the rownum member of the psrfits struct seems to be intended to indicate at the *start* of what row we are, i.e. a row that has not yet been read. In contrast, pfout.rownum indicates how many rows have been written, i.e. at the *end* of what row we are in the output.) if (pfin.rownum-1 == numrows && fabs(pfin.sub.tsubint - fulltsubint) > pfin.hdr.dt) { fprintf(stderr, "Dropping partial row of length %f s (full row is %f s)\n", pfin.sub.tsubint, fulltsubint); break; } //If we just read in the 1st row, or if we already wrote the last row in the current output file, create a new output file if ((ii == 0 && rownum == 1) || pfout.rownum == maxrows) { //Create new output file from the template pfout.fnamedigits = pfin.fnamedigits; if(ii == 0) pfout.filenum = pfin.filenum; else pfout.filenum++; sprintf(outfilename, "%s.%0*d.fits", cmd->outfile, pfout.fnamedigits, pfout.filenum); fits_create_template(&outfits, outfilename, templatename, &status); //fprintf(stderr,"After fits_create_template, status: %d\n",status); fits_close_file(outfits, &status); //Now reopen the file so that the pfout structure is initialized pfout.status = 0; pfout.initialized = 0; sprintf(pfout.basefilename, "%s.", cmd->outfile); if (psrfits_open(&pfout, READWRITE) != 0) { fprintf(stderr, "error opening file\n"); fits_report_error(stderr, pfout.status); exit(1); } outfits = pfout.fptr; maxval = pow(2, cmd->numbits) - 1; pfout.rows_per_file = maxrows; //fprintf(stderr, "maxval: %f\n", maxval); //fprintf(stderr, "pfout.rows_per_file: %d\n",pfout.rows_per_file); //These are not initialized in psrfits_open but are needed //in psrfits_write_subint (not obvious what are the corresponding //fields in any of the psrfits table headers) pfout.hdr.ds_freq_fact = 1; pfout.hdr.ds_time_fact = 1; } //Copy the subint struct from pfin to pfout, but correct //elements that are not the same pfout.sub = pfin.sub; //this copies array pointers too pfout.sub.bytes_per_subint = pfin.sub.bytes_per_subint * pfout.hdr.nbits / pfin.hdr.nbits; pfout.sub.dataBytesAlloced = pfout.sub.bytes_per_subint; pfout.sub.FITS_typecode = TBYTE; if (first) { //Allocate scaling buffer and output buffer datachunk = gen_fvect(spec_per_row); outrowdata = gen_bvect(pfout.sub.bytes_per_subint); first = 0; } pfout.sub.data = outrowdata; inrowdata = (short int *) pfin.sub.data; nclipped = 0; // Loop over all the channels: for (ichan = 0; ichan < pfout.hdr.nchan * pfout.hdr.npol; ichan++) { // Populate datachunk[] by picking out all time samples for ichan for (itsamp = 0; itsamp < spec_per_row; itsamp++) datachunk[itsamp] = (float) (inrowdata[ichan + itsamp * pfout.hdr.nchan * pfout.hdr.npol]); // Compute the statistics here, and put the offsets and scales in // pf.sub.dat_offsets[] and pf.sub.dat_scales[] if (rescale(datachunk, spec_per_row, cmd->numbits, &offset, &scale) != 0) { printf("Rescale routine failed!\n"); return (-1); } pfout.sub.dat_offsets[ichan] = offset; pfout.sub.dat_scales[ichan] = scale; // Since we have the offset and scale ready, rescale the data: for (itsamp = 0; itsamp < spec_per_row; itsamp++) { datum = (scale == 0.0) ? 0.0 : roundf((datachunk[itsamp] - offset) / scale); if (datum < 0.0) { datum = 0; nclipped++; } else if (datum > maxval) { datum = maxval; nclipped++; } inrowdata[ichan + itsamp * pfout.hdr.nchan * pfout.hdr.npol] = (short int) datum; } // Now inrowdata[ichan] contains rescaled ints. } // Then do the conversion and store the // results in pf.sub.data[] if (cmd->numbits == 8 || DEBUG) { for (itsamp = 0; itsamp < spec_per_row; itsamp++) { datidx = itsamp * pfout.hdr.nchan * pfout.hdr.npol; for (ichan = 0; ichan < pfout.hdr.nchan * pfout.hdr.npol; ichan++, datidx++) { pfout.sub.data[datidx] = (unsigned char) inrowdata[datidx]; } } } else if (cmd->numbits == 4) { for (itsamp = 0; itsamp < spec_per_row; itsamp++) { datidx = itsamp * pfout.hdr.nchan * pfout.hdr.npol; for (ichan = 0; ichan < pfout.hdr.nchan * pfout.hdr.npol; ichan += 2, datidx += 2) { packdatum = inrowdata[datidx] * 16 + inrowdata[datidx + 1]; pfout.sub.data[datidx / 2] = (unsigned char) packdatum; } } } else { fprintf(stderr, "Only 4 or 8-bit output formats supported.\n"); fprintf(stderr, "Bits per sample requested: %d\n", cmd->numbits); exit(1); } //pfout.sub.offs = (pfout.tot_rows+0.5) * pfout.sub.tsubint; fprintf(stderr, "nclipped: %d fraction clipped: %f\n", nclipped, (float) nclipped / (pfout.hdr.nchan * pfout.hdr.npol * pfout.hdr.nsblk)); // Now write the row. status = psrfits_write_subint(&pfout); if (status) { printf("\nError (%d) writing PSRFITS...\n\n", status); break; } //If current output file has reached the max # of rows, close it if (pfout.rownum == maxrows) fits_close_file(outfits, &status); } //Close the files fits_close_file(infits, &status); } fits_close_file(outfits, &status); // Free the structure arrays too... free(datachunk); free(infiles); free(pfin.sub.dat_freqs); free(pfin.sub.dat_weights); free(pfin.sub.dat_offsets); free(pfin.sub.dat_scales); free(pfin.sub.data); free(pfout.sub.data); free(pfin.sub.stat); return 0; }