int main(int argc, char *argv[]) { /* Any variable that begins with 't' means topocentric */ /* Any variable that begins with 'b' means barycentric */ FILE **outfiles = NULL; float **outdata; double dtmp, *dms, avgdm = 0.0, dsdt = 0, maxdm; double *dispdt, tlotoa = 0.0, blotoa = 0.0, BW_ddelay = 0.0; double max = -9.9E30, min = 9.9E30, var = 0.0, avg = 0.0; double *btoa = NULL, *ttoa = NULL, avgvoverc = 0.0; char obs[3], ephem[10], rastring[50], decstring[50]; long totnumtowrite, totwrote = 0, padwrote = 0, datawrote = 0; int *idispdt, **offsets; int ii, jj, numadded = 0, numremoved = 0, padding = 0, good_inputs = 1; int numbarypts = 0, numread = 0, numtowrite = 0; int padtowrite = 0, statnum = 0; int numdiffbins = 0, *diffbins = NULL, *diffbinptr = NULL, good_padvals = 0; double local_lodm; char *datafilenm, *outpath, *outfilenm, *hostname; struct spectra_info s; infodata idata; mask obsmask; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myid); #ifdef _OPENMP omp_set_num_threads(1); // Explicitly turn off OpenMP #endif set_using_MPI(); { FILE *hostfile; char tmpname[100]; int retval; hostfile = chkfopen("/etc/hostname", "r"); retval = fscanf(hostfile, "%s\n", tmpname); if (retval==0) { printf("Warning: error reading /etc/hostname on proc %d\n", myid); } hostname = (char *) calloc(strlen(tmpname) + 1, 1); memcpy(hostname, tmpname, strlen(tmpname)); fclose(hostfile); } /* Call usage() if we have no command line arguments */ if (argc == 1) { if (myid == 0) { Program = argv[0]; usage(); } MPI_Finalize(); exit(1); } make_maskbase_struct(); make_spectra_info_struct(); /* Parse the command line using the excellent program Clig */ cmd = parseCmdline(argc, argv); spectra_info_set_defaults(&s); // If we are zeroDMing, make sure that clipping is off. if (cmd->zerodmP) cmd->noclipP = 1; s.clip_sigma = cmd->clip; if (cmd->noclipP) { cmd->clip = 0.0; s.clip_sigma = 0.0; } if (cmd->ifsP) { // 0 = default or summed, 1-4 are possible also s.use_poln = cmd->ifs + 1; } if (!cmd->numoutP) cmd->numout = LONG_MAX; #ifdef DEBUG showOptionValues(); #endif if (myid == 0) { /* Master node only */ printf("\n\n"); printf(" Parallel Pulsar Subband De-dispersion Routine\n"); printf(" by Scott M. Ransom\n\n"); s.filenames = cmd->argv; s.num_files = cmd->argc; s.clip_sigma = cmd->clip; // -1 causes the data to determine if we use weights, scales, & // offsets for PSRFITS or flip the band for any data type where // we can figure that out with the data s.apply_flipband = (cmd->invertP) ? 1 : -1; s.apply_weight = (cmd->noweightsP) ? 0 : -1; s.apply_scale = (cmd->noscalesP) ? 0 : -1; s.apply_offset = (cmd->nooffsetsP) ? 0 : -1; s.remove_zerodm = (cmd->zerodmP) ? 1 : 0; if (RAWDATA) { if (cmd->filterbankP) s.datatype = SIGPROCFB; else if (cmd->psrfitsP) s.datatype = PSRFITS; else if (cmd->pkmbP) s.datatype = SCAMP; else if (cmd->bcpmP) s.datatype = BPP; else if (cmd->wappP) s.datatype = WAPP; else if (cmd->spigotP) s.datatype = SPIGOT; } else { // Attempt to auto-identify the data identify_psrdatatype(&s, 1); if (s.datatype==SIGPROCFB) cmd->filterbankP = 1; else if (s.datatype==PSRFITS) cmd->psrfitsP = 1; else if (s.datatype==SCAMP) cmd->pkmbP = 1; else if (s.datatype==BPP) cmd->bcpmP = 1; else if (s.datatype==WAPP) cmd->wappP = 1; else if (s.datatype==SPIGOT) cmd->spigotP = 1; else if (s.datatype==SUBBAND) insubs = 1; else { printf("\nError: Unable to identify input data files. Please specify type.\n\n"); good_inputs = 0; } } // So far we can only handle PSRFITS, filterbank, and subbands if (s.datatype!=PSRFITS && s.datatype!=SIGPROCFB && s.datatype!=SUBBAND) good_inputs = 0; // For subbanded data if (!RAWDATA) s.files = (FILE **)malloc(sizeof(FILE *) * s.num_files); if (good_inputs && (RAWDATA || insubs)) { char description[40]; psrdatatype_description(description, s.datatype); if (s.num_files > 1) printf("Reading %s data from %d files:\n", description, s.num_files); else printf("Reading %s data from 1 file:\n", description); for (ii = 0; ii < s.num_files; ii++) { printf(" '%s'\n", cmd->argv[ii]); if (insubs) s.files[ii] = chkfopen(s.filenames[ii], "rb"); } printf("\n"); if (RAWDATA) { read_rawdata_files(&s); print_spectra_info_summary(&s); spectra_info_to_inf(&s, &idata); } else { // insubs char *root, *suffix; cmd->nsub = s.num_files; s.N = chkfilelen(s.files[0], sizeof(short)); s.start_subint = gen_ivect(1); s.num_subint = gen_ivect(1); s.start_MJD = (long double *)malloc(sizeof(long double)); s.start_spec = (long long *)malloc(sizeof(long long)); s.num_spec = (long long *)malloc(sizeof(long long)); s.num_pad = (long long *)malloc(sizeof(long long)); s.start_spec[0] = 0L; s.start_subint[0] = 0; s.num_spec[0] = s.N; s.num_subint[0] = s.N / SUBSBLOCKLEN; s.num_pad[0] = 0L; s.padvals = gen_fvect(s.num_files); for (ii = 0 ; ii < ii ; ii++) s.padvals[ii] = 0.0; if (split_root_suffix(s.filenames[0], &root, &suffix) == 0) { printf("\nError: The input filename (%s) must have a suffix!\n\n", s.filenames[0]); exit(1); } if (strncmp(suffix, "sub", 3) == 0) { char *tmpname; tmpname = calloc(strlen(root) + 10, 1); sprintf(tmpname, "%s.sub", root); readinf(&idata, tmpname); free(tmpname); strncpy(s.telescope, idata.telescope, 40); strncpy(s.backend, idata.instrument, 40); strncpy(s.observer, idata.observer, 40); strncpy(s.source, idata.object, 40); s.ra2000 = hms2rad(idata.ra_h, idata.ra_m, idata.ra_s) * RADTODEG; s.dec2000 = dms2rad(idata.dec_d, idata.dec_m, idata.dec_s) * RADTODEG; ra_dec_to_string(s.ra_str, idata.ra_h, idata.ra_m, idata.ra_s); ra_dec_to_string(s.dec_str, idata.dec_d, idata.dec_m, idata.dec_s); s.num_channels = idata.num_chan; s.start_MJD[0] = idata.mjd_i + idata.mjd_f; s.dt = idata.dt; s.T = s.N * s.dt; s.lo_freq = idata.freq; s.df = idata.chan_wid; s.hi_freq = s.lo_freq + (s.num_channels - 1.0) * s.df; s.BW = s.num_channels * s.df; s.fctr = s.lo_freq - 0.5 * s.df + 0.5 * s.BW; s.beam_FWHM = idata.fov / 3600.0; s.spectra_per_subint = SUBSBLOCKLEN; print_spectra_info_summary(&s); } else { printf("\nThe input files (%s) must be subbands! (i.e. *.sub##)\n\n", cmd->argv[0]); MPI_Finalize(); exit(1); } free(root); free(suffix); } } } // If we don't have good input data, exit MPI_Bcast(&good_inputs, 1, MPI_INT, 0, MPI_COMM_WORLD); if (!good_inputs) { MPI_Finalize(); exit(1); } MPI_Bcast(&insubs, 1, MPI_INT, 0, MPI_COMM_WORLD); if (insubs) cmd->nsub = cmd->argc; /* Determine the output file names and open them */ local_numdms = cmd->numdms / (numprocs - 1); dms = gen_dvect(local_numdms); if (cmd->numdms % (numprocs - 1)) { if (myid == 0) printf ("\nThe number of DMs must be divisible by (the number of processors - 1).\n\n"); MPI_Finalize(); exit(1); } local_lodm = cmd->lodm + (myid - 1) * local_numdms * cmd->dmstep; split_path_file(cmd->outfile, &outpath, &outfilenm); datafilenm = (char *) calloc(strlen(outfilenm) + 20, 1); if (myid > 0) { if (chdir(outpath) == -1) { printf("\nProcess %d on %s cannot chdir() to '%s'. Exiting.\n\n", myid, hostname, outpath); MPI_Finalize(); exit(1); } outfiles = (FILE **) malloc(local_numdms * sizeof(FILE *)); for (ii = 0; ii < local_numdms; ii++) { dms[ii] = local_lodm + ii * cmd->dmstep; avgdm += dms[ii]; sprintf(datafilenm, "%s_DM%.2f.dat", outfilenm, dms[ii]); outfiles[ii] = chkfopen(datafilenm, "wb"); } avgdm /= local_numdms; } // Broadcast the raw data information broadcast_spectra_info(&s, myid); if (myid > 0) { spectra_info_to_inf(&s, &idata); if (s.datatype==SIGPROCFB) cmd->filterbankP = 1; else if (s.datatype==PSRFITS) cmd->psrfitsP = 1; else if (s.datatype==SCAMP) cmd->pkmbP = 1; else if (s.datatype==BPP) cmd->bcpmP = 1; else if (s.datatype==WAPP) cmd->wappP = 1; else if (s.datatype==SPIGOT) cmd->spigotP = 1; else if (s.datatype==SUBBAND) insubs = 1; } s.filenames = cmd->argv; /* Read an input mask if wanted */ if (myid > 0) { int numpad = s.num_channels; if (insubs) numpad = s.num_files; s.padvals = gen_fvect(numpad); for (ii = 0 ; ii < numpad ; ii++) s.padvals[ii] = 0.0; } if (cmd->maskfileP) { if (myid == 0) { read_mask(cmd->maskfile, &obsmask); printf("Read mask information from '%s'\n\n", cmd->maskfile); good_padvals = determine_padvals(cmd->maskfile, &obsmask, s.padvals); } broadcast_mask(&obsmask, myid); MPI_Bcast(&good_padvals, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(s.padvals, obsmask.numchan, MPI_FLOAT, 0, MPI_COMM_WORLD); } else { obsmask.numchan = obsmask.numint = 0; MPI_Bcast(&good_padvals, 1, MPI_INT, 0, MPI_COMM_WORLD); } // The number of topo to bary time points to generate with TEMPO numbarypts = (int) (s.T * 1.1 / TDT + 5.5) + 1; // Identify the TEMPO observatory code { char *outscope = (char *) calloc(40, sizeof(char)); telescope_to_tempocode(idata.telescope, outscope, obs); free(outscope); } // Broadcast or calculate a few extra important values if (insubs) avgdm = idata.dm; idata.dm = avgdm; dsdt = cmd->downsamp * idata.dt; maxdm = cmd->lodm + cmd->numdms * cmd->dmstep; BW_ddelay = delay_from_dm(maxdm, idata.freq) - delay_from_dm(maxdm, idata.freq + (idata.num_chan-1) * idata.chan_wid); blocksperread = ((int) (BW_ddelay / idata.dt) / s.spectra_per_subint + 1); worklen = s.spectra_per_subint * blocksperread; if (cmd->nsub > s.num_channels) { printf ("Warning: The number of requested subbands (%d) is larger than the number of channels (%d).\n", cmd->nsub, s.num_channels); printf(" Re-setting the number of subbands to %d.\n\n", s.num_channels); cmd->nsub = s.num_channels; } if (s.spectra_per_subint % cmd->downsamp) { if (myid == 0) { printf ("\nError: The downsample factor (%d) must be a factor of the\n", cmd->downsamp); printf(" blocklength (%d). Exiting.\n\n", s.spectra_per_subint); } MPI_Finalize(); exit(1); } tlotoa = idata.mjd_i + idata.mjd_f; /* Topocentric epoch */ if (cmd->numoutP) totnumtowrite = cmd->numout; else totnumtowrite = (long) idata.N / cmd->downsamp; if (cmd->nobaryP) { /* Main loop if we are not barycentering... */ /* Dispersion delays (in bins). The high freq gets no delay */ /* All other delays are positive fractions of bin length (dt) */ dispdt = subband_search_delays(s.num_channels, cmd->nsub, avgdm, idata.freq, idata.chan_wid, 0.0); idispdt = gen_ivect(s.num_channels); for (ii = 0; ii < s.num_channels; ii++) idispdt[ii] = NEAREST_LONG(dispdt[ii] / idata.dt); vect_free(dispdt); /* The subband dispersion delays (see note above) */ offsets = gen_imatrix(local_numdms, cmd->nsub); for (ii = 0; ii < local_numdms; ii++) { double *subdispdt; subdispdt = subband_delays(s.num_channels, cmd->nsub, dms[ii], idata.freq, idata.chan_wid, 0.0); dtmp = subdispdt[cmd->nsub - 1]; for (jj = 0; jj < cmd->nsub; jj++) offsets[ii][jj] = NEAREST_LONG((subdispdt[jj] - dtmp) / dsdt); vect_free(subdispdt); } /* Allocate our data array and start getting data */ if (myid == 0) { printf("De-dispersing using %d subbands.\n", cmd->nsub); if (cmd->downsamp > 1) printf("Downsampling by a factor of %d (new dt = %.10g)\n", cmd->downsamp, dsdt); printf("\n"); } /* Print the nodes and the DMs they are handling */ print_dms(hostname, myid, numprocs, local_numdms, dms); outdata = gen_fmatrix(local_numdms, worklen / cmd->downsamp); numread = get_data(outdata, blocksperread, &s, &obsmask, idispdt, offsets, &padding); while (numread == worklen) { numread /= cmd->downsamp; if (myid == 0) print_percent_complete(totwrote, totnumtowrite); /* Write the latest chunk of data, but don't */ /* write more than cmd->numout points. */ numtowrite = numread; if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout) numtowrite = cmd->numout - totwrote; if (myid > 0) { write_data(outfiles, local_numdms, outdata, 0, numtowrite); /* Update the statistics */ if (!padding) { for (ii = 0; ii < numtowrite; ii++) update_stats(statnum + ii, outdata[0][ii], &min, &max, &avg, &var); statnum += numtowrite; } } totwrote += numtowrite; /* Stop if we have written out all the data we need to */ if (cmd->numoutP && (totwrote == cmd->numout)) break; numread = get_data(outdata, blocksperread, &s, &obsmask, idispdt, offsets, &padding); } datawrote = totwrote; } else { /* Main loop if we are barycentering... */ /* What ephemeris will we use? (Default is DE405) */ strcpy(ephem, "DE405"); /* Define the RA and DEC of the observation */ ra_dec_to_string(rastring, idata.ra_h, idata.ra_m, idata.ra_s); ra_dec_to_string(decstring, idata.dec_d, idata.dec_m, idata.dec_s); /* Allocate some arrays */ btoa = gen_dvect(numbarypts); ttoa = gen_dvect(numbarypts); for (ii = 0; ii < numbarypts; ii++) ttoa[ii] = tlotoa + TDT * ii / SECPERDAY; /* Call TEMPO for the barycentering */ if (myid == 0) { double maxvoverc = -1.0, minvoverc = 1.0, *voverc = NULL; printf("\nGenerating barycentric corrections...\n"); voverc = gen_dvect(numbarypts); barycenter(ttoa, btoa, voverc, numbarypts, rastring, decstring, obs, ephem); for (ii = 0; ii < numbarypts; ii++) { if (voverc[ii] > maxvoverc) maxvoverc = voverc[ii]; if (voverc[ii] < minvoverc) minvoverc = voverc[ii]; avgvoverc += voverc[ii]; } avgvoverc /= numbarypts; vect_free(voverc); printf(" Average topocentric velocity (c) = %.7g\n", avgvoverc); printf(" Maximum topocentric velocity (c) = %.7g\n", maxvoverc); printf(" Minimum topocentric velocity (c) = %.7g\n\n", minvoverc); printf("De-dispersing using %d subbands.\n", cmd->nsub); if (cmd->downsamp > 1) { printf(" Downsample = %d\n", cmd->downsamp); printf(" New sample dt = %.10g\n", dsdt); } printf("\n"); } /* Print the nodes and the DMs they are handling */ print_dms(hostname, myid, numprocs, local_numdms, dms); MPI_Bcast(btoa, numbarypts, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&avgvoverc, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); blotoa = btoa[0]; /* Dispersion delays (in bins). The high freq gets no delay */ /* All other delays are positive fractions of bin length (dt) */ dispdt = subband_search_delays(s.num_channels, cmd->nsub, avgdm, idata.freq, idata.chan_wid, avgvoverc); idispdt = gen_ivect(s.num_channels); for (ii = 0; ii < s.num_channels; ii++) idispdt[ii] = NEAREST_LONG(dispdt[ii] / idata.dt); vect_free(dispdt); /* The subband dispersion delays (see note above) */ offsets = gen_imatrix(local_numdms, cmd->nsub); for (ii = 0; ii < local_numdms; ii++) { double *subdispdt; subdispdt = subband_delays(s.num_channels, cmd->nsub, dms[ii], idata.freq, idata.chan_wid, avgvoverc); dtmp = subdispdt[cmd->nsub - 1]; for (jj = 0; jj < cmd->nsub; jj++) offsets[ii][jj] = NEAREST_LONG((subdispdt[jj] - dtmp) / dsdt); vect_free(subdispdt); } /* Convert the bary TOAs to differences from the topo TOAs in */ /* units of bin length (dt) rounded to the nearest integer. */ dtmp = (btoa[0] - ttoa[0]); for (ii = 0; ii < numbarypts; ii++) btoa[ii] = ((btoa[ii] - ttoa[ii]) - dtmp) * SECPERDAY / dsdt; /* Find the points where we need to add or remove bins */ { int oldbin = 0, currentbin; double lobin, hibin, calcpt; numdiffbins = abs(NEAREST_LONG(btoa[numbarypts - 1])) + 1; diffbins = gen_ivect(numdiffbins); diffbinptr = diffbins; for (ii = 1; ii < numbarypts; ii++) { currentbin = NEAREST_LONG(btoa[ii]); if (currentbin != oldbin) { if (currentbin > 0) { calcpt = oldbin + 0.5; lobin = (ii - 1) * TDT / dsdt; hibin = ii * TDT / dsdt; } else { calcpt = oldbin - 0.5; lobin = -((ii - 1) * TDT / dsdt); hibin = -(ii * TDT / dsdt); } while (fabs(calcpt) < fabs(btoa[ii])) { /* Negative bin number means remove that bin */ /* Positive bin number means add a bin there */ *diffbinptr = NEAREST_LONG(LININTERP (calcpt, btoa[ii - 1], btoa[ii], lobin, hibin)); diffbinptr++; calcpt = (currentbin > 0) ? calcpt + 1.0 : calcpt - 1.0; } oldbin = currentbin; } } *diffbinptr = cmd->numout; /* Used as a marker */ } diffbinptr = diffbins; /* Now perform the barycentering */ outdata = gen_fmatrix(local_numdms, worklen / cmd->downsamp); numread = get_data(outdata, blocksperread, &s, &obsmask, idispdt, offsets, &padding); while (numread == worklen) { /* Loop to read and write the data */ int numwritten = 0; double block_avg, block_var; numread /= cmd->downsamp; /* Determine the approximate local average */ avg_var(outdata[0], numread, &block_avg, &block_var); if (myid == 0) print_percent_complete(totwrote, totnumtowrite); /* Simply write the data if we don't have to add or */ /* remove any bins from this batch. */ /* OR write the amount of data up to cmd->numout or */ /* the next bin that will be added or removed. */ numtowrite = abs(*diffbinptr) - datawrote; if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout) numtowrite = cmd->numout - totwrote; if (numtowrite > numread) numtowrite = numread; if (myid > 0) { write_data(outfiles, local_numdms, outdata, 0, numtowrite); /* Update the statistics */ if (!padding) { for (ii = 0; ii < numtowrite; ii++) update_stats(statnum + ii, outdata[0][ii], &min, &max, &avg, &var); statnum += numtowrite; } } datawrote += numtowrite; totwrote += numtowrite; numwritten += numtowrite; if ((datawrote == abs(*diffbinptr)) && (numwritten != numread) && (totwrote < cmd->numout)) { /* Add/remove a bin */ int skip, nextdiffbin; skip = numtowrite; /* Write the rest of the data after adding/removing a bin */ do { if (*diffbinptr > 0) { /* Add a bin */ if (myid > 0) write_padding(outfiles, local_numdms, block_avg, 1); numadded++; totwrote++; } else { /* Remove a bin */ numremoved++; datawrote++; numwritten++; skip++; } diffbinptr++; /* Write the part after the diffbin */ numtowrite = numread - numwritten; if (cmd->numoutP && (totwrote + numtowrite) > cmd->numout) numtowrite = cmd->numout - totwrote; nextdiffbin = abs(*diffbinptr) - datawrote; if (numtowrite > nextdiffbin) numtowrite = nextdiffbin; if (myid > 0) { write_data(outfiles, local_numdms, outdata, skip, numtowrite); /* Update the statistics and counters */ if (!padding) { for (ii = 0; ii < numtowrite; ii++) update_stats(statnum + ii, outdata[0][skip + ii], &min, &max, &avg, &var); statnum += numtowrite; } } numwritten += numtowrite; datawrote += numtowrite; totwrote += numtowrite; skip += numtowrite; /* Stop if we have written out all the data we need to */ if (cmd->numoutP && (totwrote == cmd->numout)) break; } while (numwritten < numread); } /* Stop if we have written out all the data we need to */ if (cmd->numoutP && (totwrote == cmd->numout)) break; numread = get_data(outdata, blocksperread, &s, &obsmask, idispdt, offsets, &padding); } } if (myid > 0) { /* Calculate the amount of padding we need */ if (cmd->numoutP && (cmd->numout > totwrote)) padwrote = padtowrite = cmd->numout - totwrote; /* Write the new info file for the output data */ idata.dt = dsdt; update_infodata(&idata, totwrote, padtowrite, diffbins, numdiffbins, cmd->downsamp); for (ii = 0; ii < local_numdms; ii++) { idata.dm = dms[ii]; if (!cmd->nobaryP) { double baryepoch, barydispdt, baryhifreq; baryhifreq = idata.freq + (s.num_channels - 1) * idata.chan_wid; barydispdt = delay_from_dm(dms[ii], doppler(baryhifreq, avgvoverc)); baryepoch = blotoa - (barydispdt / SECPERDAY); idata.bary = 1; idata.mjd_i = (int) floor(baryepoch); idata.mjd_f = baryepoch - idata.mjd_i; } sprintf(idata.name, "%s_DM%.2f", outfilenm, dms[ii]); writeinf(&idata); } /* Set the padded points equal to the average data point */ if (idata.numonoff >= 1) { int index, startpad, endpad; for (ii = 0; ii < local_numdms; ii++) { fclose(outfiles[ii]); sprintf(datafilenm, "%s_DM%.2f.dat", outfilenm, dms[ii]); outfiles[ii] = chkfopen(datafilenm, "rb+"); } for (ii = 0; ii < idata.numonoff; ii++) { index = 2 * ii; startpad = idata.onoff[index + 1]; if (ii == idata.numonoff - 1) endpad = idata.N - 1; else endpad = idata.onoff[index + 2]; for (jj = 0; jj < local_numdms; jj++) chkfseek(outfiles[jj], (startpad + 1) * sizeof(float), SEEK_SET); padtowrite = endpad - startpad; write_padding(outfiles, local_numdms, avg, padtowrite); } } } /* Print simple stats and results */ var /= (datawrote - 1); if (myid == 0) print_percent_complete(1, 1); if (myid == 1) { printf("\n\nDone.\n\nSimple statistics of the output data:\n"); printf(" Data points written: %ld\n", totwrote); if (padwrote) printf(" Padding points written: %ld\n", padwrote); if (!cmd->nobaryP) { if (numadded) printf(" Bins added for barycentering: %d\n", numadded); if (numremoved) printf(" Bins removed for barycentering: %d\n", numremoved); } printf(" Maximum value of data: %.2f\n", max); printf(" Minimum value of data: %.2f\n", min); printf(" Data average value: %.2f\n", avg); printf(" Data standard deviation: %.2f\n", sqrt(var)); printf("\n"); } /* Close the files and cleanup */ if (cmd->maskfileP) free_mask(obsmask); if (myid > 0) { for (ii = 0; ii < local_numdms; ii++) fclose(outfiles[ii]); free(outfiles); } vect_free(outdata[0]); vect_free(outdata); vect_free(dms); free(hostname); vect_free(idispdt); vect_free(offsets[0]); vect_free(offsets); free(datafilenm); free(outfilenm); free(outpath); if (!cmd->nobaryP) { vect_free(btoa); vect_free(ttoa); vect_free(diffbins); } MPI_Finalize(); return (0); }
int main(int argc, char *argv[]) { Cmdline *cmd; struct psrfits pfupper, pflower, pfo; fitsfile *infits, *outfits; char *pc1, *pc2; char outfilename[200]; //Name of outfile if not specified on command line int stat = 0, padding = 0, userN = 0, status; // Call usage() if we have no command line arguments if (argc == 1) { Program = argv[0]; usage(); exit(0); } // Parse the command line using the excellent program Clig cmd = parseCmdline(argc, argv); pfupper.tot_rows = pfupper.N = pfupper.T = pfupper.status = 0; //Initialize upper band pflower.tot_rows = pflower.N = pflower.T = pflower.status = 0; //Initialize lower band pfupper.filenum = pflower.filenum = 1; pfo.tot_rows = pfo.N = pfo.T = pfo.status = pfo.multifile = 0; //Initialize output sprintf(pfupper.filename, cmd->argv[0]); //Copy filename specified on command line to sprintf(pflower.filename, cmd->argv[0]); //upper and lower bands, will correct filenames shortly if ((pc2 = strstr(pfupper.filename, "s1")) != NULL) //Upper contains s1, change to s0 strncpy(pc2, "s0", 2); else if ((pc2 = strstr(pflower.filename, "s0")) != NULL) //Lower contains s0, change to s1 strncpy(pc2, "s1", 2); else { printf("Unable to determine which sideband is which\n"); exit(EXIT_FAILURE); } //Setting the name of the output file, setting as same name as input file, but removing s0/s1. pc1 = strstr(pflower.filename, "s1"); pc2 = strrchr(pflower.filename, '.'); //At '.fits' pc2--; while ((pc2 >= pflower.filename) && isdigit(*pc2)) //Move through the digits to the separation char. pc2--; strncpy(outfilename, pflower.filename, pc1 - pflower.filename); //Copy everything up to s1 into outfilename strncpy(outfilename + (pc1 - pflower.filename), pc1 + 2, pc2 - pc1 - 2); //Concatenate from after s1 to char before the separation char. pc1 = outfilename + (pc2 - pflower.filename - 2); *pc1 = 0; int rv = psrfits_open(&pfupper); //Open upper band if (rv) { fits_report_error(stderr, rv); exit(1); } rv = psrfits_open(&pflower); //Open lower band if (rv) { fits_report_error(stderr, rv); exit(1); } pfo = pflower; //Copy all lower band variables into the output struct if (!cmd->outputbasenameP) sprintf(pfo.basefilename, basename(outfilename)); else sprintf(pfo.basefilename, cmd->outputbasename); pfo.filenum = 0; sprintf(pfo.filename, "\0"); //Set filename to null so psrfits_open will create the filename for me pfo.rownum = 1; pfo.tot_rows = 0; pfo.N = 0; printf("lower rows_per_file=%d\n",pflower.rows_per_file); printf("upper rows_per_file=%d\n",pfupper.rows_per_file); if (pfupper.rows_per_file != pflower.rows_per_file) { //Sanity check for the two input frequency bands fprintf(stderr, "rows_per_file in input files do not match!\n"); exit(1); } double upperfreqoflower, nextfromlower, lowerfreqofupper, numchandiff; //Used to find which frequencies to take from each band double offsetfactor, scalefactor; //Factors which will be applied to offsets and scales int upchanskip, lowchanskip; //Number of channels to skip in each banda //Variables used to make code cleaner int extrachanoffset, outoffset, upperoffset, numtocopyupper, loweroffset_skip, loweroffset, numtocopylower, newuppernchan, newlowernchan; double df = pflower.hdr.df; int nchan = pflower.hdr.nchan; int outnchan; int npol = pflower.hdr.npol; int nbits = pflower.hdr.nbits; int nsblk = pflower.hdr.nsblk; //Allocate memory for all upper and lower data pflower.sub.dat_freqs = (double *) malloc(sizeof(double) * nchan); pflower.sub.dat_weights = (float *) malloc(sizeof(float) * nchan); pflower.sub.dat_offsets = (float *) malloc(sizeof(float) * nchan * npol); pflower.sub.dat_scales = (float *) malloc(sizeof(float) * nchan * npol); pflower.sub.rawdata = (unsigned char *) malloc(pflower.sub.bytes_per_subint); pflower.sub.data = (unsigned char *) malloc(pflower.sub.bytes_per_subint*2); pfupper.sub.dat_freqs = (double *) malloc(sizeof(double) * nchan); pfupper.sub.dat_weights = (float *) malloc(sizeof(float) * nchan); pfupper.sub.dat_offsets = (float *) malloc(sizeof(float) * nchan * npol); pfupper.sub.dat_scales = (float *) malloc(sizeof(float) * nchan * npol); pfupper.sub.rawdata = (unsigned char *) malloc(pfupper.sub.bytes_per_subint); pfupper.sub.data = (unsigned char *) malloc(pfupper.sub.bytes_per_subint*2); int firsttime = 1; //First time through do while loop do { print_percent_complete(pflower.rownum, pflower.rows_per_file, pflower.rownum == 1 ? 1 : 0); psrfits_read_subint(&pflower); psrfits_read_subint(&pfupper); if (firsttime) { //First time through loop, calculate factors for scales and offsets and number of channels to skip firsttime = 0; //Find the number of channels in the upper band which will be skipped if (df < 0) { //Find channel order, low to high or high to low upperfreqoflower = pflower.sub.dat_freqs[0]; //Highest frequency channel in lower band lowerfreqofupper = pfupper.sub.dat_freqs[nchan - 1]; //Lowest frequency channel in upper band } else { upperfreqoflower = pflower.sub.dat_freqs[nchan - 1]; //Highest frequency channel in lower band lowerfreqofupper = pfupper.sub.dat_freqs[0]; //Lowest frequency channel in upper band } nextfromlower = upperfreqoflower + fabs(df); //Second highest channel in lower band numchandiff = (nextfromlower - lowerfreqofupper) / fabs(df); //Number of channels to skip in float form int chanskip; if (numchandiff > 0) { //Make sure there are channels which need to be skipped if (numchandiff - (double) ((int) numchandiff) > .5) // See whether we need to round up integer channels to skip chanskip = (int) numchandiff + 1; else chanskip = (int) numchandiff; } else chanskip = 0; //No need to skip any channels if (chanskip % 2 == 1) { //Odd number of channels, give lower band the extra channel upchanskip = chanskip / 2; lowchanskip = chanskip / 2 + 1; } else //Even number of channels to skip upchanskip = lowchanskip = chanskip / 2; if (upchanskip % 2 == 1) { //We want an even number of channels in upper band for 4-bit data to get copied correctly ++lowchanskip; --upchanskip; } //Find new values given the number of channels skipped pfo.hdr.nchan = outnchan = nchan + nchan - chanskip + 2; //New number of channels, plus 2 to make nchan=960 (many factors of 2) pfo.hdr.BW = (double) outnchan *fabs(df); //New bandwidth pfo.hdr.fctr = //New center frequency (pflower.hdr.fctr - (double) (nchan / 2) * fabs(df)) + pfo.hdr.BW / 2.0; pfo.sub.bytes_per_subint = //Calculate new number of bytes in each subint outnchan * nsblk * nbits / 8 * npol; //Allocate space for output data now that we know the new number of channels pfo.sub.dat_freqs = (double *) malloc(sizeof(double) * outnchan); pfo.sub.dat_weights = (float *) malloc(sizeof(float) * outnchan); pfo.sub.dat_offsets = (float *) malloc(sizeof(float) * outnchan * npol); pfo.sub.dat_scales = (float *) malloc(sizeof(float) * outnchan * npol); pfo.sub.rawdata = (unsigned char *) malloc(pfo.sub.bytes_per_subint); pfo.sub.data = (unsigned char *) malloc(pfo.sub.bytes_per_subint*2); newuppernchan = nchan - upchanskip; //The number of channels to copy from the upper sideband. newlowernchan = nchan - lowchanskip; //The number of channels to copy from the lower sideband. extrachanoffset = 2; //Offset for 2 extra freq channels making nchan 960 in bytes outoffset = (outnchan * npol); //Offset in each loop due to previously written data upperoffset = (nchan * npol); //Offset in loop for upper band numtocopyupper = (newuppernchan * npol); //Number of bytes to copy from upper band loweroffset_skip = (lowchanskip * npol); //Number of bytes to skip when copying lower band due to //having written upper band loweroffset = //Number of bytes to skip due to having written previous lower band data (nchan * npol); numtocopylower = (newlowernchan * npol); //Number of bytes to copy from lower band float upmean, upvar, lowmean, lowvar; avg_var(pfupper.sub.dat_offsets + (nchan - upchanskip), //Find the mean and variance of the upper band's offsets upchanskip, &upmean, &upvar); printf("Upper offset stats: mean=%f variance=%f\n", upmean, upvar); avg_var(pflower.sub.dat_offsets, lowchanskip, &lowmean, &lowvar); //Find the mean and variance of the lower band's offsets printf("Lower offset stats: mean=%f variance=%f\n", lowmean, lowvar); printf("Applying factor of %f to upper offsets\n", (lowmean / upmean)); offsetfactor = lowmean / upmean; //Set offset factor used to correct variance differences in the two bands avg_var(pfupper.sub.dat_scales + (nchan - upchanskip), //Find the mean and var. of the upper band's scales upchanskip, &upmean, &upvar); printf("Upper scales stats: mean=%f variance=%f\n", upmean, upvar); avg_var(pflower.sub.dat_scales, lowchanskip, &lowmean, &lowvar); //Find the mean and var. of the lower band's scales printf("Lower scales stats: mean=%f variance=%f\n", lowmean, lowvar); printf("Applying factor of %f to upper scales\n", (lowmean / upmean)); scalefactor = lowmean / upmean; //Set scale factor used to correct variance differences in the two bands } if (pflower.status == 0 && pfupper.status == 0) { //Copy info from the lower band subint struct to the output file's subint struct pfo.sub.tsubint = pflower.sub.tsubint; pfo.sub.offs = pflower.sub.offs; pfo.sub.lst = pflower.sub.lst; pfo.sub.ra = pflower.sub.ra; pfo.sub.dec = pflower.sub.dec; pfo.sub.glon = pflower.sub.glon; pfo.sub.glat = pflower.sub.glat; pfo.sub.feed_ang = pflower.sub.feed_ang; pfo.sub.pos_ang = pflower.sub.pos_ang; pfo.sub.par_ang = pflower.sub.par_ang; pfo.sub.tel_az = pflower.sub.tel_az; pfo.sub.tel_zen = pflower.sub.tel_zen; pfo.sub.FITS_typecode = pflower.sub.FITS_typecode; //Create variables to reduce column width of lines below double *dat_freqs = pfo.sub.dat_freqs; double *udat_freqs = pfupper.sub.dat_freqs; double *ldat_freqs = pflower.sub.dat_freqs; float *dat_weights = pfo.sub.dat_weights; float *udat_weights = pfupper.sub.dat_weights; float *ldat_weights = pflower.sub.dat_weights; float *dat_offsets = pfo.sub.dat_offsets; float *udat_offsets = pfupper.sub.dat_offsets; float *ldat_offsets = pflower.sub.dat_offsets; float *dat_scales = pfo.sub.dat_scales; float *udat_scales = pfupper.sub.dat_scales; float *ldat_scales = pflower.sub.dat_scales; unsigned char *data = pfo.sub.data; unsigned char *udata = pfupper.sub.data; unsigned char *ldata = pflower.sub.data; if (df < 0) { //Copy frequency labels dat_freqs[1] = udat_freqs[0] + fabs(df); //Calculate the frequency labels dat_freqs[0] = dat_freqs[1] + fabs(df); //for our two empty frequency channels int newuppernchan = nchan - upchanskip; //The number of channels to copy from the upper band int newlowernchan = nchan - lowchanskip; //The number of channels to copy from the lower band memcpy(dat_freqs + 2, udat_freqs, sizeof(double) * newuppernchan); //Copy from the upper band, skipping first two chans. memcpy(dat_freqs + newuppernchan + 2, //Copy from the lower band ldat_freqs + lowchanskip, sizeof(double) * newlowernchan); //Copy weights dat_weights[0] = dat_weights[1] = 0; //Set the weights of first two channels to 0, so they shouldn't be used in calculations memcpy(dat_weights + 2, udat_weights, //Copy weights from the upper band sizeof(float) * newuppernchan); memcpy(dat_weights + 2 + newuppernchan, //Copy weights from the lower band ldat_weights + lowchanskip, sizeof(float) * newlowernchan); //Copy offsets dat_offsets[0] = dat_offsets[1] = //Set offsets of first two channels to the same as upper's first channel udat_offsets[0]; //(shouldn't matter since they should be ignored) int ii; for (ii = 0; ii < newuppernchan; ++ii) //Apply offset factor to upper band udat_offsets[ii] = udat_offsets[ii] * (offsetfactor); memcpy(dat_offsets + 2 * npol, udat_offsets, //Copy upper offsets sizeof(float) * newuppernchan * npol); memcpy(dat_offsets + (newuppernchan + 2) * npol, //Copy lower offsets ldat_offsets + lowchanskip, sizeof(float) * newlowernchan * npol); //Copy scales for (ii = 0; ii < newuppernchan; ++ii) //Apply scale factor to upper band udat_scales[ii] = udat_scales[ii] * (scalefactor); dat_scales[0] = dat_scales[1] = udat_scales[0]; memcpy(dat_scales + 2 * npol, udat_scales, //Copy upper scales sizeof(float) * newuppernchan * npol); memcpy(dat_scales + (newuppernchan + 2) * npol, //Copy lower scales ldat_scales + lowchanskip, sizeof(float) * newlowernchan * npol); //Copy the data for (ii = 0; ii < nsblk; ++ii) { //Loop through data copying into place memcpy(data + ii * outoffset + extrachanoffset, udata + ii * upperoffset, numtocopyupper); memcpy(data + ii * outoffset + extrachanoffset + numtocopyupper, ldata + ii * loweroffset + loweroffset_skip, numtocopylower); } psrfits_write_subint(&pfo); } else { } } } while (pfo.rownum <= pfo.rows_per_file && pfupper.status==0 && pflower.status==0); printf("Closing file '%s'\n", pflower.filename); fits_close_file(pfupper.fptr, &status); printf("Closing file '%s'\n", pfupper.filename); fits_close_file(pflower.fptr, &status); if(pflower.status!=0||pfupper.status!=0) { fprintf(stderr,"An error occurred when combining the two Mock files!\n"); if(pflower.status==108||pfupper.status==108) fprintf(stderr,"One or both of the files is incomplete.\n"); exit(1); } exit(0); }
int get_current_row(struct psrfits *pfi, struct subband_info *si) { static int firsttime = 1, num_pad_blocks = 0; static double last_offs, row_duration; double diff_offs, dnum_blocks; if (firsttime) { row_duration = pfi->sub.tsubint; last_offs = pfi->sub.offs-row_duration; firsttime = 0; } print_percent_complete(pfi->rownum, pfi->rows_per_file, pfi->rownum==1 ? 1 : 0); #if 0 printf("row %d\n", pfi->rownum); #endif if (num_pad_blocks==0) { // Try to read the PSRFITS file // Read the current row of data psrfits_read_subint(pfi); diff_offs = pfi->sub.offs - last_offs; if (si->userwgts) // Always overwrite if using user weights memcpy(pfi->sub.dat_weights, si->userwgts, pfi->hdr.nchan * sizeof(float)); if (!TEST_CLOSE(diff_offs, row_duration) || pfi->status) { if (pfi->status) { // End of the files num_pad_blocks = 1; } else { // Missing row(s) dnum_blocks = diff_offs/row_duration - 1.0; num_pad_blocks = (int)(dnum_blocks + 1e-7); pfi->rownum--; // Will re-read when no more padding pfi->tot_rows--; // Only count "real" rows towards tot_rows #if 1 printf("At row %d, found %d dropped rows.\n", pfi->rownum, num_pad_blocks); printf("Adding a missing row (#%d) of padding to the subbands.\n", pfi->tot_rows); #endif pfi->N -= pfi->hdr.nsblk; // Will be re-added below for padding } // Now fill the main part of si->fbuffer with the chan_avgs so that // it acts like a correctly read block (or row) fill_chans_with_avgs(si->buflen, si->bufwid, pfi->sub.fdata, si->chan_avgs); } else { // Return the row from the file // Compute the float representations of the data scale_and_offset_data(pfi, si->numunsigned); // Determine channel statistics get_chan_stats(pfi, si); last_offs = pfi->sub.offs; return 0; } } // Return the same padding as before last_offs += row_duration; pfi->N += pfi->hdr.nsblk; pfi->T = pfi->N * pfi->hdr.dt; num_pad_blocks--; return num_pad_blocks; }
int main(int argc, char *argv[]) { int ii; double ttim, utim, stim, tott; struct tms runtimes; subharminfo **subharminfs; accelobs obs; infodata idata; GSList *cands = NULL; Cmdline *cmd; /* Prep the timer */ tott = times(&runtimes) / (double) CLK_TCK; /* Call usage() if we have no command line arguments */ if (argc == 1) { Program = argv[0]; printf("\n"); usage(); exit(1); } /* Parse the command line using the excellent program Clig */ cmd = parseCmdline(argc, argv); #ifdef DEBUG showOptionValues(); #endif printf("\n\n"); printf(" Fourier-Domain Acceleration Search Routine\n"); printf(" by Scott M. Ransom\n\n"); /* Create the accelobs structure */ create_accelobs(&obs, &idata, cmd, 1); /* Zap birdies if requested and if in memory */ if (cmd->zaplistP && !obs.mmap_file && obs.fft) { int numbirds; double *bird_lobins, *bird_hibins, hibin; /* Read the Standard bird list */ numbirds = get_birdies(cmd->zaplist, obs.T, cmd->baryv, &bird_lobins, &bird_hibins); /* Zap the birdies */ printf("Zapping them using a barycentric velocity of %.5gc.\n\n", cmd->baryv); hibin = obs.N / 2; for (ii = 0; ii < numbirds; ii++) { if (bird_lobins[ii] >= hibin) break; if (bird_hibins[ii] >= hibin) bird_hibins[ii] = hibin - 1; zapbirds(bird_lobins[ii], bird_hibins[ii], NULL, obs.fft); } free(bird_lobins); free(bird_hibins); } printf("Searching with up to %d harmonics summed:\n", 1 << (obs.numharmstages - 1)); printf(" f = %.1f to %.1f Hz\n", obs.rlo / obs.T, obs.rhi / obs.T); printf(" r = %.1f to %.1f Fourier bins\n", obs.rlo, obs.rhi); printf(" z = %.1f to %.1f Fourier bins drifted\n\n", obs.zlo, obs.zhi); /* Generate the correlation kernels */ printf("Generating correlation kernels:\n"); subharminfs = create_subharminfos(obs.numharmstages, (int) obs.zhi); printf("Done generating kernels.\n\n"); printf("Starting the search.\n"); /* Don't use the *.txtcand files on short in-memory searches */ if (!obs.dat_input) { printf(" Working candidates in a test format are in '%s'.\n\n", obs.workfilenm); } /* Start the main search loop */ { double startr = obs.rlo, lastr = 0, nextr = 0; ffdotpows *fundamental; while (startr + ACCEL_USELEN * ACCEL_DR < obs.highestbin) { /* Search the fundamental */ print_percent_complete(startr - obs.rlo, obs.highestbin - obs.rlo, "search", 0); nextr = startr + ACCEL_USELEN * ACCEL_DR; lastr = nextr - ACCEL_DR; fundamental = subharm_ffdot_plane(1, 1, startr, lastr, &subharminfs[0][0], &obs); cands = search_ffdotpows(fundamental, 1, &obs, cands); if (obs.numharmstages > 1) { /* Search the subharmonics */ int stage, harmtosum, harm; ffdotpows *subharmonic; for (stage = 1; stage < obs.numharmstages; stage++) { harmtosum = 1 << stage; for (harm = 1; harm < harmtosum; harm += 2) { subharmonic = subharm_ffdot_plane(harmtosum, harm, startr, lastr, &subharminfs[stage][harm - 1], &obs); add_ffdotpows(fundamental, subharmonic, harmtosum, harm); free_ffdotpows(subharmonic); } cands = search_ffdotpows(fundamental, harmtosum, &obs, cands); } } free_ffdotpows(fundamental); startr = nextr; } print_percent_complete(obs.highestbin - obs.rlo, obs.highestbin - obs.rlo, "search", 0); } printf("\n\nDone searching. Now optimizing each candidate.\n\n"); free_subharminfos(obs.numharmstages, subharminfs); { /* Candidate list trimming and optimization */ int numcands; GSList *listptr; accelcand *cand; fourierprops *props; numcands = g_slist_length(cands); if (numcands) { /* Sort the candidates according to the optimized sigmas */ cands = sort_accelcands(cands); /* Eliminate (most of) the harmonically related candidates */ if ((cmd->numharm > 1) && !(cmd->noharmremoveP)) eliminate_harmonics(cands, &numcands); /* Now optimize each candidate and its harmonics */ print_percent_complete(0, 0, NULL, 1); listptr = cands; for (ii = 0; ii < numcands; ii++) { print_percent_complete(ii, numcands, "optimization", 0); cand = (accelcand *) (listptr->data); optimize_accelcand(cand, &obs); listptr = listptr->next; } print_percent_complete(ii, numcands, "optimization", 0); /* Calculate the properties of the fundamentals */ props = (fourierprops *) malloc(sizeof(fourierprops) * numcands); listptr = cands; for (ii = 0; ii < numcands; ii++) { cand = (accelcand *) (listptr->data); /* In case the fundamental harmonic is not significant, */ /* send the originally determined r and z from the */ /* harmonic sum in the search. Note that the derivs are */ /* not used for the computations with the fundamental. */ calc_props(cand->derivs[0], cand->r, cand->z, 0.0, props + ii); /* Override the error estimates based on power */ props[ii].rerr = (float) (ACCEL_DR) / cand->numharm; props[ii].zerr = (float) (ACCEL_DZ) / cand->numharm; listptr = listptr->next; } /* Write the fundamentals to the output text file */ output_fundamentals(props, cands, &obs, &idata); /* Write the harmonics to the output text file */ output_harmonics(cands, &obs, &idata); /* Write the fundamental fourierprops to the cand file */ obs.workfile = chkfopen(obs.candnm, "wb"); chkfwrite(props, sizeof(fourierprops), numcands, obs.workfile); fclose(obs.workfile); free(props); printf("\n\n"); } else { printf("No candidates above sigma = %.2f were found.\n\n", obs.sigma); } } /* Finish up */ printf("Searched the following approx numbers of independent points:\n"); printf(" %d harmonic: %9lld\n", 1, obs.numindep[0]); for (ii = 1; ii < obs.numharmstages; ii++) printf(" %d harmonics: %9lld\n", 1 << ii, obs.numindep[ii]); printf("\nTiming summary:\n"); tott = times(&runtimes) / (double) CLK_TCK - tott; utim = runtimes.tms_utime / (double) CLK_TCK; stim = runtimes.tms_stime / (double) CLK_TCK; ttim = utim + stim; printf(" CPU time: %.3f sec (User: %.3f sec, System: %.3f sec)\n", ttim, utim, stim); printf(" Total time: %.3f sec\n\n", tott); printf("Final candidates in binary format are in '%s'.\n", obs.candnm); printf("Final Candidates in a text format are in '%s'.\n\n", obs.accelnm); free_accelobs(&obs); g_slist_foreach(cands, free_accelcand, NULL); g_slist_free(cands); return (0); }