static int calc_fftlen(int numharm, int harmnum, int max_zfull) /* The fft length needed to properly process a subharmonic */ { int bins_needed, end_effects; double harm_fract; harm_fract = (double) harmnum / (double) numharm; bins_needed = (ACCEL_USELEN * harmnum) / numharm + 2; end_effects = 2 * ACCEL_NUMBETWEEN * z_resp_halfwidth(calc_required_z(harm_fract, max_zfull), LOWACC); return next2_to_n(bins_needed + end_effects); }
static dataview *get_dataview(int centern, int zoomlevel, datapart * dp) { int ii, jj, offset; double tmpavg, tmpvar; float *tmpchunk; dataview *dv; dv = (dataview *) malloc(sizeof(dataview)); dv->zoomlevel = zoomlevel; dv->numsamps = (1 << (LOGMAXDISPNUM - zoomlevel)); if (dv->numsamps > dp->nn) dv->numsamps = next2_to_n(dp->nn) / 2; dv->chunklen = (zoomlevel < -LOGMINCHUNKLEN) ? (1 << abs(zoomlevel)) : (1 << LOGMINCHUNKLEN); dv->dispnum = (dv->numsamps > MAXDISPNUM) ? MAXDISPNUM : dv->numsamps; if (DEBUGOUT) printf("zoomlevel = %d numsamps = %d chunklen = %d dispnum %d nn = %d\n", dv->zoomlevel, dv->numsamps, dv->chunklen, dv->dispnum, dp->nn); dv->numchunks = dv->numsamps / dv->chunklen; dv->centern = centern; dv->lon = centern - dv->numsamps / 2; dv->vdt = dv->chunklen * idata.dt; dv->maxval = SMALLNUM; dv->minval = LARGENUM; if (dv->lon < 0) { dv->lon = 0; dv->centern = dv->lon + dv->numsamps / 2; } if (dv->lon + dv->numsamps >= dp->nn) { dv->lon = dp->nn - dv->numsamps; dv->centern = dv->lon + dv->numsamps / 2; } tmpchunk = gen_fvect(dv->chunklen); for (ii = 0; ii < dv->numchunks; ii++) { float tmpmin = LARGENUM, tmpmax = SMALLNUM, tmpval; offset = dv->lon + ii * dv->chunklen; memcpy(tmpchunk, dp->data + offset, sizeof(float) * dv->chunklen); avg_var(dp->data + offset, dv->chunklen, &tmpavg, &tmpvar); if (usemedian) dv->avgmeds[ii] = median(tmpchunk, dv->chunklen); else dv->avgmeds[ii] = tmpavg; dv->stds[ii] = sqrt(tmpvar); for (jj = 0; jj < dv->chunklen; jj++, offset++) { tmpval = dp->data[offset]; if (tmpval > tmpmax) tmpmax = tmpval; if (tmpval < tmpmin) tmpmin = tmpval; } dv->maxs[ii] = tmpmax; if (tmpmax > dv->maxval) dv->maxval = tmpmax; dv->mins[ii] = tmpmin; if (tmpmin < dv->minval) dv->minval = tmpmin; } vect_free(tmpchunk); offset = dv->lon; if (zoomlevel > 0) { for (ii = 0, offset = dv->lon; ii < dv->numsamps; ii++, offset++) *(dv->vals + ii) = *(dp->data + offset); } return dv; }
ffdotpows *subharm_ffdot_plane(int numharm, int harmnum, double fullrlo, double fullrhi, subharminfo * shi, accelobs * obs) { int ii, lobin, hibin, numdata, nice_numdata, nrs, fftlen, binoffset; static int numrs_full = 0, numzs_full = 0; float powargr, powargi; double drlo, drhi, harm_fract; ffdotpows *ffdot; fcomplex *data, **result; presto_datainf datainf; if (numrs_full == 0) { if (numharm == 1 && harmnum == 1) { numrs_full = ACCEL_USELEN; numzs_full = shi->numkern; } else { printf("You must call subharm_ffdot_plane() with numharm=1 and\n"); printf("harnum=1 before you use other values! Exiting.\n\n"); exit(0); } } ffdot = (ffdotpows *) malloc(sizeof(ffdotpows)); /* Calculate and get the required amplitudes */ harm_fract = (double) harmnum / (double) numharm; drlo = calc_required_r(harm_fract, fullrlo); drhi = calc_required_r(harm_fract, fullrhi); ffdot->rlo = (int) floor(drlo); ffdot->zlo = calc_required_z(harm_fract, obs->zlo); /* Initialize the lookup indices */ if (numharm > 1) { double rr, subr; for (ii = 0; ii < numrs_full; ii++) { rr = fullrlo + ii * ACCEL_DR; subr = calc_required_r(harm_fract, rr); shi->rinds[ii] = index_from_r(subr, ffdot->rlo); } } ffdot->rinds = shi->rinds; ffdot->numrs = (int) ((ceil(drhi) - floor(drlo)) * ACCEL_RDR + DBLCORRECT) + 1; if (numharm == 1 && harmnum == 1) { ffdot->numrs = ACCEL_USELEN; } else { if (ffdot->numrs % ACCEL_RDR) { ffdot->numrs = (ffdot->numrs / ACCEL_RDR + 1) * ACCEL_RDR; } } ffdot->numzs = shi->numkern; binoffset = shi->kern[0].kern_half_width; fftlen = shi->kern[0].fftlen; lobin = ffdot->rlo - binoffset; hibin = (int) ceil(drhi) + binoffset; numdata = hibin - lobin + 1; nice_numdata = next2_to_n(numdata); // for FFTs data = get_fourier_amplitudes(lobin, nice_numdata, obs); if (!obs->mmap_file && !obs->dat_input && 0) printf("This is newly malloc'd!\n"); // Normalize the Fourier amplitudes if (obs->nph > 0.0) { // Use freq 0 normalization if requested (i.e. photons) double norm = 1.0 / sqrt(obs->nph); for (ii = 0; ii < numdata; ii++) { data[ii].r *= norm; data[ii].i *= norm; } } else if (obs->norm_type == 0) { // old-style block median normalization float *powers; double norm; powers = gen_fvect(numdata); for (ii = 0; ii < numdata; ii++) powers[ii] = POWER(data[ii].r, data[ii].i); norm = 1.0 / sqrt(median(powers, numdata)/log(2.0)); free(powers); for (ii = 0; ii < numdata; ii++) { data[ii].r *= norm; data[ii].i *= norm; } } else { // new-style running double-tophat local-power normalization float *powers, *loc_powers; powers = gen_fvect(nice_numdata); for (ii = 0; ii < nice_numdata; ii++) { powers[ii] = POWER(data[ii].r, data[ii].i); } loc_powers = corr_loc_pow(powers, nice_numdata); for (ii = 0; ii < numdata; ii++) { float norm = invsqrt(loc_powers[ii]); data[ii].r *= norm; data[ii].i *= norm; } free(powers); free(loc_powers); } /* Perform the correlations */ result = gen_cmatrix(ffdot->numzs, ffdot->numrs); datainf = RAW; for (ii = 0; ii < ffdot->numzs; ii++) { nrs = corr_complex(data, numdata, datainf, shi->kern[ii].data, fftlen, FFT, result[ii], ffdot->numrs, binoffset, ACCEL_NUMBETWEEN, binoffset, CORR); datainf = SAME; } // Always free data free(data); /* Convert the amplitudes to normalized powers */ ffdot->powers = gen_fmatrix(ffdot->numzs, ffdot->numrs); for (ii = 0; ii < (ffdot->numzs * ffdot->numrs); ii++) ffdot->powers[0][ii] = POWER(result[0][ii].r, result[0][ii].i); free(result[0]); free(result); return ffdot; }
int main(int argc, char *argv[]) { float maxpow = 0.0, inx = 0.0, iny = 0.0; double centerr, offsetf; int zoomlevel, maxzoom, minzoom, xid, psid; char *rootfilenm, inchar; fftpart *lofp; fftview *fv; if (argc == 1) { printf("\nusage: explorefft fftfilename\n\n"); exit(0); } printf("\n\n"); printf(" Interactive FFT Explorer\n"); printf(" by Scott M. Ransom\n"); printf(" October, 2001\n"); print_help(); { int hassuffix = 0; char *suffix; hassuffix = split_root_suffix(argv[1], &rootfilenm, &suffix); if (hassuffix) { if (strcmp(suffix, "fft") != 0) { printf("\nInput file ('%s') must be a FFT file ('.fft')!\n\n", argv[1]); free(suffix); exit(0); } free(suffix); } else { printf("\nInput file ('%s') must be a FFT file ('.fft')!\n\n", argv[1]); exit(0); } } /* Read the info file */ readinf(&idata, rootfilenm); if (strlen(remove_whitespace(idata.object)) > 0) { printf("Examining %s data from '%s'.\n\n", remove_whitespace(idata.object), argv[1]); } else { printf("Examining data from '%s'.\n\n", argv[1]); } N = idata.N; T = idata.dt * idata.N; #ifdef USEMMAP printf("Memory mapping the input FFT. This may take a while...\n"); mmap_file = open(argv[1], O_RDONLY); { int rt; struct stat buf; rt = fstat(mmap_file, &buf); if (rt == -1) { perror("\nError in fstat() in explorefft.c"); printf("\n"); exit(-1); } Nfft = buf.st_size / sizeof(fcomplex); } lofp = get_fftpart(0, Nfft); #else { int numamps; fftfile = chkfopen(argv[1], "rb"); Nfft = chkfilelen(fftfile, sizeof(fcomplex)); numamps = (Nfft > MAXBINS) ? (int) MAXBINS : (int) Nfft; lofp = get_fftpart(0, numamps); } #endif /* Plot the initial data */ { int initnumbins = INITIALNUMBINS; if (initnumbins > Nfft) { initnumbins = next2_to_n(Nfft) / 2; zoomlevel = LOGDISPLAYNUM - (int) (log(initnumbins) / log(2.0)); minzoom = zoomlevel; } else { zoomlevel = LOGDISPLAYNUM - LOGINITIALNUMBINS; minzoom = LOGDISPLAYNUM - LOGMAXBINS; } maxzoom = LOGDISPLAYNUM - LOGMINBINS; centerr = initnumbins / 2; } fv = get_fftview(centerr, zoomlevel, lofp); /* Prep the XWIN device for PGPLOT */ xid = cpgopen("/XWIN"); if (xid <= 0) { free(fv); #ifdef USEMMAP close(mmap_file); #else fclose(fftfile); #endif free_fftpart(lofp); exit(EXIT_FAILURE); } cpgscr(15, 0.4, 0.4, 0.4); cpgask(0); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); do { cpgcurs(&inx, &iny, &inchar); if (DEBUGOUT) printf("You pressed '%c'\n", inchar); switch (inchar) { case 'A': /* Zoom in */ case 'a': centerr = (inx + offsetf) * T; case 'I': case 'i': if (DEBUGOUT) printf(" Zooming in (zoomlevel = %d)...\n", zoomlevel); if (zoomlevel < maxzoom) { zoomlevel++; free(fv); fv = get_fftview(centerr, zoomlevel, lofp); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); } else printf(" Already at maximum zoom level (%d).\n", zoomlevel); break; case 'X': /* Zoom out */ case 'x': case 'O': case 'o': if (DEBUGOUT) printf(" Zooming out (zoomlevel = %d)...\n", zoomlevel); if (zoomlevel > minzoom) { zoomlevel--; free(fv); fv = get_fftview(centerr, zoomlevel, lofp); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); } else printf(" Already at minimum zoom level (%d).\n", zoomlevel); break; case '<': /* Shift left 1 full screen */ centerr -= fv->numbins + fv->numbins / 8; case ',': /* Shift left 1/8 screen */ if (DEBUGOUT) printf(" Shifting left...\n"); centerr -= fv->numbins / 8; { /* Should probably get the previous chunk from the fftfile... */ double lowestr; lowestr = 0.5 * fv->numbins; if (centerr < lowestr) centerr = lowestr; } free(fv); fv = get_fftview(centerr, zoomlevel, lofp); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); break; case '>': /* Shift right 1 full screen */ centerr += fv->numbins - fv->numbins / 8; case '.': /* Shift right 1/8 screen */ if (DEBUGOUT) printf(" Shifting right...\n"); centerr += fv->numbins / 8; { /* Should probably get the next chunk from the fftfile... */ double highestr; highestr = lofp->rlo + lofp->numamps - 0.5 * fv->numbins; if (centerr > highestr) centerr = highestr; } free(fv); fv = get_fftview(centerr, zoomlevel, lofp); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); break; case '+': /* Increase height of powers */ case '=': if (maxpow == 0.0) { printf(" Auto-scaling is off.\n"); maxpow = 1.1 * fv->maxpow; } maxpow = 3.0 / 4.0 * maxpow; cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); break; case '-': /* Decrease height of powers */ case '_': if (maxpow == 0.0) { printf(" Auto-scaling is off.\n"); maxpow = 1.1 * fv->maxpow; } maxpow = 4.0 / 3.0 * maxpow; cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); break; case 'S': /* Auto-scale */ case 's': if (maxpow == 0.0) break; else { printf(" Auto-scaling is on.\n"); maxpow = 0.0; cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); break; } case 'G': /* Goto a frequency */ case 'g': { char freqstr[50]; double freq = -1.0; while (freq < 0.0) { printf(" Enter the frequency (Hz) to go to:\n"); fgets(freqstr, 50, stdin); freqstr[strlen(freqstr) - 1] = '\0'; freq = atof(freqstr); } offsetf = 0.0; centerr = freq * T; printf(" Moving to frequency %.15g.\n", freq); free(fv); fv = get_fftview(centerr, zoomlevel, lofp); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, centerr, 2); } break; case 'H': /* Show harmonics */ case 'h': { double retval; retval = harmonic_loop(xid, centerr, zoomlevel, lofp); if (retval > 0.0) { offsetf = 0.0; centerr = retval; free(fv); fv = get_fftview(centerr, zoomlevel, lofp); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, centerr, 2); } } break; case '?': /* Print help screen */ print_help(); break; case 'D': /* Show details about a selected point */ case 'd': { double newr; printf(" Searching for peak near freq = %.7g Hz...\n", (inx + offsetf)); newr = find_peak(inx + offsetf, fv, lofp); centerr = newr; free(fv); fv = get_fftview(centerr, zoomlevel, lofp); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, centerr, 2); } break; case 'L': /* Load a zaplist */ case 'l': { int ii, len; char filename[200]; double *lobins, *hibins; printf(" Enter the filename containing the zaplist to load:\n"); fgets(filename, 199, stdin); len = strlen(filename) - 1; filename[len] = '\0'; numzaplist = get_birdies(filename, T, 0.0, &lobins, &hibins); lenzaplist = numzaplist + 20; /* Allow some room to add more */ if (lenzaplist) free(zaplist); zaplist = (bird *) malloc(sizeof(bird) * lenzaplist); for (ii = 0; ii < numzaplist; ii++) { zaplist[ii].lobin = lobins[ii]; zaplist[ii].hibin = hibins[ii]; } vect_free(lobins); vect_free(hibins); printf("\n"); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); } break; case 'Z': /* Add a birdie to a zaplist */ case 'z': { int badchoice = 2; float lox, hix, loy, hiy; double rs[2]; char choice; if (numzaplist + 1 > lenzaplist) { lenzaplist += 10; zaplist = (bird *) realloc(zaplist, sizeof(bird) * lenzaplist); } cpgqwin(&lox, &hix, &loy, &hiy); printf(" Click the left mouse button on the first frequency limit.\n"); while (badchoice) { cpgcurs(&inx, &iny, &choice); if (choice == 'A' || choice == 'a') { rs[2 - badchoice] = ((double) inx + offsetf) * T; cpgsave(); cpgsci(7); cpgmove(inx, 0.0); cpgdraw(inx, hiy); cpgunsa(); badchoice--; if (badchoice == 1) printf (" Click the left mouse button on the second frequency limit.\n"); } else { printf(" Option not recognized.\n"); } }; if (rs[1] > rs[0]) { zaplist[numzaplist].lobin = rs[0]; zaplist[numzaplist].hibin = rs[1]; } else { zaplist[numzaplist].lobin = rs[1]; zaplist[numzaplist].hibin = rs[0]; } printf(" The new birdie has: f_avg = %.15g f_width = %.15g\n\n", 0.5 * (zaplist[numzaplist].hibin + zaplist[numzaplist].lobin) / T, (zaplist[numzaplist].hibin - zaplist[numzaplist].lobin) / T); numzaplist++; qsort(zaplist, numzaplist, sizeof(bird), compare_birds); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); } break; case 'P': /* Print the current plot */ case 'p': { int len; char filename[200]; printf(" Enter the filename to save the plot as:\n"); fgets(filename, 196, stdin); len = strlen(filename) - 1; filename[len + 0] = '/'; filename[len + 1] = 'P'; filename[len + 2] = 'S'; filename[len + 3] = '\0'; psid = cpgopen(filename); cpgslct(psid); cpgpap(10.25, 8.5 / 11.0); cpgiden(); cpgscr(15, 0.8, 0.8, 0.8); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); cpgclos(); cpgslct(xid); cpgscr(15, 0.4, 0.4, 0.4); filename[len] = '\0'; printf(" Wrote the plot to the file '%s'.\n", filename); } break; case 'N': /* Changing power normalization */ case 'n': { float inx2 = 0.0, iny2 = 0.0; char choice; unsigned char badchoice = 1; printf(" Specify the type of power normalization:\n" " m,M : Median values determined locally\n" " d,D : DC frequency amplitude\n" " r,R : Raw powers (i.e. no normalization)\n" " u,U : User specified interval (the average powers)\n"); while (badchoice) { cpgcurs(&inx2, &iny2, &choice); switch (choice) { case 'M': case 'm': norm_const = 0.0; maxpow = 0.0; badchoice = 0; printf (" Using local median normalization. Autoscaling is on.\n"); break; case 'D': case 'd': norm_const = 1.0 / r0; maxpow = 0.0; badchoice = 0; printf (" Using DC frequency (%f) normalization. Autoscaling is on.\n", r0); break; case 'R': case 'r': norm_const = 1.0; maxpow = 0.0; badchoice = 0; printf (" Using raw powers (i.e. no normalization). Autoscaling is on.\n"); break; case 'U': case 'u': { char choice2; float xx = inx, yy = iny; int lor, hir, numr; double avg, var; printf (" Use the left mouse button to select a left and right boundary\n" " of a region to calculate the average power.\n"); do { cpgcurs(&xx, &yy, &choice2); } while (choice2 != 'A' && choice2 != 'a'); lor = (int) ((xx + offsetf) * T); cpgsci(7); cpgmove(xx, 0.0); cpgdraw(xx, 10.0 * fv->maxpow); do { cpgcurs(&xx, &yy, &choice2); } while (choice2 != 'A' && choice2 != 'a'); hir = (int) ((xx + offsetf) * T); cpgmove(xx, 0.0); cpgdraw(xx, 10.0 * fv->maxpow); cpgsci(1); if (lor > hir) { int tempr; tempr = hir; hir = lor; lor = tempr; } numr = hir - lor + 1; avg_var(lofp->rawpowers + lor - lofp->rlo, numr, &avg, &var); printf(" Selection has: average = %.5g\n" " std dev = %.5g\n", avg, sqrt(var)); norm_const = 1.0 / avg; maxpow = 0.0; badchoice = 0; printf (" Using %.5g as the normalization constant. Autoscaling is on.\n", avg); break; } default: printf(" Unrecognized choice '%c'.\n", choice); break; } } free(fv); fv = get_fftview(centerr, zoomlevel, lofp); cpgpage(); offsetf = plot_fftview(fv, maxpow, 1.0, 0.0, 0); } break; case 'Q': /* Quit */ case 'q': printf(" Quitting...\n"); free(fv); cpgclos(); break; default: printf(" Unrecognized option '%c'.\n", inchar); break; } } while (inchar != 'Q' && inchar != 'q'); free_fftpart(lofp); #ifdef USEMMAP close(mmap_file); #else fclose(fftfile); #endif if (lenzaplist) free(zaplist); printf("Done\n\n"); return 0; }