double *dorbint(double Eo, long numpts, double dt, orbitparams * orb) /* This routine integrates Keplar's Equation and returns a double */ /* vector of the eccentric anomalys (E) for each point. The initial */ /* value for eccentric anomaly (usually determined by using */ /* keplars_equation()) goes in Eo. The time increment to use is dt, */ /* total number of pts goes in 'numpts' and all of the various orbital */ /* parameters are found in *orb. The routine uses 4th order Runge- */ /* Kutta in a dumb mode (no adaptive step-size) since all we want is */ /* tabulated results with even intervals. */ { long ii; double k1, k2, k3, k4, dt2, twopif, *E, e, Etmp; E = gen_dvect(numpts); E[0] = Eo; e = orb->e; twopif = TWOPI / orb->p; dt2 = 0.5 * dt; for (ii = 0; ii < numpts - 1; ii++) { Etmp = E[ii]; k1 = EDOT(Etmp); k2 = EDOT(Etmp + dt2 * k1); k3 = EDOT(Etmp + dt2 * k2); k4 = EDOT(Etmp + dt * k3); E[ii + 1] = Etmp + dt * (((k1 + k4) * 0.5 + k2 + k3) / 3.0); } return E; }
int bary2topo(double *topotimes, double *barytimes, int numtimes, double fb, double fbd, double fbdd, double *ft, double *ftd, double *ftdd) /* Convert a set of barycentric pulsar spin parameters (fb, fbd, fbdd) */ /* into topocentric spin parameters (ft, ftd, ftdd) by performing */ /* a linear least-squares fit (using LAPACK routine DGELS). The */ /* routine equates the pulse phase using topcentric parameters and */ /* times to the pulse phase using barycentric parameters and times. */ { double *work, *aa, *bb, dtmp; int ii, mm = 3, nn, nrhs = 1, lwork, info, index; char trans = 'T'; if (numtimes < 4) { printf("\n'numtimes' < 4 in bary2topo(): Cannot solve.\n\n"); exit(0); } nn = numtimes; lwork = mm + nn * 9; aa = gen_dvect(mm * nn); bb = gen_dvect(nn); work = gen_dvect(lwork); for (ii = 0; ii < nn; ii++) { index = ii * 3; dtmp = (topotimes[ii] - topotimes[0]) * SECPERDAY; aa[index] = dtmp; aa[index + 1] = 0.5 * dtmp * dtmp; aa[index + 2] = dtmp * dtmp * dtmp / 6.0; dtmp = (barytimes[ii] - barytimes[0]) * SECPERDAY; bb[ii] = dtmp * (fb + dtmp * (0.5 * fbd + fbdd * dtmp / 6.0)); } // dgels_(&trans, &mm, &nn, &nrhs, aa, &mm, bb, &nn, work, &lwork, &info); call_dgels(&trans, mm, nn, nrhs, aa, mm, bb, nn, work, lwork, &info); *ft = bb[0]; *ftd = bb[1]; *ftdd = bb[2]; vect_free(aa); vect_free(bb); vect_free(work); return info; }
double *gen_dfreqs(long numfreqs, double lof, double df) /* This routine generates a double vector of length numfreqs */ /* with values set to lof, lof+df, lof+2df, ... */ /* It is normally used when generating a list of freqs */ /* for an x-y plot of spectral data. */ { long i; double *freqs; freqs = gen_dvect(numfreqs); for (i = 0; i < numfreqs; i++) { freqs[i] = lof + i * df; } return freqs; }
float estimate_offpulse_redchi2(double *inprofs, foldstats *stats, int numparts, int numsubbands, int proflen, int numtrials, double dofeff) // Randomly offset each pulse profile in a .pfd data square or cube // and combine them to estimate a "true" off-pulse level. Do this // numtrials times in order to improve the statistics. Return the // inverse of the average of the off-pulse reduced-chi^2 (i.e. the // correction factor). dofeff is the effective number of DOF as // returned by DOF_corr(). { int ii, jj, kk, offset, trialnum, phsindex, statindex; float *chis; double chi_avg, chi_var, redchi; double prof_avg, prof_var, *prof_ptr, *sumprof; sumprof = gen_dvect(proflen); chis = gen_fvect(numtrials); for (trialnum = 0; trialnum < numtrials; trialnum++) { // Initialize the summed profile for (ii = 0; ii < proflen; ii++) sumprof[ii] = 0.0; prof_avg = 0.0; prof_var = 0.0; prof_ptr = inprofs; for (ii = 0; ii < numparts; ii++) { // parts for (jj = 0; jj < numsubbands; jj++) { // subbands statindex = ii * numsubbands + jj; offset = random() % proflen; phsindex = 0; for (kk = offset; kk < proflen; kk++, phsindex++) // phases sumprof[phsindex] += prof_ptr[kk]; for (kk = 0; kk < offset; kk++, phsindex++) // phases sumprof[phsindex] += prof_ptr[kk]; prof_ptr += proflen; prof_avg += stats[statindex].prof_avg; prof_var += stats[statindex].prof_var; } } /* Calculate the current chi-squared */ redchi = chisqr(sumprof, proflen, prof_avg, prof_var) / dofeff; chis[trialnum] = (float) redchi; } avg_var(chis, numtrials, &chi_avg, &chi_var); vect_free(chis); vect_free(sumprof); return 1.0/chi_avg; }
void drotate_1d(double *data, long numbins, long bins_to_left) /* Rotates a vector by bins_to_left places to the left. */ /* numbins is the number of DOUBLE points to move. */ /* drotate is better. Use it. */ { double *tmp; if (bins_to_left < 0 || bins_to_left >= numbins) { printf("\nNumber of bins to rotate array in rotate_1d is\n"); printf("\nout of bounds. Tried to rotate %ld bins. Exiting.\n", bins_to_left); exit(1); } tmp = gen_dvect(bins_to_left); memcpy(tmp, data, sizeof(double) * bins_to_left); memmove(data, data + bins_to_left, sizeof(double) * (numbins - bins_to_left)); memcpy(data + bins_to_left, tmp, sizeof(double) * bins_to_left); free(tmp); }
double *get_hdr_double_arr(struct HEADERP *h, char *name, int *len) { struct HEADERVAL val; int ii; double *dptr, *darr; if (find_hdrval(h, name, &val)) { printf("ERROR: Can't find '%s' in the WAPP header!\n", name); exit(0); } dptr = (double *) val.value; *len = val.key->alen; /* Note that this needs to be freed! */ darr = gen_dvect(*len); for (ii = 0; ii < *len; ii++, dptr++) { darr[ii] = *dptr; } return darr; }
void drotate(double *data, long numbins, double bins_to_left) /* Rotates a vector by bins_to_left places to the left. */ /* numbins is the number of DOUBLE points to move. */ { double *tmp, lopart, hipart, intpart; long i, index; bins_to_left = fmod(bins_to_left, (double) numbins); if (bins_to_left < 0.0) bins_to_left += numbins; tmp = gen_dvect(numbins); lopart = modf(bins_to_left, &intpart); hipart = 1.0 - lopart; index = (long) floor(intpart + 1.0E-20); for (i = 0; i < numbins; i++) tmp[i] = hipart * data[(index + i) % numbins] + lopart * data[(index + i + 1) % numbins]; memcpy(data, tmp, sizeof(double) * numbins); free(tmp); }
double *dedisp_delays(int numchan, double dm, double lofreq, double chanwidth, double voverc) /* Return an array of delays (sec) for dedispersing 'numchan' */ /* channels at a DM of 'dm'. 'lofreq' is the center frequency */ /* in MHz of the lowest frequency channel. 'chanwidth' is the */ /* width in MHz of each channel. 'voverc' is the observatory's */ /* velocity towards or away from the source. This is to adjust */ /* the frequencies for doppler effects (for no correction use */ /* voverc=0). The returned array is allocated by this routine. */ { int ii; double *delays, freq; delays = gen_dvect(numchan); for (ii = 0; ii < numchan; ii++) { freq = doppler(lofreq + ii * chanwidth, voverc); delays[ii] = delay_from_dm(dm, freq); } return delays; }
// FIXME: this shouldn't be a #define, or it shouldn't be here void optimize_accelcand(accelcand * cand, accelobs * obs) { int ii; int *r_offset; fcomplex **data; double r, z; cand->pows = gen_dvect(cand->numharm); cand->hirs = gen_dvect(cand->numharm); cand->hizs = gen_dvect(cand->numharm); r_offset = (int*) malloc(sizeof(int)*cand->numharm); data = (fcomplex**) malloc(sizeof(fcomplex*)*cand->numharm); cand->derivs = (rderivs *) malloc(sizeof(rderivs) * cand->numharm); if (obs->use_harmonic_polishing) { if (obs->mmap_file || obs->dat_input) { for(ii=0;ii<cand->numharm;ii++) { r_offset[ii]=obs->lobin; data[ii] = obs->fft; } max_rz_arr_harmonics(data, cand->numharm, r_offset, obs->numbins, cand->r-obs->lobin, cand->z, &r, &z, cand->derivs, cand->pows); } else { max_rz_file_harmonics(obs->fftfile, cand->numharm, obs->lobin, cand->r-obs->lobin, cand->z, &r, &z, cand->derivs, cand->pows); } for(ii=0;ii<cand->numharm;ii++) { cand->hirs[ii]=(r+obs->lobin)*(ii+1); cand->hizs[ii]=z*(ii+1); } } else { for (ii = 0; ii < cand->numharm; ii++) { if (obs->mmap_file || obs->dat_input) cand->pows[ii] = max_rz_arr(obs->fft, obs->numbins, cand->r * (ii + 1) - obs->lobin, cand->z * (ii + 1), &(cand->hirs[ii]), &(cand->hizs[ii]), &(cand->derivs[ii])); else cand->pows[ii] = max_rz_file(obs->fftfile, cand->r * (ii + 1) - obs->lobin, cand->z * (ii + 1), &(cand->hirs[ii]), &(cand->hizs[ii]), &(cand->derivs[ii])); cand->hirs[ii] += obs->lobin; } } free(r_offset); free(data); cand->sigma = candidate_sigma(cand->power, cand->numharm, obs->numindep[twon_to_index(cand->numharm)]); }
/* NEW Clipping Routine (uses channel running averages) */ int clip_times(float *rawdata, int ptsperblk, int numchan, float clip_sigma, float *good_chan_levels) // Perform time-domain clipping of rawdata. This is a 2D array with // ptsperblk*numchan points, each of which is a float. The clipping // is done at clip_sigma sigma above/below the running mean. The // up-to-date running averages of the channels are returned in // good_chan_levels (which must be pre-allocated). { static float *chan_running_avg; static float running_avg = 0.0, running_std = 0.0; static int blocksread = 0, firsttime = 1; static long long current_point = 0; static int numonoff = 0, onoffindex = 0; static long long *onbins = NULL, *offbins = NULL; float *zero_dm_block, *ftmp, *powptr; double *chan_avg_temp; float current_med, trigger; double current_avg = 0.0, current_std = 0.0; int ii, jj, clipit = 0, clipped = 0; if (firsttime) { chan_running_avg = gen_fvect(numchan); firsttime = 0; { // This is experimental code to zap radar-filled data char *envval = getenv("CLIPBINSFILE"); if (envval != NULL) { FILE *onofffile = chkfopen(envval, "r"); numonoff = read_onoff_paris(onofffile, &onbins, &offbins); fclose(onofffile); printf("\nRead %d bin clipping pairs from '%s'.\n", numonoff, envval); //for (ii=0;ii<numonoff;ii++) printf("%lld %lld\n", onbins[ii], offbins[ii]); } } } chan_avg_temp = gen_dvect(numchan); zero_dm_block = gen_fvect(ptsperblk); ftmp = gen_fvect(ptsperblk); /* Calculate the zero DM time series */ for (ii = 0; ii < ptsperblk; ii++) { zero_dm_block[ii] = 0.0; powptr = rawdata + ii * numchan; for (jj = 0; jj < numchan; jj++) zero_dm_block[ii] += *powptr++; ftmp[ii] = zero_dm_block[ii]; } avg_var(ftmp, ptsperblk, ¤t_avg, ¤t_std); current_std = sqrt(current_std); current_med = median(ftmp, ptsperblk); /* Calculate the current standard deviation and mean */ /* but only for data points that are within a certain */ /* fraction of the median value. This removes the */ /* really strong RFI from the calculation. */ { float lo_cutoff, hi_cutoff; int numgoodpts = 0; lo_cutoff = current_med - 3.0 * current_std; hi_cutoff = current_med + 3.0 * current_std;; for (jj = 0; jj < numchan; jj++) chan_avg_temp[jj] = 0.0; /* Find the "good" points */ for (ii = 0; ii < ptsperblk; ii++) { if (zero_dm_block[ii] > lo_cutoff && zero_dm_block[ii] < hi_cutoff) { ftmp[numgoodpts] = zero_dm_block[ii]; powptr = rawdata + ii * numchan; for (jj = 0; jj < numchan; jj++) chan_avg_temp[jj] += *powptr++; numgoodpts++; } } //printf("avg = %f med = %f std = %f numgoodpts = %d\n", // current_avg, current_med, current_std, numgoodpts); /* Calculate the current average and stddev */ if (numgoodpts < 1) { current_avg = running_avg; current_std = running_std; for (jj = 0; jj < numchan; jj++) chan_avg_temp[jj] = chan_running_avg[jj]; } else { avg_var(ftmp, numgoodpts, ¤t_avg, ¤t_std); current_std = sqrt(current_std); for (jj = 0; jj < numchan; jj++) chan_avg_temp[jj] /= numgoodpts; } } /* Update a pseudo running average and stdev */ if (blocksread) { running_avg = 0.9 * running_avg + 0.1 * current_avg; running_std = 0.9 * running_std + 0.1 * current_std; for (ii = 0; ii < numchan; ii++) chan_running_avg[ii] = 0.9 * chan_running_avg[ii] + 0.1 * chan_avg_temp[ii]; } else { running_avg = current_avg; running_std = current_std; for (ii = 0; ii < numchan; ii++) chan_running_avg[ii] = chan_avg_temp[ii]; if (current_avg == 0.0) printf("Warning: problem with clipping in first block!!!\n\n"); } /* See if any points need clipping */ trigger = clip_sigma * running_std; for (ii = 0; ii < ptsperblk; ii++) { if (fabs(zero_dm_block[ii] - running_avg) > trigger) { clipit = 1; break; } } /* or alternatively from the CLIPBINSFILE */ if (numonoff && ((current_point > onbins[onoffindex] && current_point <= offbins[onoffindex]) || (current_point + ptsperblk > onbins[onoffindex] && current_point + ptsperblk <= offbins[onoffindex]) || (current_point < onbins[onoffindex] && current_point + ptsperblk > offbins[onoffindex]))) clipit = 1; /* Update the good channel levels */ for (ii = 0; ii < numchan; ii++) good_chan_levels[ii] = chan_running_avg[ii]; /* Replace the bad channel data with channel median values */ /* that are scaled to equal the running_avg. */ if (clipit) { for (ii = 0; ii < ptsperblk; ii++) { if ((fabs(zero_dm_block[ii] - running_avg) > trigger) || (numonoff && (current_point > onbins[onoffindex] && current_point <= offbins[onoffindex]))) { powptr = rawdata + ii * numchan; for (jj = 0; jj < numchan; jj++) *powptr++ = good_chan_levels[jj]; clipped++; //fprintf(stderr, "zapping %lld\n", current_point); } current_point++; if (numonoff && current_point > offbins[onoffindex] && onoffindex < numonoff - 1) { while (current_point > offbins[onoffindex] && onoffindex < numonoff - 1) onoffindex++; //printf("updating index to %d\n", onoffindex); } } } else { current_point += ptsperblk; if (numonoff && current_point > offbins[onoffindex] && onoffindex < numonoff - 1) { while (current_point > offbins[onoffindex] && onoffindex < numonoff - 1) onoffindex++; //printf("updating index to %d\n", onoffindex); } } blocksread++; vect_free(chan_avg_temp); vect_free(zero_dm_block); vect_free(ftmp); return clipped; }
float *periodogram(double *xx, double *tt, int nn, double lof, double df, int numf) /* Return the normalized Lomb-Scargle Periodogram powers of 'numf' frequencies (Hz) from the lowest freq 'lof' upwards by stepsize 'df'. There are 'nn' input data points with amplitudes 'xx' and times 'tt' (s). The returned power vector is dynamically allocated. */ { int ii, jj; float *pows; double avg, var, ivar, c, cc, cwtau; double s, ss, sumc, sumcxx, sums, sumsh, sumsxx,swtau; double wtau, ttavg, ttmax, ttmin; double arg, wtemp, *xxnorm, *wi, *wpi, *wpr, *wr; /* Set-up */ davg_dvar(xx, nn, &avg, &var); if (var==0.0) ivar = 0.5; else ivar = 0.5 / var; wr = gen_dvect(nn); wi = gen_dvect(nn); wpr = gen_dvect(nn); wpi = gen_dvect(nn); xxnorm = gen_dvect(nn); pows = gen_fvect(numf); /* Scale the times around the midpt */ ttmax = ttmin = tt[0]; for (ii = 0; ii < nn; ii++){ if (tt[ii] > ttmax) ttmax = tt[ii]; if (tt[ii] < ttmin) ttmin = tt[ii]; } ttavg = 0.5 * (ttmax + ttmin); /* Generate the trig recurrence values */ c = cos(TWOPI * lof); s = sin(TWOPI * lof); for (ii = 0; ii < nn; ii++){ arg = TWOPI * ((tt[ii] - ttavg) * df); wtemp = sin(0.5 * arg); wpr[ii] = -2.0 * wtemp * wtemp; wpi[ii] = sin(arg); wtemp = TWOPI * ((tt[ii] - ttavg) * lof); wr[ii] = cos(wtemp); wi[ii] = sin(wtemp); if (var==0.0) xxnorm[ii] = 1.0; else xxnorm[ii] = xx[ii] - avg; } /* Calculate the periodogram */ for (ii = 0; ii < numf; ii++){ sumsh = sumc = 0.0; for (jj=0; jj<nn; jj++){ c = wr[jj]; s = wi[jj]; sumsh += s * c; sumc += (c - s) * (c + s); } wtau = 0.5 * atan2(2.0 * sumsh, sumc); cwtau = cos(wtau); swtau = sin(wtau); sums = sumc = sumsxx = sumcxx = 0.0; /* Step through the data points */ for (jj = 0; jj < nn; jj++){ c = wr[jj]; s = wi[jj]; ss = s * cwtau - c * swtau; cc = c * cwtau + s * swtau; sums += ss * ss; sumc += cc * cc; sumsxx += xxnorm[jj] * ss; sumcxx += xxnorm[jj] * cc; wr[jj] += c * wpr[jj] - s * wpi[jj]; wi[jj] += s * wpr[jj] + c * wpi[jj]; } /* Set the current power */ pows[ii] = ivar * (sumcxx * sumcxx / sumc + sumsxx * sumsxx / sums); } /* Free the temp arrays and return */ free(wr); free(wi); free(wpr); free(wpi); free(xxnorm); return(pows); }
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[]) { FILE *infile; int numchan, numtodisplay = 0, numprofs = 0; long i, j, proflen, offset; double *profs, *sumprof, nc, pl, tt, bt, p, f, df, rotate = 0.0; double dm = 0.0, bindelay = 0.0; char device[200], output[200]; if (argc <= 2) { printf("usage: showmulti_dm filename dm [rotate] [numtodisplay] [device]\n"); printf(" 'filename' (required) is the multi-profile save file.\n"); printf(" 'dm' (required) DM to base profile delays on.\n"); printf(" 'rotate' (optional) is the number of bins to rotate\n"); printf(" each profile to the left.\n"); printf(" Can be fractional. Default is 0.\n"); printf(" 'numtodisplay' (optional) is the number of profiles to\n"); printf(" display at once. Defaults to\n"); printf(" the number of channels.\n"); printf(" 'device' (optional) is the pgplot device to use ('x' or\n"); printf(" 'ps'). Defaults to 'x'\n"); exit(1); } infile = chkfopen(argv[1], "rb"); sprintf(output, "%s.ps", argv[1]); chkfread(&nc, sizeof(double), 1, infile); chkfread(&pl, sizeof(double), 1, infile); chkfread(&p, sizeof(double), 1, infile); chkfread(&tt, sizeof(double), 1, infile); chkfread(&bt, sizeof(double), 1, infile); chkfread(&f, sizeof(double), 1, infile); chkfread(&df, sizeof(double), 1, infile); numchan = nc; proflen = pl; if (argc == 3) { dm = strtod(argv[2], NULL); rotate = 0.0; strcpy(device, "x"); } else if (argc == 4) { dm = strtod(argv[2], NULL); rotate = strtod(argv[3], NULL); numtodisplay = numchan; strcpy(device, "x"); } else if (argc == 5) { dm = strtod(argv[2], NULL); rotate = strtod(argv[3], NULL); numtodisplay = (int) strtol(argv[4], NULL, 10); strcpy(device, "x"); } else if (argc == 6) { dm = strtod(argv[2], NULL); rotate = strtod(argv[3], NULL); numtodisplay = (int) strtol(argv[4], NULL, 10); strcpy(device, argv[5]); } printf("\n Multi-Profile Display Program\n"); printf(" With DM Delay Correction\n"); printf(" Scott M. Ransom\n"); printf(" 20 July 1998\n"); printf("\nProfile properties:\n"); printf("Initial folding period (s) = %-15.13f\n", p); printf("Topocentric time (start) = %-15.10f\n", tt); printf("Barycentric time (start) = %-15.10f\n", bt); printf("Profile length (bins) = %-ld\n", proflen); printf("Number of channels = %-d\n", numchan); printf("Channel 1 frequency (MHz) = %-10.5f\n", f); printf("Channel freq width (MHz) = %-10.5f\n", df); printf("Dispersion Measure (cm-3 pc) = %-10.5f\n\n", dm); /* Read the profiles. */ profs = gen_dvect(proflen * numchan); chkfread(profs, sizeof(double), (unsigned long) (numchan * proflen), infile); fclose(infile); /* Create a Summed-Profile vector */ sumprof = gen_dvect(proflen); for (i = 0; i < proflen; i++) { sumprof[i] = 0.0; } /* Rotate the vectors and sum the profiles */ for (i = 0; i < numchan; i++) { bindelay = delay_from_dm(dm, f + i * df) * (double) proflen / p; drotate(&profs[i * proflen], proflen, bindelay); if (rotate) drotate(&profs[i * proflen], proflen, rotate); for (j = 0; j < proflen; j++) { sumprof[j] += profs[i * proflen + j]; } } /* Plot the profiles */ if (0 == strcmp("x", device)) cpgstart_x("portrait"); else cpgstart_ps(output, "portrait"); for (i = 0; i <= numchan / numtodisplay; i++) { offset = i * numtodisplay; numprofs = (numchan - offset) > numtodisplay ? numtodisplay : numchan - offset; if (numprofs > 0) { cpgpage(); multi_prof_plot(proflen, numprofs, profs + offset * proflen, sumprof, "Pulse Phase (Periods)", (double) (1.0 + offset), 1.0, "Channel Number", f + offset * df, df, "Frequency (MHz)"); } } cpgend(); /* Cleanup */ vect_free(profs); vect_free(sumprof); return 0; }
void read_prepfoldinfo(prepfoldinfo * in, char *filename) /* Read a prepfoldinfo data structure from a binary file */ { FILE *infile; int itmp, byteswap = 0; char temp[16]; infile = chkfopen(filename, "rb"); in->numdms = read_int(infile, byteswap); in->numperiods = read_int(infile, byteswap); in->numpdots = read_int(infile, byteswap); in->nsub = read_int(infile, byteswap); in->npart = read_int(infile, byteswap); /* The following is not exactly the most robust, but it should work... */ if (in->npart < 1 || in->npart > 10000) { byteswap = 1; in->numdms = swap_int(in->numdms); in->numperiods = swap_int(in->numperiods); in->numpdots = swap_int(in->numpdots); in->nsub = swap_int(in->nsub); in->npart = swap_int(in->npart); } in->proflen = read_int(infile, byteswap); in->numchan = read_int(infile, byteswap); in->pstep = read_int(infile, byteswap); in->pdstep = read_int(infile, byteswap); in->dmstep = read_int(infile, byteswap); in->ndmfact = read_int(infile, byteswap); in->npfact = read_int(infile, byteswap); itmp = read_int(infile, byteswap); in->filenm = calloc(itmp + 1, sizeof(char)); chkfread(in->filenm, sizeof(char), itmp, infile); itmp = read_int(infile, byteswap); in->candnm = calloc(itmp + 1, sizeof(char)); chkfread(in->candnm, sizeof(char), itmp, infile); itmp = read_int(infile, byteswap); in->telescope = calloc(itmp + 1, sizeof(char)); chkfread(in->telescope, sizeof(char), itmp, infile); itmp = read_int(infile, byteswap); in->pgdev = calloc(itmp + 1, sizeof(char)); chkfread(in->pgdev, sizeof(char), itmp, infile); //chkfread(in->rastr, sizeof(char), 16, infile); { int has_posn = 1, ii; chkfread(temp, sizeof(char), 16, infile); /* Check to see if a position string was written */ for (ii = 0; ii < 16; ii++){ if (!isdigit(temp[ii]) && temp[ii] != ':' && temp[ii] != '.' && temp[ii] != '-' && temp[ii] != '\0'){ has_posn = 0; break; } } if (has_posn){ strcpy(in->rastr, temp); chkfread(in->decstr, sizeof(char), 16, infile); in->dt = read_double(infile, byteswap); in->startT = read_double(infile, byteswap); } else { strcpy(in->rastr, "Unknown"); strcpy(in->decstr, "Unknown"); in->dt = *(double *)(temp + 0); if (byteswap) in->dt = swap_double(in->dt); in->startT = *(double *)(temp + sizeof(double)); if (byteswap) in->startT = swap_double(in->startT); } } in->endT = read_double(infile, byteswap); in->tepoch = read_double(infile, byteswap); in->bepoch = read_double(infile, byteswap); in->avgvoverc = read_double(infile, byteswap); in->lofreq = read_double(infile, byteswap); in->chan_wid = read_double(infile, byteswap); in->bestdm = read_double(infile, byteswap); /* The .pow elements were written as doubles (Why??) */ in->topo.pow = read_float(infile, byteswap); read_float(infile, byteswap); in->topo.p1 = read_double(infile, byteswap); in->topo.p2 = read_double(infile, byteswap); in->topo.p3 = read_double(infile, byteswap); /* The .pow elements were written as doubles (Why??) */ in->bary.pow = read_float(infile, byteswap); read_float(infile, byteswap); in->bary.p1 = read_double(infile, byteswap); in->bary.p2 = read_double(infile, byteswap); in->bary.p3 = read_double(infile, byteswap); /* The .pow elements were written as doubles (Why??) */ in->fold.pow = read_float(infile, byteswap); read_float(infile, byteswap); in->fold.p1 = read_double(infile, byteswap); in->fold.p2 = read_double(infile, byteswap); in->fold.p3 = read_double(infile, byteswap); in->orb.p = read_double(infile, byteswap); in->orb.e = read_double(infile, byteswap); in->orb.x = read_double(infile, byteswap); in->orb.w = read_double(infile, byteswap); in->orb.t = read_double(infile, byteswap); in->orb.pd = read_double(infile, byteswap); in->orb.wd = read_double(infile, byteswap); in->dms = gen_dvect(in->numdms); chkfread(in->dms, sizeof(double), in->numdms, infile); in->periods = gen_dvect(in->numperiods); chkfread(in->periods, sizeof(double), in->numperiods, infile); in->pdots = gen_dvect(in->numpdots); chkfread(in->pdots, sizeof(double), in->numpdots, infile); in->rawfolds = gen_dvect(in->nsub * in->npart * in->proflen); chkfread(in->rawfolds, sizeof(double), in->nsub * in->npart * in->proflen, infile); in->stats = (foldstats *) malloc(sizeof(foldstats) * in->nsub * in->npart); chkfread(in->stats, sizeof(foldstats), in->nsub * in->npart, infile); fclose(infile); if (byteswap) { int ii; for (ii = 0; ii < in->numdms; ii++) in->dms[ii] = swap_double(in->dms[ii]); for (ii = 0; ii < in->numperiods; ii++) in->periods[ii] = swap_double(in->periods[ii]); for (ii = 0; ii < in->numpdots; ii++) in->pdots[ii] = swap_double(in->pdots[ii]); for (ii = 0; ii < in->nsub * in->npart * in->proflen; ii++) in->rawfolds[ii] = swap_double(in->rawfolds[ii]); for (ii = 0; ii < in->nsub * in->npart; ii++) { in->stats[ii].numdata = swap_double(in->stats[ii].numdata); in->stats[ii].data_avg = swap_double(in->stats[ii].data_avg); in->stats[ii].data_var = swap_double(in->stats[ii].data_var); in->stats[ii].numprof = swap_double(in->stats[ii].numprof); in->stats[ii].prof_avg = swap_double(in->stats[ii].prof_avg); in->stats[ii].prof_var = swap_double(in->stats[ii].prof_var); in->stats[ii].redchi = swap_double(in->stats[ii].redchi); } } }
int main(int argc, char *argv[]) { /* Any variable that begins with 't' means topocentric */ /* Any variable that begins with 'b' means barycentric */ FILE *outfile; float *outdata = NULL; double tdf = 0.0, dtmp = 0.0, barydispdt = 0.0, dsdt = 0.0; double *dispdt, *tobsf = NULL, tlotoa = 0.0, blotoa = 0.0; double max = -9.9E30, min = 9.9E30, var = 0.0, avg = 0.0; char obs[3], ephem[10], *datafilenm, *outinfonm; char rastring[50], decstring[50]; int numchan = 1, newper = 0, oldper = 0, nummasked = 0, useshorts = 0; int numadded = 0, numremoved = 0, padding = 0, *maskchans = NULL, offset = 0; long slen, ii, numbarypts = 0, worklen = 65536; long numread = 0, numtowrite = 0, totwrote = 0, datawrote = 0; long padwrote = 0, padtowrite = 0, statnum = 0; int numdiffbins = 0, *diffbins = NULL, *diffbinptr = NULL, good_padvals = 0; int *idispdt; struct spectra_info s; infodata idata; Cmdline *cmd; mask obsmask; /* Call usage() if we have no command line arguments */ if (argc == 1) { Program = argv[0]; printf("\n"); usage(); exit(0); } /* Parse the command line using the excellent program Clig */ cmd = parseCmdline(argc, argv); spectra_info_set_defaults(&s); s.filenames = cmd->argv; s.num_files = cmd->argc; // If we are zeroDMing, make sure that clipping is off. if (cmd->zerodmP) cmd->noclipP = 1; 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 (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->ncpus > 1) { #ifdef _OPENMP int maxcpus = omp_get_num_procs(); int openmp_numthreads = (cmd->ncpus <= maxcpus) ? cmd->ncpus : maxcpus; // Make sure we are not dynamically setting the number of threads omp_set_dynamic(0); omp_set_num_threads(openmp_numthreads); printf("Using %d threads with OpenMP\n\n", openmp_numthreads); #endif } else { #ifdef _OPENMP omp_set_num_threads(1); // Explicitly turn off OpenMP #endif } #ifdef DEBUG showOptionValues(); #endif printf("\n\n"); printf(" Pulsar Data Preparation Routine\n"); printf(" Type conversion, de-dispersion, barycentering.\n"); printf(" by Scott M. Ransom\n\n"); if (RAWDATA) { if (cmd->filterbankP) s.datatype = SIGPROCFB; else if (cmd->psrfitsP) s.datatype = PSRFITS; } 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 == SDAT) useshorts = 1; else if (s.datatype != DAT) { printf ("Error: Unable to identify input data files. Please specify type.\n\n"); exit(1); } } if (!RAWDATA) { char *root, *suffix; /* Split the filename into a rootname and a suffix */ if (split_root_suffix(s.filenames[0], &root, &suffix) == 0) { printf("\nThe input filename (%s) must have a suffix!\n\n", s.filenames[0]); exit(1); } printf("Reading input data from '%s'.\n", s.filenames[0]); printf("Reading information from '%s.inf'.\n\n", root); /* Read the info file if available */ readinf(&idata, root); free(root); free(suffix); s.files = (FILE **) malloc(sizeof(FILE *)); s.files[0] = chkfopen(s.filenames[0], "rb"); } else { 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]); } printf("\n"); } /* Determine the other file names and open the output data file */ slen = strlen(cmd->outfile) + 8; datafilenm = (char *) calloc(slen, 1); sprintf(datafilenm, "%s.dat", cmd->outfile); outfile = chkfopen(datafilenm, "wb"); sprintf(idata.name, "%s", cmd->outfile); outinfonm = (char *) calloc(slen, 1); sprintf(outinfonm, "%s.inf", cmd->outfile); if (RAWDATA) { read_rawdata_files(&s); if (cmd->ignorechanstrP) { s.ignorechans = get_ignorechans(cmd->ignorechanstr, 0, s.num_channels-1, &s.num_ignorechans, &s.ignorechans_str); if (s.ignorechans_str==NULL) { s.ignorechans_str = (char *)malloc(strlen(cmd->ignorechanstr)+1); strcpy(s.ignorechans_str, cmd->ignorechanstr); } } print_spectra_info_summary(&s); spectra_info_to_inf(&s, &idata); /* Finish setting up stuff common to all raw formats */ idata.dm = cmd->dm; worklen = s.spectra_per_subint; /* If we are offsetting into the file, change inf file start time */ if (cmd->start > 0.0 || cmd->offset > 0) { if (cmd->start > 0.0) /* Offset in units of worklen */ cmd->offset = (long) (cmd->start * idata.N / worklen) * worklen; add_to_inf_epoch(&idata, cmd->offset * idata.dt); offset_to_spectra(cmd->offset, &s); printf("Offsetting into the input files by %ld spectra (%.6g sec)\n", cmd->offset, cmd->offset * idata.dt); } if (cmd->maskfileP) maskchans = gen_ivect(idata.num_chan); /* Compare the size of the data to the size of output we request */ if (cmd->numoutP) { dtmp = idata.N; idata.N = cmd->numout; writeinf(&idata); idata.N = dtmp; } else { /* Set the output length to a good number if it wasn't requested */ cmd->numoutP = 1; cmd->numout = choose_good_N((long long)(idata.N/cmd->downsamp)); writeinf(&idata); printf("Setting a 'good' output length of %ld samples\n", cmd->numout); } /* The number of topo to bary time points to generate with TEMPO */ numbarypts = (long) (idata.dt * idata.N * 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); } } /* Read an input mask if wanted */ if (cmd->maskfileP) { read_mask(cmd->maskfile, &obsmask); printf("Read mask information from '%s'\n\n", cmd->maskfile); good_padvals = determine_padvals(cmd->maskfile, &obsmask, s.padvals); } else { obsmask.numchan = obsmask.numint = 0; } /* Determine our initialization data if we do _not_ have Parkes, */ /* Green Bank BCPM, or Arecibo WAPP data sets. */ if (!RAWDATA) { /* If we will be barycentering... */ if (!cmd->nobaryP) { /* The number of topo to bary time points to generate with TEMPO */ numbarypts = (long) (idata.dt * idata.N * 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); } } /* The number of data points to work with at a time */ if (worklen > idata.N) worklen = idata.N; worklen = (long) (worklen / 1024) * 1024; /* If we are offsetting into the file, change inf file start time */ if (cmd->start > 0.0 || cmd->offset > 0) { if (cmd->start > 0.0) /* Offset in units of worklen */ cmd->offset = (long) (cmd->start * idata.N / worklen) * worklen; add_to_inf_epoch(&idata, cmd->offset * idata.dt); printf("Offsetting into the input files by %ld samples (%.6g sec)\n", cmd->offset, cmd->offset * idata.dt); if (useshorts) { chkfileseek(s.files[0], cmd->offset, sizeof(short), SEEK_SET); } else { chkfileseek(s.files[0], cmd->offset, sizeof(float), SEEK_SET); } } /* Set the output length to a good number if it wasn't requested */ if (!cmd->numoutP) { cmd->numoutP = 1; cmd->numout = choose_good_N((long long)(idata.N/cmd->downsamp)); printf("Setting a 'good' output length of %ld samples\n", cmd->numout); } } /* Check if we are downsampling */ dsdt = idata.dt * cmd->downsamp; if (cmd->downsamp > 1) { printf("Downsampling by a factor of %d\n", cmd->downsamp); printf("New sample dt = %.10g\n\n", dsdt); if (worklen % cmd->downsamp) { printf("Error: The downsample factor (%d) must be a factor of the\n", cmd->downsamp); printf(" worklength (%ld). Exiting.\n\n", worklen); exit(1); } } printf("Writing output data to '%s'.\n", datafilenm); printf("Writing information to '%s'.\n\n", outinfonm); /* The topocentric epoch of the start of the data */ tlotoa = (double) idata.mjd_i + idata.mjd_f; if (!strcmp(idata.band, "Radio") && RAWDATA) { /* The topocentric spacing between channels */ tdf = idata.chan_wid; numchan = idata.num_chan; /* The topocentric observation frequencies */ tobsf = gen_dvect(numchan); tobsf[0] = idata.freq; for (ii = 0; ii < numchan; ii++) tobsf[ii] = tobsf[0] + ii * tdf; /* The dispersion delays (in time bins) */ dispdt = gen_dvect(numchan); // full float bins idispdt = gen_ivect(numchan); // nearest integer bins if (cmd->nobaryP) { /* Determine our dispersion time delays for each channel */ for (ii = 0; ii < numchan; ii++) dispdt[ii] = delay_from_dm(cmd->dm, tobsf[ii]); /* The highest frequency channel gets no delay */ /* All other delays are positive fractions of bin length (dt) */ dtmp = dispdt[numchan - 1]; for (ii = 0; ii < numchan; ii++) { dispdt[ii] = (dispdt[ii] - dtmp) / idata.dt; idispdt[ii] = (int) (dispdt[ii] + 0.5); } worklen *= ((int) (fabs(dispdt[0])) / worklen) + 1; } } else { /* For unknown radio raw data (Why is this here?) */ tobsf = gen_dvect(numchan); dispdt = gen_dvect(numchan); idispdt = gen_ivect(numchan); dispdt[0] = 0.0; idispdt[0] = 0; if (!strcmp(idata.band, "Radio")) { tobsf[0] = idata.freq + (idata.num_chan - 1) * idata.chan_wid; cmd->dm = idata.dm; } else { tobsf[0] = 0.0; cmd->dm = 0.0; } } if (cmd->nobaryP) { /* Main loop if we are not barycentering... */ /* Allocate our data array */ outdata = gen_fvect(worklen); printf("Massaging the data ...\n\n"); printf("Amount Complete = 0%%"); do { if (RAWDATA) numread = read_psrdata(outdata, worklen, &s, idispdt, &padding, maskchans, &nummasked, &obsmask); else if (useshorts) numread = read_shorts(s.files[0], outdata, worklen, numchan); else numread = read_floats(s.files[0], outdata, worklen, numchan); if (numread == 0) break; /* Downsample if requested */ if (cmd->downsamp > 1) numread = downsample(outdata, numread, cmd->downsamp); /* Print percent complete */ newper = (int) ((float) totwrote / cmd->numout * 100.0) + 1; if (newper > oldper) { printf("\rAmount Complete = %3d%%", newper); fflush(stdout); oldper = newper; } /* Write the latest chunk of data, but don't */ /* write more than cmd->numout points. */ numtowrite = numread; if ((totwrote + numtowrite) > cmd->numout) numtowrite = cmd->numout - totwrote; chkfwrite(outdata, sizeof(float), numtowrite, outfile); totwrote += numtowrite; /* Update the statistics */ if (!padding) { for (ii = 0; ii < numtowrite; ii++) update_stats(statnum + ii, outdata[ii], &min, &max, &avg, &var); statnum += numtowrite; } /* Stop if we have written out all the data we need to */ if (totwrote == cmd->numout) break; } while (numread); datawrote = totwrote; } else { /* Main loop if we are barycentering... */ double avgvoverc = 0.0, maxvoverc = -1.0, minvoverc = 1.0, *voverc = NULL; double *bobsf = NULL, *btoa = NULL, *ttoa = NULL; /* 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 */ bobsf = gen_dvect(numchan); btoa = gen_dvect(numbarypts); ttoa = gen_dvect(numbarypts); voverc = gen_dvect(numbarypts); for (ii = 0; ii < numbarypts; ii++) ttoa[ii] = tlotoa + TDT * ii / SECPERDAY; /* Call TEMPO for the barycentering */ printf("Generating barycentric corrections...\n"); 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); blotoa = btoa[0]; 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("Collecting and barycentering %s...\n\n", cmd->argv[0]); /* Determine the initial dispersion time delays for each channel */ for (ii = 0; ii < numchan; ii++) { bobsf[ii] = doppler(tobsf[ii], avgvoverc); dispdt[ii] = delay_from_dm(cmd->dm, bobsf[ii]); } /* The highest frequency channel gets no delay */ /* All other delays are positive fractions of bin length (dt) */ barydispdt = dispdt[numchan - 1]; for (ii = 0; ii < numchan; ii++) { dispdt[ii] = (dispdt[ii] - barydispdt) / idata.dt; idispdt[ii] = (int) (dispdt[ii] + 0.5); } if (RAWDATA) worklen *= ((int) (dispdt[0]) / worklen) + 1; /* If the data is de-dispersed radio data... */ if (!strcmp(idata.band, "Radio")) { printf("The DM of %.2f at the barycentric observing freq of %.3f MHz\n", idata.dm, bobsf[numchan - 1]); printf(" causes a delay of %f seconds compared to infinite freq.\n", barydispdt); printf(" This delay is removed from the barycented times.\n\n"); } printf("Topocentric epoch (at data start) is:\n"); printf(" %17.11f\n\n", tlotoa); printf("Barycentric epoch (infinite obs freq at data start) is:\n"); printf(" %17.11f\n\n", blotoa - (barydispdt / SECPERDAY)); /* Convert the bary TOAs to differences from the topo TOAs in */ /* units of bin length (dsdt) 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 */ printf("Massaging the data...\n\n"); printf("Amount Complete = 0%%"); /* Allocate our data array */ outdata = gen_fvect(worklen); do { /* Loop to read and write the data */ int numwritten = 0; double block_avg, block_var; if (RAWDATA) numread = read_psrdata(outdata, worklen, &s, idispdt, &padding, maskchans, &nummasked, &obsmask); else if (useshorts) numread = read_shorts(s.files[0], outdata, worklen, numchan); else numread = read_floats(s.files[0], outdata, worklen, numchan); if (numread == 0) break; /* Downsample if requested */ if (cmd->downsamp > 1) numread = downsample(outdata, numread, cmd->downsamp); /* Determine the approximate local average */ avg_var(outdata, numread, &block_avg, &block_var); /* Print percent complete */ newper = (int) ((float) totwrote / cmd->numout * 100.0) + 1; if (newper > oldper) { printf("\rAmount Complete = %3d%%", newper); fflush(stdout); oldper = newper; } /* 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; /* FIXME: numtowrite+totwrote can wrap! */ if ((totwrote + numtowrite) > cmd->numout) numtowrite = cmd->numout - totwrote; if (numtowrite > numread) numtowrite = numread; chkfwrite(outdata, sizeof(float), numtowrite, outfile); datawrote += numtowrite; totwrote += numtowrite; numwritten += numtowrite; /* Update the statistics */ if (!padding) { for (ii = 0; ii < numtowrite; ii++) update_stats(statnum + ii, outdata[ii], &min, &max, &avg, &var); statnum += numtowrite; } if ((datawrote == abs(*diffbinptr)) && (numwritten != numread) && (totwrote < cmd->numout)) { /* Add/remove a bin */ float favg; int skip, nextdiffbin; skip = numtowrite; do { /* Write the rest of the data after adding/removing a bin */ if (*diffbinptr > 0) { /* Add a bin */ favg = (float) block_avg; chkfwrite(&favg, sizeof(float), 1, outfile); numadded++; totwrote++; } else { /* Remove a bin */ numremoved++; datawrote++; numwritten++; skip++; } diffbinptr++; /* Write the part after the diffbin */ numtowrite = numread - numwritten; if ((totwrote + numtowrite) > cmd->numout) numtowrite = cmd->numout - totwrote; nextdiffbin = abs(*diffbinptr) - datawrote; if (numtowrite > nextdiffbin) numtowrite = nextdiffbin; chkfwrite(outdata + skip, sizeof(float), numtowrite, outfile); numwritten += numtowrite; datawrote += numtowrite; totwrote += numtowrite; /* Update the statistics and counters */ if (!padding) { for (ii = 0; ii < numtowrite; ii++) update_stats(statnum + ii, outdata[skip + ii], &min, &max, &avg, &var); statnum += numtowrite; } skip += numtowrite; /* Stop if we have written out all the data we need to */ if (totwrote == cmd->numout) break; } while (numwritten < numread); } /* Stop if we have written out all the data we need to */ if (totwrote == cmd->numout) break; } while (numread); /* Free the arrays used in barycentering */ vect_free(bobsf); vect_free(btoa); vect_free(ttoa); } /* Calculate what the amount of padding we need */ if (cmd->numout > totwrote) padwrote = padtowrite = cmd->numout - totwrote; /* Write the new info file for the output data */ if (!cmd->nobaryP) { idata.bary = 1; idata.mjd_i = (int) floor(blotoa - (barydispdt / SECPERDAY)); idata.mjd_f = blotoa - (barydispdt / SECPERDAY) - idata.mjd_i; } if (cmd->downsamp > 1) idata.dt = dsdt; update_infodata(&idata, totwrote, padtowrite, diffbins, numdiffbins); writeinf(&idata); /* Set the padded points equal to the average data point */ if (idata.numonoff >= 1) { int jj, index, startpad, endpad; for (ii = 0; ii < worklen; ii++) outdata[ii] = avg; fclose(outfile); outfile = 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]; chkfseek(outfile, (startpad + 1) * sizeof(float), SEEK_SET); padtowrite = endpad - startpad; for (jj = 0; jj < padtowrite / worklen; jj++) chkfwrite(outdata, sizeof(float), worklen, outfile); chkfwrite(outdata, sizeof(float), padtowrite % worklen, outfile); } } vect_free(outdata); // Close all the raw files and free their vectors close_rawfiles(&s); /* Print simple stats and results */ var /= (datawrote - 1); /* Conver the '.dat' file to '.sdat' if requested */ if (cmd->shortsP) { FILE *infile; int safe_convert = 1, bufflen = 65536; char *sdatafilenm; float *fbuffer; short *sbuffer; offset = (int) (floor(avg)); if ((max - min) > (SHRT_MAX - SHRT_MIN)) { if ((max - min) < 1.5 * (SHRT_MAX - SHRT_MIN)) { printf("Warning: There is more dynamic range in the data\n" " than can be handled perfectly:\n" " max - min = %.2f - %.2f = %.2f\n" " Clipping the low values...\n\n", max, min, max - min); offset = max - SHRT_MAX; } else { printf("Error: There is way too much dynamic range in the data:\n" " max - min = %.2f - %.2f = %.2f\n" " Not converting to shorts.\n\n", max, min, max - min); safe_convert = 0; } } if (safe_convert) { fbuffer = gen_fvect(bufflen); sbuffer = gen_svect(bufflen); sdatafilenm = (char *) calloc(slen, 1); sprintf(sdatafilenm, "%s.sdat", cmd->outfile); printf("\n\nConverting floats in '%s' to shorts in '%s'.", datafilenm, sdatafilenm); fflush(NULL); infile = chkfopen(datafilenm, "rb"); outfile = chkfopen(sdatafilenm, "wb"); while ((numread = chkfread(fbuffer, sizeof(float), bufflen, infile))) { for (ii = 0; ii < numread; ii++) sbuffer[ii] = (short) (fbuffer[ii] + 1e-20 - offset); chkfwrite(sbuffer, sizeof(short), numread, outfile); } fclose(infile); fclose(outfile); remove(datafilenm); vect_free(fbuffer); vect_free(sbuffer); } } 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)); if (cmd->shortsP && offset != 0) printf(" Offset applied to data: %d\n", -offset); printf("\n"); /* Cleanup */ if (cmd->maskfileP) { free_mask(obsmask); vect_free(maskchans); } vect_free(tobsf); vect_free(dispdt); vect_free(idispdt); free(outinfonm); free(datafilenm); if (!cmd->nobaryP) vect_free(diffbins); return (0); }
/* NEW Clipping Routine (uses channel running averages) */ int new_clip_times(unsigned char *rawdata, int ptsperblk, int numchan, float clip_sigma, unsigned char *good_chan_levels) /* Perform time-domain clipping of rawdata. This is a 2D */ /* array with ptsperblk*numchan points, each of which is an */ /* unsigned char. The clipping is done at clip_sigma sigma */ /* above/below the running mean. The up-to-date running */ /* averages of the channels are returned in good_chan_levels */ /* (which must be pre-allocated). */ { static float *chan_running_avg; static float running_avg = 0.0, running_std = 0.0; static int blocksread = 0, firsttime = 1; static long long current_point = 0; float *zero_dm_block, *median_temp; double *chan_avg_temp; float current_med, trigger; double current_avg = 0.0, current_std = 0.0; unsigned char *powptr; int ii, jj, clipit = 0, clipped = 0; if (firsttime) { chan_running_avg = gen_fvect(numchan); firsttime = 0; } chan_avg_temp = gen_dvect(numchan); zero_dm_block = gen_fvect(ptsperblk); median_temp = gen_fvect(ptsperblk); /* Calculate the zero DM time series */ for (ii = 0; ii < ptsperblk; ii++) { zero_dm_block[ii] = 0.0; powptr = rawdata + ii * numchan; for (jj = 0; jj < numchan; jj++) zero_dm_block[ii] += *powptr++; median_temp[ii] = zero_dm_block[ii]; } current_med = median(median_temp, ptsperblk); /* Calculate the current standard deviation and mean */ /* but only for data points that are within a certain */ /* fraction of the median value. This removes the */ /* really strong RFI from the calculation. */ { float lo_cutoff, hi_cutoff; int numgoodpts = 0; lo_cutoff = 0.7 * current_med; hi_cutoff = 1.3 * current_med; for (jj = 0; jj < numchan; jj++) chan_avg_temp[jj] = 0.0; /* Find the "good" points */ for (ii = 0; ii < ptsperblk; ii++) { if (zero_dm_block[ii] > lo_cutoff && zero_dm_block[ii] < hi_cutoff) { median_temp[numgoodpts] = zero_dm_block[ii]; powptr = rawdata + ii * numchan; for (jj = 0; jj < numchan; jj++) chan_avg_temp[jj] += *powptr++; numgoodpts++; } } /* Calculate the current average and stddev */ if (numgoodpts < 1) { current_avg = running_avg; current_std = running_std; for (jj = 0; jj < numchan; jj++) chan_avg_temp[jj] = chan_running_avg[jj]; } else { avg_var(median_temp, numgoodpts, ¤t_avg, ¤t_std); current_std = sqrt(current_std); for (jj = 0; jj < numchan; jj++) chan_avg_temp[jj] /= numgoodpts; } } /* Update a pseudo running average and stdev */ if (blocksread) { running_avg = 0.9 * running_avg + 0.1 * current_avg; running_std = 0.9 * running_std + 0.1 * current_std; for (ii = 0; ii < numchan; ii++) chan_running_avg[ii] = 0.9 * chan_running_avg[ii] + 0.1 * chan_avg_temp[ii]; } else { running_avg = current_avg; running_std = current_std; for (ii = 0; ii < numchan; ii++) chan_running_avg[ii] = chan_avg_temp[ii]; if (running_avg == 0.0 || current_avg == 0.0) printf("BAD RFI IN BLOCK#1!!!\n\n"); } /* See if any points need clipping */ trigger = clip_sigma * running_std; for (ii = 0; ii < ptsperblk; ii++) { if (fabs(zero_dm_block[ii] - running_avg) > trigger) { clipit = 1; break; } } /* Update the good channel levels */ for (ii = 0; ii < numchan; ii++) good_chan_levels[ii] = (unsigned char) (chan_running_avg[jj] + 0.5); /* Replace the bad channel data with channel median values */ /* that are scaled to equal the running_avg. */ if (clipit) { for (ii = 0; ii < ptsperblk; ii++) { if (fabs(zero_dm_block[ii] - running_avg) > trigger) { powptr = rawdata + ii * numchan; for (jj = 0; jj < numchan; jj++) *powptr++ = good_chan_levels[jj]; clipped++; /* fprintf(stderr, "%lld\n", current_point); */ } current_point++; } } else { current_point += ptsperblk; } blocksread++; free(chan_avg_temp); free(zero_dm_block); free(median_temp); return clipped; }