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; }
int main(int argc, char *argv[]) { /* Cmd line */ static struct option long_opts[] = { {"output", 1, NULL, 'o'}, {"npulse", 1, NULL, 'n'}, {"nbin", 1, NULL, 'b'}, {"nthread", 1, NULL, 'j'}, {"initial", 1, NULL, 'i'}, {"final", 1, NULL, 'f'}, {"time", 1, NULL, 'T'}, {"length", 1, NULL, 'L'}, {"src", 1, NULL, 's'}, {"polyco", 1, NULL, 'p'}, {"parfile", 1, NULL, 'P'}, {"foldfreq",1, NULL, 'F'}, {"cal", 0, NULL, 'C'}, {"unsigned",0, NULL, 'u'}, {"quiet", 0, NULL, 'q'}, {"help", 0, NULL, 'h'}, {0,0,0,0} }; int opt, opti; int nbin=256, nthread=4, fnum_start=1, fnum_end=0; int quiet=0, raw_signed=1, use_polycos=1, cal=0; int npulse_per_file = 64; double start_time=0.0, process_time=0.0; double fold_frequency=0.0; char output_base[256] = ""; char polyco_file[256] = ""; char par_file[256] = ""; char source[24]; source[0]='\0'; while ((opt=getopt_long(argc,argv,"o:n:b:j:i:f:T:L:s:p:P:F:Cuqh",long_opts,&opti))!=-1) { switch (opt) { case 'o': strncpy(output_base, optarg, 255); output_base[255]='\0'; break; case 'n': npulse_per_file = atoi(optarg); break; case 'b': nbin = atoi(optarg); break; case 'j': nthread = atoi(optarg); break; case 'i': fnum_start = atoi(optarg); break; case 'f': fnum_end = atoi(optarg); break; case 'T': start_time = atof(optarg); break; case 'L': process_time = atof(optarg); break; case 's': strncpy(source, optarg, 24); source[23]='\0'; break; case 'p': strncpy(polyco_file, optarg, 255); polyco_file[255]='\0'; use_polycos = 1; break; case 'P': strncpy(par_file, optarg, 255); par_file[255] = '\0'; break; case 'F': fold_frequency = atof(optarg); use_polycos = 0; break; case 'C': cal = 1; use_polycos = 0; break; case 'u': raw_signed=0; break; case 'q': quiet=1; break; case 'h': default: usage(); exit(0); break; } } if (optind==argc) { usage(); exit(1); } /* If no polyco/par file given, default to polyco.dat */ if (use_polycos && (par_file[0]=='\0' && polyco_file[0]=='\0')) sprintf(polyco_file, "polyco.dat"); /* Open first file */ struct psrfits pf; strcpy(pf.basefilename, argv[optind]); pf.filenum = fnum_start; pf.tot_rows = pf.N = pf.T = pf.status = 0; pf.hdr.chan_dm = 0.0; // What if folding data that has been partially de-dispersed? pf.filename[0]='\0'; int rv = psrfits_open(&pf); if (rv) { fits_report_error(stderr, rv); exit(1); } /* Check any constraints */ if (pf.hdr.nbits!=8) { fprintf(stderr, "Only implemented for 8-bit data (read nbits=%d).\n", pf.hdr.nbits); exit(1); } /* Check for calfreq */ if (cal) { if (pf.hdr.cal_freq==0.0) { if (fold_frequency==0.0) { fprintf(stderr, "Error: Cal mode selected, but CAL_FREQ=0. " "Set cal frequency with -F\n"); exit(1); } else { pf.hdr.cal_freq = fold_frequency; } } else { fold_frequency = pf.hdr.cal_freq; } } /* Set up output file */ struct psrfits pf_out; memcpy(&pf_out, &pf, sizeof(struct psrfits)); if (source[0]!='\0') { strncpy(pf_out.hdr.source, source, 24); } else { strncpy(source, pf.hdr.source, 24); source[23]='\0'; } if (output_base[0]=='\0') { /* Set up default output filename */ if (start_time>0.0) sprintf(output_base, "%s_SP_%s_%5.5d_%5.5d_%4.4d_%3.3d%s", pf_out.hdr.backend, pf_out.hdr.source, pf_out.hdr.start_day, (int)pf_out.hdr.start_sec, fnum_start, (int)start_time, cal ? "_cal" : ""); else sprintf(output_base, "%s_SP_%s_%5.5d_%5.5d%s", pf_out.hdr.backend, pf_out.hdr.source, pf_out.hdr.start_day, (int)pf_out.hdr.start_sec, cal ? "_cal" : ""); } strcpy(pf_out.basefilename, output_base); if (cal) { sprintf(pf_out.hdr.obs_mode, "CAL"); sprintf(pf_out.hdr.cal_mode, "SYNC"); } else sprintf(pf_out.hdr.obs_mode, "PSR"); strncpy(pf_out.fold.parfile,par_file,255); pf_out.fold.parfile[255]='\0'; pf_out.fptr = NULL; pf_out.filenum=0; pf_out.status=0; pf_out.hdr.nbin=nbin; pf_out.sub.FITS_typecode = TFLOAT; pf_out.sub.bytes_per_subint = sizeof(float) * pf_out.hdr.nchan * pf_out.hdr.npol * pf_out.hdr.nbin; pf_out.multifile = 1; pf_out.quiet = 1; pf_out.rows_per_file = npulse_per_file; rv = psrfits_create(&pf_out); if (rv) { fits_report_error(stderr, rv); exit(1); } /* Alloc data buffers */ pf.sub.dat_freqs = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf_out.sub.dat_freqs = pf.sub.dat_freqs; pf.sub.dat_weights = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf_out.sub.dat_weights = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf.sub.dat_offsets = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf_out.sub.dat_offsets = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf.sub.dat_scales = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf_out.sub.dat_scales = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf_out.sub.data = (unsigned char *)malloc(pf_out.sub.bytes_per_subint); /* Output scale/offset */ int i, j, ipol, ichan; float offset_uv=0.0; // Extra cross-term offset for GUPPI if (strcmp("GUPPI",pf.hdr.backend)==0) { offset_uv=0.5; fprintf(stderr, "Found backend=GUPPI, setting offset_uv=%f\n", offset_uv); } // TODO: copy these from the input file for (ipol=0; ipol<pf.hdr.npol; ipol++) { for (ichan=0; ichan<pf.hdr.nchan; ichan++) { float offs = 0.0; if (ipol>1) offs = offset_uv; pf_out.sub.dat_scales[ipol*pf.hdr.nchan + ichan] = 1.0; pf_out.sub.dat_offsets[ipol*pf.hdr.nchan + ichan] = offs; } } for (i=0; i<pf.hdr.nchan; i++) { pf_out.sub.dat_weights[i]=1.0; } /* Read or make polycos */ int npc=0, ipc=0; struct polyco *pc = NULL; if (use_polycos) { if (polyco_file[0]=='\0') { /* Generate from par file */ npc = make_polycos(par_file, &pf.hdr, source, &pc); if (npc<=0) { fprintf(stderr, "Error generating polycos.\n"); exit(1); } printf("Auto-generated %d polycos, src=%s\n", npc, source); } else { /* Read from polyco file */ FILE *pcfile = fopen(polyco_file, "r"); if (pcfile==NULL) { fprintf(stderr, "Couldn't open polyco file.\n"); exit(1); } npc = read_all_pc(pcfile, &pc); if (npc==0) { fprintf(stderr, "Error parsing polyco file.\n"); exit(1); } fclose(pcfile); } } else { // Const fold period mode, generate a fake polyco? pc = (struct polyco *)malloc(sizeof(struct polyco)); sprintf(pc[0].psr, "CONST"); pc[0].mjd = (int)pf.hdr.MJD_epoch; pc[0].fmjd = fmod(pf.hdr.MJD_epoch,1.0); pc[0].rphase = 0.0; pc[0].f0 = fold_frequency; pc[0].nsite = 0; // Does this matter? pc[0].nmin = 24 * 60; pc[0].nc = 1; pc[0].rf = pf.hdr.fctr; pc[0].c[0] = 0.0; pc[0].used = 0; npc = 1; } int *pc_written = (int *)malloc(sizeof(int) * npc); for (i=0; i<npc; i++) pc_written[i]=0; /* Set up fold buf */ struct foldbuf fb; fb.nchan = pf.hdr.nchan; fb.npol = pf.hdr.npol; fb.nbin = pf_out.hdr.nbin; malloc_foldbuf(&fb); clear_foldbuf(&fb); struct fold_args fargs; fargs.data = (char *)malloc(sizeof(char)*pf.sub.bytes_per_subint); fargs.fb = &fb; fargs.nsamp = 1; fargs.tsamp = pf.hdr.dt; fargs.raw_signed = raw_signed; /* Main loop */ rv=0; int imjd; double fmjd, fmjd0=0, fmjd_samp, fmjd_epoch; long long cur_pulse=0, last_pulse=0; double psr_freq=0.0; int first_loop=1, first_data=1, sampcount=0, last_filenum=0; int bytes_per_sample = pf.hdr.nchan * pf.hdr.npol; signal(SIGINT, cc); while (run) { /* Read data block */ pf.sub.data = (unsigned char *)fargs.data; rv = psrfits_read_subint(&pf); if (rv) { if (rv==FILE_NOT_OPENED) rv=0; // Don't complain on file not found run=0; break; } /* If we've passed final file, exit */ if (fnum_end && pf.filenum>fnum_end) { run=0; break; } /* Get start date, etc */ imjd = (int)pf.hdr.MJD_epoch; fmjd = (double)(pf.hdr.MJD_epoch - (long double)imjd); fmjd += (pf.sub.offs-0.5*pf.sub.tsubint)/86400.0; /* Select polyco set. * We'll assume same one is valid for whole data block. */ if (use_polycos) { ipc = select_pc(pc, npc, source, imjd, fmjd); //ipc = select_pc(pc, npc, NULL, imjd, fmjd); if (ipc<0) { fprintf(stderr, "No matching polycos (src=%s, imjd=%d, fmjd=%f)\n", source, imjd, fmjd); break; } } else { ipc = 0; } pc[ipc].used = 1; // Mark this polyco set as used for folding /* First time stuff */ if (first_loop) { fmjd0 = fmjd; psr_phase(&pc[ipc], imjd, fmjd, NULL, &last_pulse); pf_out.sub.offs=0.0; first_loop=0; for (i=0; i<pf.hdr.nchan; i++) { pf_out.sub.dat_weights[i]=pf.sub.dat_weights[i]; } last_filenum = pf_out.filenum; } /* Check to see if its time to process data */ if (start_time>0.0) { double cur_time = (fmjd - fmjd0) * 86400.0; if (cur_time<start_time) continue; } if (first_data) { psr_phase(&pc[ipc], imjd, fmjd, NULL, &last_pulse); first_data=0; } /* Check to see if we're done */ if (process_time>0.0) { double cur_time = (fmjd - fmjd0) * 86400.0; if (cur_time > start_time + process_time) { run=0; break; } } /* for singlepulse: loop over samples, output a new subint * whenever pulse number increases. */ for (i=0; i<pf.hdr.nsblk; i++) { /* Keep track of timestamp */ // TODO also pointing stuff? fmjd_samp = fmjd + i*pf.hdr.dt/86400.0; pf_out.sub.offs += pf.sub.offs - 0.5*pf.sub.tsubint + i*pf.hdr.dt; sampcount++; /* Calc current pulse number */ psr_phase(&pc[ipc], imjd, fmjd_samp, &psr_freq, &cur_pulse); /* TODO: deal with scale/offset? */ /* Fold this sample */ fargs.pc = &pc[ipc]; fargs.imjd = imjd; fargs.fmjd = fmjd_samp; rv = fold_8bit_power(fargs.pc, fargs.imjd, fargs.fmjd, fargs.data + i*bytes_per_sample, fargs.nsamp, fargs.tsamp, fargs.raw_signed, fargs.fb); if (rv!=0) { fprintf(stderr, "Fold error.\n"); exit(1); } /* See if integration needs to be written, etc */ if (cur_pulse > last_pulse) { /* Figure out timestamp */ pf_out.sub.offs /= (double)sampcount; pf_out.sub.tsubint = 1.0/psr_freq; fmjd_epoch = fmjd0 + pf_out.sub.offs/86400.0; /* Transpose, output subint */ normalize_transpose_folds((float *)pf_out.sub.data, &fb); psrfits_write_subint(&pf_out); /* If file incremented, clear polyco flags */ if (pf_out.filenum > last_filenum) for (j=0; j<npc; j++) pc_written[j]=0; /* Write this polyco if needed */ if (pc_written[ipc]==0) { psrfits_write_polycos(&pf_out, pc, npc); pc_written[ipc] = 1; } /* Check for write errors */ if (pf_out.status) { fprintf(stderr, "Error writing subint.\n"); fits_report_error(stderr, pf_out.status); exit(1); } /* Clear counters, avgs */ clear_foldbuf(&fb); pf_out.sub.offs = 0.0; sampcount=0; last_pulse = cur_pulse; last_filenum = pf_out.filenum; } } /* Progress report */ if (!quiet) { printf("\rFile %d %5.1f%%", pf.filenum, 100.0 * (float)(pf.rownum-1)/(float)pf.rows_per_file); fflush(stdout); } } psrfits_close(&pf_out); psrfits_close(&pf); if (rv) { fits_report_error(stderr, rv); } exit(0); }
int main(int argc, char *argv[]) { int ii, ipol, nc = 0, ncnp = 0, gpubps = 0, status = 0, statsum = 0; int fnum_start = 1, fnum_end = 0; int numprocs, numbands, myid, baddata = 0, droppedrow = 0; int *counts, *offsets; unsigned char *tmpbuf = NULL; struct psrfits pf; struct { double value; int index; } offs_in, offs_out; char hostname[256]; char vegas_base_dir[256] = "\0"; char output_base[256] = "\0"; int starthpc = 0; int reverse = 0; MPI_Status mpistat; /* Cmd line */ static struct option long_opts[] = { {"output", 1, NULL, 'o'}, {"initial", 1, NULL, 'i'}, {"final", 1, NULL, 'f'}, {"vegas", 1, NULL, 'V'}, {"starthpc",1, NULL, 's'}, {"reverse" ,0, NULL, 'r'}, {0,0,0,0} }; int opt, opti; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myid); numbands = numprocs - 1; // Process the command line while ((opt=getopt_long(argc,argv,"o:i:f:V:s:r",long_opts,&opti))!=-1) { switch (opt) { case 'o': strncpy(output_base, optarg, 255); output_base[255]='\0'; break; case 'i': fnum_start = atoi(optarg); break; case 'f': fnum_end = atoi(optarg); break; case 'V': strcpy(vegas_base_dir, optarg); break; case 's': starthpc = atoi(optarg); break; case 'r': reverse = 1; break; default: if (myid==0) usage(); MPI_Finalize(); exit(0); break; } } if (optind==argc) { if (myid==0) usage(); MPI_Finalize(); exit(1); } if (myid == 0) { // Master proc only printf("\n\n"); printf(" MPI Search-mode PSRFITs Combiner\n"); printf(" by Scott M. Ransom\n\n"); } // Determine the hostnames of the processes { if (gethostname(hostname, 255) < 0) strcpy(hostname, "unknown"); MPI_Barrier(MPI_COMM_WORLD); if (myid == 0) printf("\n"); fflush(NULL); for (ii = 0 ; ii < numprocs ; ii++) { MPI_Barrier(MPI_COMM_WORLD); if (myid == ii) printf("Process %3d is on machine %s\n", myid, hostname); fflush(NULL); MPI_Barrier(MPI_COMM_WORLD); } MPI_Barrier(MPI_COMM_WORLD); fflush(NULL); } // Basefilenames for the GPU nodes if (myid > 0) { // Default to GUPPI mode if (vegas_base_dir[0]=='\0') sprintf(pf.basefilename, "/data/gpu/partial/%s/%s", hostname, argv[optind]); // VEGAS mode else { int hpcidx; if (reverse) hpcidx = starthpc - myid + 1; else hpcidx = myid + starthpc - 1; sprintf(pf.basefilename, "%s/vegas-hpc%d-bdata1/%s", vegas_base_dir, hpcidx, argv[optind]); printf("**********: hostname = %s, myid = %d, datamnt = %d, basename=%s\n", hostname, myid, hpcidx, pf.basefilename); } } // Initialize some key parts of the PSRFITS structure pf.tot_rows = pf.N = pf.T = pf.status = 0; pf.filenum = fnum_start; pf.filename[0] = '\0'; pf.filenames = NULL; pf.numfiles = 0; if (myid == 1) { FILE *psrfitsfile; char hdr[HDRLEN], filenm[200]; // Read the header info sprintf(filenm, "%s_0001.fits", pf.basefilename); psrfitsfile = fopen(filenm, "r"); fread(&hdr, 1, HDRLEN, psrfitsfile); fclose(psrfitsfile); // Send the header to the master proc MPI_Send(hdr, HDRLEN, MPI_CHAR, 0, 0, MPI_COMM_WORLD); } else if (myid == 0) { FILE *psrfitsfile; char hdr[HDRLEN], tmpfilenm[80]; // Receive the header info from proc 1 MPI_Recv(hdr, HDRLEN, MPI_CHAR, 1, 0, MPI_COMM_WORLD, &mpistat); // Now write that header to a temp file strcpy(tmpfilenm, "mpi_merge_psrfits.XXXXXX"); mkstemp(tmpfilenm); psrfitsfile = fopen(tmpfilenm, "w"); fwrite(&hdr, 1, HDRLEN, psrfitsfile); fclose(psrfitsfile); pf.filenames = (char **)malloc(sizeof(char *)); pf.filenames[0] = tmpfilenm; pf.basefilename[0]='\0'; pf.filenum = 0; pf.numfiles = 1; // And read the key information into a PSRFITS struct status = psrfits_open(&pf); status = psrfits_close(&pf); free(pf.filenames); remove(tmpfilenm); // Now create the output PSTFITS file if (output_base[0]=='\0') { /* Set up default output filename */ strcpy(output_base, argv[optind]); } strcpy(pf.basefilename, output_base); pf.multifile = 1; pf.filenum = 0; pf.numfiles = 0; pf.filename[0] = '\0'; pf.filenames = NULL; nc = pf.hdr.nchan; ncnp = pf.hdr.nchan * pf.hdr.npol; gpubps = pf.sub.bytes_per_subint; pf.hdr.orig_nchan *= numbands; pf.hdr.nchan *= numbands; pf.hdr.fctr = pf.hdr.fctr - 0.5 * pf.hdr.BW + numbands/2.0 * pf.hdr.BW; pf.hdr.BW *= numbands; pf.sub.bytes_per_subint *= numbands; long long filelen = 40 * (1L<<30); // In GB pf.rows_per_file = filelen / pf.sub.bytes_per_subint; status = psrfits_create(&pf); // For in-memory transpose of data tmpbuf = (unsigned char *)malloc(pf.sub.bytes_per_subint); } // Open the input PSRFITs files for real if (myid > 0) { status = psrfits_open(&pf); nc = pf.hdr.nchan; ncnp = pf.hdr.nchan * pf.hdr.npol; gpubps = pf.sub.bytes_per_subint; } // Alloc data buffers for the PSRFITS files pf.sub.dat_freqs = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf.sub.dat_weights = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf.sub.dat_offsets = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf.sub.dat_scales = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf.sub.data = (unsigned char *)malloc(pf.sub.bytes_per_subint); pf.sub.rawdata = pf.sub.data; // Counts and offsets for MPI_Gatherv counts = (int *)malloc(sizeof(int) * numprocs); offsets = (int *)malloc(sizeof(int) * numprocs); counts[0] = offsets[0] = 0; // master sends nothing // Now loop over the rows (i.e. subints)... do { MPI_Barrier(MPI_COMM_WORLD); // Read the current subint from each of the "slave" nodes if ((myid > 0) && (!baddata)) { status = psrfits_read_subint(&pf); if (status) { pf.sub.offs = FLAG; // High value so it won't be min if (pf.rownum > pf.rows_per_file) { // Shouldn't be here unless opening of new file failed... printf("Proc %d: Can't open next file. Setting status=114.\n", myid); status = 114; } } } else { // Root process pf.sub.offs = FLAG; // High value so it won't be min } // Find the minimum value of OFFS_SUB to see if we dropped a row offs_in.value = pf.sub.offs; offs_in.index = myid; MPI_Allreduce(&offs_in, &offs_out, 1, MPI_DOUBLE_INT, MPI_MINLOC, MPI_COMM_WORLD); // If all procs are returning the FLAG value, break. if (offs_out.value==FLAG) break; // Identify dropped rows if ((myid > 0) && (!status) && (!baddata) && (pf.sub.offs > (offs_out.value + 0.1 * pf.sub.tsubint))) { printf("Proc %d, row %d: Dropped a row. Filling with zeros.\n", myid, pf.rownum); droppedrow = 1; } if (myid > 0) { // Ignore errors for moving past EOF (107), read errors (108) // and missing files (114) if (droppedrow || status==108 || ((myid > 0) && (status==114 || status==107) && (!baddata))) { if (status) printf("Proc %d, row %d: Ignoring CFITSIO error %d. Filling with zeros.\n", myid, pf.rownum, status); // Set the data and the weights to all zeros for (ii = 0 ; ii < pf.hdr.nchan ; ii++) pf.sub.dat_weights[ii] = 0.0; for (ii = 0 ; ii < pf.sub.bytes_per_subint ; ii++) pf.sub.data[ii] = 0; // And the scales and offsets to nominal values 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; } // reset the status to 0 and allow going to next row if (status==114 || status==107) { baddata = 1; } if (status==108) { // Try reading the next row... pf.rownum++; pf.tot_rows++; pf.N += pf.hdr.nsblk; pf.T = pf.N * pf.hdr.dt; } if (droppedrow) { // We want to read the current row again... pf.rownum--; pf.tot_rows--; pf.N -= pf.hdr.nsblk; pf.T = pf.N * pf.hdr.dt; droppedrow = 0; // reset } status = 0; } } // If we've passed final file, exit if (fnum_end && pf.filenum > fnum_end) break; // Combine statuses of all nodes by summing.... MPI_Allreduce(&status, &statsum, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); if (statsum) break; if (myid == offs_out.index) { // Send all of the non-band-specific parts to master MPI_Send(&pf.sub.tsubint, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.offs, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.lst, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.ra, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.dec, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.glon, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.glat, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.feed_ang, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.pos_ang, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.par_ang, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.tel_az, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); MPI_Send(&pf.sub.tel_zen, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); } else if (myid == 0) { // Receive all of the non-data parts MPI_Recv(&pf.sub.tsubint, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.offs, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.lst, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.ra, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.dec, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.glon, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.glat, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.feed_ang, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.pos_ang, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.par_ang, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.tel_az, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); MPI_Recv(&pf.sub.tel_zen, 1, MPI_DOUBLE, offs_out.index, 0, MPI_COMM_WORLD, &mpistat); } // Now gather the vector quantities... // Vectors of length nchan for (ii = 1 ; ii < numprocs ; ii++) { counts[ii] = nc; offsets[ii] = (ii - 1) * nc; } status = MPI_Gatherv(pf.sub.dat_freqs, nc, MPI_FLOAT, pf.sub.dat_freqs, counts, offsets, MPI_FLOAT, 0, MPI_COMM_WORLD); status = MPI_Gatherv(pf.sub.dat_weights, nc, MPI_FLOAT, pf.sub.dat_weights, counts, offsets, MPI_FLOAT, 0, MPI_COMM_WORLD); // Vectors of length nchan * npol for (ipol=0; ipol < pf.hdr.npol; ipol++) { for (ii = 1 ; ii < numprocs ; ii++) { counts[ii] = nc; offsets[ii] = ipol*nc*numbands + (ii - 1) * nc; } status = MPI_Gatherv(pf.sub.dat_offsets+(ipol*nc), nc, MPI_FLOAT, pf.sub.dat_offsets, counts, offsets, MPI_FLOAT, 0, MPI_COMM_WORLD); status = MPI_Gatherv(pf.sub.dat_scales+(ipol*nc), nc, MPI_FLOAT, pf.sub.dat_scales, counts, offsets, MPI_FLOAT, 0, MPI_COMM_WORLD); } // Vectors of length pf.sub.bytes_per_subint for the raw data for (ii = 1 ; ii < numprocs ; ii++) { counts[ii] = gpubps; offsets[ii] = (ii - 1) * gpubps; } status = MPI_Gatherv(pf.sub.data, gpubps, MPI_UNSIGNED_CHAR, tmpbuf, counts, offsets, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD); // Reorder and write the new row to the output file if (myid == 0) { reorder_data(pf.sub.data, tmpbuf, numbands, pf.hdr.nsblk, pf.hdr.npol, nc); status = psrfits_write_subint(&pf); } } while (statsum == 0); // Free the arrays free(pf.sub.dat_freqs); free(pf.sub.dat_weights); free(pf.sub.dat_offsets); free(pf.sub.dat_scales); free(pf.sub.data); if (myid == 0) free(tmpbuf); free(counts); free(offsets); // Close the files and finalize things status = psrfits_close(&pf); MPI_Finalize(); exit(0); }
int main(int argc, char *argv[]) { /* Cmd line */ static struct option long_opts[] = { {"frontend", 1, NULL, 'F'}, {"offset", 0, NULL, 'o'}, {"srcname", 1, NULL, 's'}, }; int ii; double dtmp; char filename[256], *adr; struct psrfits pf; int c1,c2; double c3; int opt, opti; int scan_id, beam_id; bool have_Stokes = false; bool have_chan_offset = false; bool have_frontend = false; char frontend[3]; bool have_srcname = false; char srcname[24]; while ((opt=getopt_long(argc,argv,"ob:t:j:i:F:s:p:P:F:CuU:SAqh",long_opts,&opti))!=-1) { switch (opt) { case 'F': have_frontend = true; strncpy(frontend, optarg, 3); break; case 'o': have_chan_offset = true; break; case 's': have_srcname = true; strncpy(srcname, optarg, 24); break; case 'S': have_Stokes = true; break; case 'h': default: usage(); exit(0); break; } } // Only set the basefilename and not "filename" // Also, fptr will be set by psrfits_create_searchmode() FILE *pfi; strcpy(filename, argv[optind]); printf("Filename = %s\n", filename); // Read filterbank if((pfi=fopen(filename,"r"))==NULL) { printf("Cannot open file %s\n", filename); exit(-2); } else { printf("Opening file %s\n", filename); } /* try to read the header */ long long header_size, numsamps; header iheader; if (!(header_size=read_header(pfi,&iheader))) { printf("Error reading header\n"); exit(-2); } //printf("header_size = %lld\n", header_size); // Get the number of samples numsamps=nsamples(filename, header_size, &iheader); //printf("numsamps = %lld ra=%lf dec=%lf\n", numsamps, iheader.src_raj, iheader.src_dej); //fflush(stdout); pf.filenum = 0; // This is the crucial one to set to initialize things pf.rows_per_file = 4000; // Need to set this based on PSRFITS_MAXFILELEN // Now set values for our hdrinfo structure pf.hdr.scanlen = 3600; // in sec strcpy(pf.hdr.observer, "Observer"); strcpy(pf.hdr.telescope, "Effelsberg"); strcpy(pf.hdr.obs_mode, "SEARCH"); strcpy(pf.hdr.backend, "PFFTS"); strncpy(pf.hdr.source, iheader.source_name, 24); strcpy(pf.hdr.frontend, "LBand"); strcpy(pf.hdr.project_id, "HTRUN"); strcpy(pf.hdr.date_obs, "2010-01-01T05:15:30.000"); strcpy(pf.hdr.poln_type, "LIN"); strcpy(pf.hdr.poln_order, "IQUV"); strcpy(pf.hdr.track_mode, "TRACK"); strcpy(pf.hdr.cal_mode, "OFF"); strcpy(pf.hdr.feed_mode, "FA"); //printf("filename = %s\n", filename); fflush(stdout); if(strstr(filename,"/") != NULL) { adr=(char *)strrchr(filename,'/')+1; sprintf(pf.filename,"%s",adr); } else strncpy(pf.filename, filename, 80); //printf("filename = %s\n", pf.filename); fflush(stdout); sscanf(pf.filename, "%d_%d_%d_%dbit.fil", &scan_id, &c1, &beam_id, &c2); pf.hdr.dt = iheader.tsamp; pf.hdr.fctr = iheader.fch1+iheader.foff*iheader.nchans/2. - iheader.foff/2.; if (have_chan_offset) pf.hdr.fctr += iheader.foff/2.; pf.hdr.BW = iheader.nchans * iheader.foff; angle_split(iheader.src_raj, &c1, &c2, &c3); sprintf(pf.hdr.ra_str, "%2.2d:%2.2d:%07.4lf", c1, c2, c3); angle_split(iheader.src_dej, &c1, &c2, &c3); sprintf(pf.hdr.dec_str, "%2.2d:%2.2d:%07.4lf", c1, c2, c3); pf.hdr.azimuth = iheader.az_start; pf.hdr.zenith_ang = iheader.za_start; pf.hdr.beam_FWHM = 0.25; pf.hdr.start_lst = 0.0; pf.hdr.start_sec = 0.0; pf.hdr.start_day = 55000; pf.hdr.scan_number = scan_id; pf.hdr.rcvr_polns = 2; pf.hdr.summed_polns = 0; pf.hdr.offset_subint = 0; pf.hdr.nchan = iheader.nchans; pf.hdr.orig_nchan = pf.hdr.nchan; pf.hdr.orig_df = pf.hdr.df = pf.hdr.BW / pf.hdr.nchan; pf.hdr.nbits = iheader.nbits; pf.hdr.npol = iheader.nifs; pf.hdr.onlyI = 0; if (pf.hdr.npol==1) pf.hdr.onlyI = 1; pf.hdr.chan_dm = 0.0; pf.hdr.fd_hand = 1; pf.hdr.fd_sang = 0; pf.hdr.fd_xyph = 0; pf.hdr.be_phase = 1; pf.hdr.ibeam = beam_id; pf.hdr.nsblk = 2048; pf.hdr.MJD_epoch = iheader.tstart; // Note the "L" for long double pf.hdr.ds_time_fact = 1; pf.hdr.ds_freq_fact = 1; //sprintf(pf.basefilename, "%s_%04d_%02d", pf.hdr.backend, pf.hdr.scan_number, pf.hdr.ibeam); //psrfits_create(&pf); // Now set values for our subint structure pf.sub.tsubint = pf.hdr.nsblk * pf.hdr.dt; pf.tot_rows = 0.0; pf.sub.offs = (pf.tot_rows + 0.5) * pf.sub.tsubint; pf.sub.lst = pf.hdr.start_lst; pf.sub.ra = pf.hdr.ra2000; pf.sub.dec = pf.hdr.dec2000; // GD slaEqgal(pf.hdr.ra2000*DEGTORAD, pf.hdr.dec2000*DEGTORAD, //&pf.sub.glon, &pf.sub.glat); //pf.sub.glon *= RADTODEG; //pf.sub.glat *= RADTODEG; pf.sub.feed_ang = 0.0; pf.sub.pos_ang = 0.0; pf.sub.par_ang = 0.0; pf.sub.tel_az = pf.hdr.azimuth; pf.sub.tel_zen = pf.hdr.zenith_ang; pf.sub.bytes_per_subint = (pf.hdr.nbits * pf.hdr.nchan * pf.hdr.npol * pf.hdr.nsblk) / 8; if (pf.hdr.nbits==32) pf.sub.FITS_typecode = TFLOAT; else pf.sub.FITS_typecode = TBYTE; // 11 = byte // if (have_frontend) { if (strncmp(frontend,"S36",3)==0) { strcpy(pf.hdr.backend, "PSRIX"); strcpy(pf.hdr.frontend, "S36"); strcpy(pf.hdr.poln_type, "CIRC"); strcpy(pf.hdr.poln_order, "AABBCRCI"); pf.hdr.fd_hand = -1; // To conform PA and Stokes V to PSR/IEEE } else if (strncmp(frontend,"S60",3)==0) { strcpy(pf.hdr.backend, "PSRIX"); strcpy(pf.hdr.frontend, "S60"); strcpy(pf.hdr.poln_type, "CIRC"); strcpy(pf.hdr.poln_order, "AABBCRCI"); } else if (strncmp(frontend,"S110",3)==0) { strcpy(pf.hdr.backend, "PSRIX"); strcpy(pf.hdr.frontend, "S110"); strcpy(pf.hdr.poln_type, "CIRC"); strcpy(pf.hdr.poln_order, "AABBCRCI"); pf.hdr.be_phase = -1; // To conform Stokes V to PSR/IEEE } else if (strncmp(frontend,"S45",3)==0) { strcpy(pf.hdr.backend, "PSRIX"); strcpy(pf.hdr.frontend, "S45"); strcpy(pf.hdr.poln_type, "LIN"); strcpy(pf.hdr.poln_order, "AABBCRCI"); pf.hdr.be_phase = -1; // To conform Stokes V to PSR/IEEE } else {printf("Frontend %s not recognised\n", frontend);} } if (have_srcname) strncpy(pf.hdr.source, srcname, 24); if (have_Stokes) strcpy(pf.hdr.poln_order, "IQUV"); if (strncmp(pf.hdr.backend, "PFFTS",5)==0) sprintf(pf.basefilename, "%s_%04d_%02d", pf.hdr.backend, pf.hdr.scan_number, pf.hdr.ibeam); else sprintf(pf.basefilename, "%s_%s_%5d_%d", pf.hdr.backend, pf.hdr.source, (int) pf.hdr.MJD_epoch, (int) pf.hdr.fctr); psrfits_create(&pf); // Create and initialize the subint arrays pf.sub.dat_freqs = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf.sub.dat_weights = (float *)malloc(sizeof(float) * pf.hdr.nchan); dtmp = pf.hdr.fctr - 0.5 * pf.hdr.BW + 0.5 * pf.hdr.df; for (ii = 0 ; ii < pf.hdr.nchan ; ii++) { pf.sub.dat_freqs[ii] = dtmp + ii * pf.hdr.df; pf.sub.dat_weights[ii] = 1.0; } pf.sub.dat_offsets = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf.sub.dat_scales = (float *)malloc(sizeof(float) * 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 what you would update for each time sample (likely just // adjusting the pointer to point to your data) pf.sub.rawdata = (unsigned char *)malloc(pf.sub.bytes_per_subint); // Here is the real data-writing loop do { // Update the pf.sub entries here for each subint // as well as the pf.sub.data pointer fread(pf.sub.rawdata, pf.sub.bytes_per_subint, 1, pfi); pf.sub.offs = (pf.tot_rows + 0.5) * pf.sub.tsubint; psrfits_write_subint(&pf); } while (pf.T < pf.hdr.scanlen && !feof (pfi) && !pf.status); // Close the last file and cleanup fits_close_file(pf.fptr, &(pf.status)); free(pf.sub.dat_freqs); free(pf.sub.dat_weights); free(pf.sub.dat_offsets); free(pf.sub.dat_scales); free(pf.sub.rawdata); printf("Done. Wrote %d subints (%f sec) in %d files. status = %d\n", pf.tot_rows, pf.T, pf.filenum, pf.status); exit(0); }
int main(int argc, char *argv[]) { /* Cmd line */ static struct option long_opts[] = { {"output", 1, NULL, 'o'}, {"nbin", 1, NULL, 'b'}, {"tsub", 1, NULL, 't'}, {"nthread", 1, NULL, 'j'}, {"initial", 1, NULL, 'i'}, {"final", 1, NULL, 'f'}, {"src", 1, NULL, 's'}, {"polyco", 1, NULL, 'p'}, {"parfile", 1, NULL, 'P'}, {"foldfreq",1, NULL, 'F'}, {"cal", 0, NULL, 'C'}, {"unsigned",0, NULL, 'u'}, {"nunsigned",1, NULL, 'U'}, {"split", 1, NULL, 'S'}, {"apply", 0, NULL, 'A'}, {"quiet", 0, NULL, 'q'}, {"help", 0, NULL, 'h'}, {0,0,0,0} }; int opt, opti; int nbin=256, nthread=4, fnum_start=1, fnum_end=0; int quiet=0, raw_signed=1, use_polycos=1, cal=0, apply_scale=0; double split_size_gb = 1.0; double tfold = 60.0; double fold_frequency=0.0; char output_base[256] = ""; char polyco_file[256] = ""; char par_file[256] = ""; char source[24]; source[0]='\0'; while ((opt=getopt_long(argc,argv,"o:b:t:j:i:f:s:p:P:F:CuU:S:Aqh",long_opts,&opti))!=-1) { switch (opt) { case 'o': strncpy(output_base, optarg, 255); output_base[255]='\0'; break; case 'b': nbin = atoi(optarg); break; case 't': tfold = atof(optarg); break; case 'j': nthread = atoi(optarg); break; case 'i': fnum_start = atoi(optarg); break; case 'f': fnum_end = atoi(optarg); break; case 's': strncpy(source, optarg, 24); source[23]='\0'; break; case 'p': strncpy(polyco_file, optarg, 255); polyco_file[255]='\0'; use_polycos = 1; break; case 'P': strncpy(par_file, optarg, 255); par_file[255] = '\0'; break; case 'F': fold_frequency = atof(optarg); use_polycos = 0; break; case 'C': cal = 1; use_polycos = 0; break; case 'u': raw_signed=0; break; case 'U': raw_signed = 4 - atoi(optarg); break; case 'S': split_size_gb = atof(optarg); break; case 'A': apply_scale = 1; break; case 'q': quiet=1; break; case 'h': default: usage(); exit(0); break; } } if (optind==argc) { usage(); exit(1); } /* If no polyco/par file given, default to polyco.dat */ if (use_polycos && (par_file[0]=='\0' && polyco_file[0]=='\0')) sprintf(polyco_file, "polyco.dat"); /* Open first file */ struct psrfits pf; sprintf(pf.basefilename, argv[optind]); pf.filenum = fnum_start; pf.tot_rows = pf.N = pf.T = pf.status = 0; pf.hdr.chan_dm = 0.0; // What if folding data that has been partially de-dispersed? pf.filename[0]='\0'; int rv = psrfits_open(&pf); if (rv) { fits_report_error(stderr, rv); exit(1); } /* Check any constraints */ if (pf.hdr.nbits!=8) { fprintf(stderr, "Only implemented for 8-bit data (read nbits=%d).\n", pf.hdr.nbits); exit(1); } /* Check for calfreq */ if (cal) { if (pf.hdr.cal_freq==0.0) { if (fold_frequency==0.0) { fprintf(stderr, "Error: Cal mode selected, but CAL_FREQ=0. " "Set cal frequency with -F\n"); exit(1); } else { pf.hdr.cal_freq = fold_frequency; } } else { fold_frequency = pf.hdr.cal_freq; } } /* Set up output file */ struct psrfits pf_out; memcpy(&pf_out, &pf, sizeof(struct psrfits)); if (source[0]!='\0') { strncpy(pf_out.hdr.source, source, 24); } else { strncpy(source, pf.hdr.source, 24); source[23]='\0'; } if (output_base[0]=='\0') { /* Set up default output filename */ sprintf(output_base, "%s_%s_%5.5d_%5.5d%s", pf_out.hdr.backend, pf_out.hdr.source, pf_out.hdr.start_day, (int)pf_out.hdr.start_sec, cal ? "_cal" : ""); } sprintf(pf_out.basefilename, output_base); if (cal) { sprintf(pf_out.hdr.obs_mode, "CAL"); sprintf(pf_out.hdr.cal_mode, "SYNC"); } else sprintf(pf_out.hdr.obs_mode, "PSR"); strncpy(pf_out.fold.parfile,par_file,255); pf_out.fold.parfile[255]='\0'; pf_out.fptr = NULL; pf_out.filenum=0; pf_out.status=0; pf_out.quiet=0; pf_out.hdr.nbin=nbin; pf_out.sub.FITS_typecode = TFLOAT; pf_out.sub.bytes_per_subint = sizeof(float) * pf_out.hdr.nchan * pf_out.hdr.npol * pf_out.hdr.nbin; if (split_size_gb > 0.0) { pf_out.multifile = 1; pf_out.rows_per_file = (int) (split_size_gb * (1024.0*1024.0*1024.0) / (double)pf_out.sub.bytes_per_subint); printf("Writing a maximum of %d subintegrations (~%.1f GB) per output file.\n", pf_out.rows_per_file, split_size_gb); } else { pf_out.multifile = 0; printf("Writing a single output file.\n"); } rv = psrfits_create(&pf_out); if (rv) { fits_report_error(stderr, rv); exit(1); } /* Alloc data buffers */ pf.sub.dat_freqs = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf_out.sub.dat_freqs = pf.sub.dat_freqs; pf.sub.dat_weights = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf_out.sub.dat_weights = (float *)malloc(sizeof(float) * pf.hdr.nchan); pf.sub.dat_offsets = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf_out.sub.dat_offsets = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf.sub.dat_scales = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf_out.sub.dat_scales = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); pf_out.sub.data = (unsigned char *)malloc(pf_out.sub.bytes_per_subint); /* Output scale/offset */ int i, ipol, ichan; float offset_uv=0.0; // Extra cross-term offset for GUPPI if (strcmp("GUPPI",pf.hdr.backend)==0 && apply_scale==0) { offset_uv=0.5; fprintf(stderr, "Found backend=GUPPI, setting offset_uv=%f\n", offset_uv); } // Initialize scale/output and weights. // These get copied from the input file later during the main loop. for (ipol=0; ipol<pf.hdr.npol; ipol++) { for (ichan=0; ichan<pf.hdr.nchan; ichan++) { float offs = 0.0; if (ipol>1) offs = offset_uv; pf_out.sub.dat_scales[ipol*pf.hdr.nchan + ichan] = 1.0; pf_out.sub.dat_offsets[ipol*pf.hdr.nchan + ichan] = offs; } } for (i=0; i<pf.hdr.nchan; i++) { pf_out.sub.dat_weights[i]=1.0; } /* Read or make polycos */ int npc=0, ipc=0; struct polyco *pc = NULL; if (use_polycos) { if (polyco_file[0]=='\0') { /* Generate from par file */ npc = make_polycos(par_file, &pf.hdr, source, &pc); if (npc<=0) { fprintf(stderr, "Error generating polycos.\n"); exit(1); } printf("Auto-generated %d polycos, src=%s\n", npc, source); } else { /* Read from polyco file */ FILE *pcfile = fopen(polyco_file, "r"); if (pcfile==NULL) { fprintf(stderr, "Couldn't open polyco file.\n"); exit(1); } npc = read_all_pc(pcfile, &pc); if (npc==0) { fprintf(stderr, "Error parsing polyco file.\n"); exit(1); } fclose(pcfile); } } else { // Const fold period mode, generate a fake polyco? pc = (struct polyco *)malloc(sizeof(struct polyco)); sprintf(pc[0].psr, "CONST"); pc[0].mjd = (int)pf.hdr.MJD_epoch; pc[0].fmjd = fmod(pf.hdr.MJD_epoch,1.0); pc[0].rphase = 0.0; pc[0].f0 = fold_frequency; pc[0].nsite = 0; // Does this matter? pc[0].nmin = 24 * 60; pc[0].nc = 1; pc[0].rf = pf.hdr.fctr; pc[0].c[0] = 0.0; pc[0].used = 0; npc = 1; } int *pc_written = (int *)malloc(sizeof(int) * npc); for (i=0; i<npc; i++) pc_written[i]=0; /* Alloc total fold buf */ struct foldbuf fb; fb.nchan = pf.hdr.nchan; fb.npol = pf.hdr.npol; fb.nbin = pf_out.hdr.nbin; malloc_foldbuf(&fb); clear_foldbuf(&fb); /* Set up thread management */ pthread_t *thread_id; struct fold_args *fargs; thread_id = (pthread_t *)malloc(sizeof(pthread_t) * nthread); fargs = (struct fold_args *)malloc(sizeof(struct fold_args) * nthread); for (i=0; i<nthread; i++) { thread_id[i] = 0; fargs[i].data = (char *)malloc(sizeof(char)*pf.sub.bytes_per_subint); fargs[i].fb = (struct foldbuf *)malloc(sizeof(struct foldbuf)); fargs[i].fb->nbin = pf_out.hdr.nbin; fargs[i].fb->nchan = pf.hdr.nchan; fargs[i].fb->npol = pf.hdr.npol; fargs[i].nsamp = pf.hdr.nsblk; fargs[i].tsamp = pf.hdr.dt; fargs[i].raw_signed=raw_signed; malloc_foldbuf(fargs[i].fb); clear_foldbuf(fargs[i].fb); fargs[i].scale = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); fargs[i].offset = (float *)malloc(sizeof(float) * pf.hdr.nchan * pf.hdr.npol); } /* Main loop */ rv=0; int imjd; double fmjd, fmjd0=0, fmjd_next=0, fmjd_epoch; double offs0=0, offs1=0; //double phase=0.0, freq=1.0; int first=1, subcount=0; int cur_thread = 0; signal(SIGINT, cc); while (run) { /* Read data block */ pf.sub.data = (unsigned char *)fargs[cur_thread].data; rv = psrfits_read_subint(&pf); if (rv) { if (rv==FILE_NOT_OPENED) rv=0; // Don't complain on file not found run=0; break; } /* If we've passed final file, exit */ if (fnum_end && pf.filenum>fnum_end) { run=0; break; } /* Get start date, etc */ imjd = (int)pf.hdr.MJD_epoch; fmjd = (double)(pf.hdr.MJD_epoch - (long double)imjd); fmjd += (pf.sub.offs-0.5*pf.sub.tsubint)/86400.0; /* First time stuff */ if (first) { fmjd0 = fmjd; fmjd_next = fmjd + tfold/86400.0; pf_out.sub.offs=0.0; offs0 = pf.sub.offs - 0.5*pf.sub.tsubint; offs1 = pf.sub.offs + 0.5*pf.sub.tsubint; first=0; for (i=0; i<pf.hdr.nchan; i++) { pf_out.sub.dat_weights[i]=pf.sub.dat_weights[i]; } } /* Keep track of timestamp */ // TODO also pointing stuff. pf_out.sub.offs += pf.sub.offs; subcount++; /* Update output block end time */ offs1 = pf.sub.offs + 0.5*pf.sub.tsubint; /* Select polyco set */ if (use_polycos) { ipc = select_pc(pc, npc, source, imjd, fmjd); //ipc = select_pc(pc, npc, NULL, imjd, fmjd); if (ipc<0) { fprintf(stderr, "No matching polycos (src=%s, imjd=%d, fmjd=%f)\n", source, imjd, fmjd); break; } } else { ipc = 0; } pc[ipc].used = 1; // Mark this polyco set as used for folding /* Copy scale/offset from input to output if we're not applying it */ if (apply_scale==0) { for (i=0; i<pf.hdr.nchan*pf.hdr.npol; i++) { pf_out.sub.dat_scales[i] = pf.sub.dat_scales[i]; pf_out.sub.dat_offsets[i] = pf.sub.dat_offsets[i]; } } /* Fold this subint */ fargs[cur_thread].pc = &pc[ipc]; fargs[cur_thread].imjd = imjd; fargs[cur_thread].fmjd = fmjd; rv = pthread_create(&thread_id[cur_thread], NULL, fold_8bit_power_thread, &fargs[cur_thread]); if (rv) { fprintf(stderr, "Thread creation error.\n"); exit(1); } if (apply_scale) { for (i=0; i<pf.hdr.nchan*pf.hdr.npol; i++) { fargs[cur_thread].scale[i] = pf.sub.dat_scales[i]; fargs[cur_thread].offset[i] = pf.sub.dat_offsets[i]; } } cur_thread++; /* Combine thread results if needed */ if (cur_thread==nthread || fmjd>fmjd_next) { /* Loop over active threads */ for (i=0; i<cur_thread; i++) { /* Wait for thread to finish */ rv = pthread_join(thread_id[i], NULL); if (rv) { fprintf(stderr, "Thread join error.\n"); exit(1); } /* Apply scale and offset here */ if (apply_scale) scale_offset_folds(fargs[i].fb, fargs[i].scale, fargs[i].offset); /* Combine its result into total fold */ accumulate_folds(&fb, fargs[i].fb); /* Reset thread info */ clear_foldbuf(fargs[i].fb); thread_id[i] = 0; } /* Reset active thread count */ cur_thread = 0; } /* See if integration needs to be written, etc */ if (fmjd > fmjd_next) { /* Figure out timestamp */ pf_out.sub.offs /= (double)subcount; pf_out.sub.tsubint = offs1 - offs0; fmjd_epoch = fmjd0 + pf_out.sub.offs/86400.0; /* // Don't need this stuff if we set EPOCHS=MIDTIME ipc = select_pc(pc, npc, pf.hdr.source, imjd, fmjd_epoch); if (ipc<0) { fprintf(stderr, "Polyco error, exiting.\n"); exit(1); } phase = psr_phase(&pc[ipc], imjd, fmjd_epoch, &freq); phase = fmod(phase, 1.0); pf_out.sub.offs -= phase/freq; // ref epoch needs 0 phase */ /* Transpose, output subint */ normalize_transpose_folds((float *)pf_out.sub.data, &fb); int last_filenum = pf_out.filenum; psrfits_write_subint(&pf_out); /* Check for write errors */ if (pf_out.status) { fprintf(stderr, "Error writing subint.\n"); fits_report_error(stderr, pf_out.status); exit(1); } /* Check if we started a new file */ if (pf_out.filenum!=last_filenum) { /* No polycos yet written to this file */ for (i=0; i<npc; i++) pc_written[i]=0; } /* Write the current polyco if needed */ if (pc_written[ipc]==0) { psrfits_write_polycos(&pf_out, &pc[ipc], 1); if (pf_out.status) { fprintf(stderr, "Error writing polycos.\n"); fits_report_error(stderr, pf_out.status); exit(1); } pc_written[ipc] = 1; } /* Clear counters, avgs */ clear_foldbuf(&fb); pf_out.sub.offs = 0.0; offs0 = pf.sub.offs - 0.5*pf.sub.tsubint; subcount=0; /* Set next output time */ fmjd_next = fmjd + tfold/86400.0; } /* Progress report */ if (!quiet) { printf("\rFile %d %5.1f%%", pf.filenum, 100.0 * (float)(pf.rownum-1)/(float)pf.rows_per_file); fflush(stdout); } } /* Join any running threads */ for (i=0; i<cur_thread; i++) if (thread_id[i]) pthread_join(thread_id[i], NULL); /* Remove polyco table in cal mode */ if (cal) { rv = psrfits_remove_polycos(&pf_out); if (rv) { fits_report_error(stderr, rv); } } psrfits_close(&pf_out); psrfits_close(&pf); if (rv) { fits_report_error(stderr, rv); } exit(0); }