/********** Copyright 2008 Holger Vogt. All rights reserved. Author: 2008 Holger Vogt **********/ /* * Code to do fast fourier transform on data. */ #include #include #include #include #include "com_fft.h" #include "variable.h" #include "parse.h" #include "../misc/misc_time.h" #include static void fftext(double*, double*, long int, long int, int); void com_fft(wordlist *wl) { ngcomplex_t **fdvec; double **tdvec; double *freq, *win, *time; double delta_t, span; int fpts, i, j, tlen, ngood; struct dvec *f, *vlist, *lv = NULL, *vec; struct pnode *names, *first_name; double *reald, *imagd; int size, sign, order; double scale, sigma; if (!plot_cur || !plot_cur->pl_scale) { fprintf(cp_err, "Error: no vectors loaded.\n"); return; } if (!isreal(plot_cur->pl_scale) || ((plot_cur->pl_scale)->v_type != SV_TIME)) { fprintf(cp_err, "Error: fft needs real time scale\n"); return; } tlen = (plot_cur->pl_scale)->v_length; time = (plot_cur->pl_scale)->v_realdata; span = time[tlen-1] - time[0]; delta_t = span/(tlen - 1); /* size of input vector is power of two and larger than spice vector */ size = 1; while (size < tlen) size *= 2; /* output vector has length of size/2 */ fpts = size/2; /* window functions - should have an average of one */ win = TMALLOC(double, tlen); { char window[BSIZE_SP]; double maxt = time[tlen-1]; if (!cp_getvar("specwindow", CP_STRING, window)) strcpy(window,"blackman"); if (eq(window, "none")) for(i=0; i span) { win[i] = 0.0; } else { win[i] = 1.0; } } else if (eq(window, "triangle") || eq(window, "bartlet") || eq(window, "bartlett")) for(i=0; i span) { win[i] = 0.0; } else { win[i] = 2.0 - fabs(2+4*(time[i]-maxt)/span); } } else if (eq(window, "hann") || eq(window, "hanning") || eq(window, "cosine")) for(i=0; i span) { win[i] = 0.0; } else { win[i] = 1.0 - cos(2*M_PI*(time[i]-maxt)/span); } } else if (eq(window, "hamming")) for(i=0; i span) { win[i] = 0.0; } else { win[i] = 1.0 - 0.46/0.54*cos(2*M_PI*(time[i]-maxt)/span); } } else if (eq(window, "blackman")) for(i=0; i span) { win[i] = 0; } else { win[i] = 1.0; win[i] -= 0.50/0.42*cos(2*M_PI*(time[i]-maxt)/span); win[i] += 0.08/0.42*cos(4*M_PI*(time[i]-maxt)/span); } } else if (eq(window, "flattop")) for(i=0; i span) { win[i] = 0; } else { win[i] = 1.0; win[i] -= 1.93*cos(2*M_PI*(time[i]-maxt)/span); win[i] += 1.29*cos(4*M_PI*(time[i]-maxt)/span); win[i] -= 0.388*cos(6*M_PI*(time[i]-maxt)/span); win[i] += 0.032*cos(8*M_PI*(time[i]-maxt)/span); } } else if (eq(window, "gaussian")) { if (!cp_getvar("specwindoworder", CP_NUM, &order)) order = 2; if (order < 2) order = 2; sigma=1.0/order; scale=0.83/sigma; for(i=0; i span) { win[i] = 0; } else { win[i] = scale*exp(-0.5*pow((time[i]-maxt/2)/(sigma*maxt/2),2)); } } } else { fprintf(cp_err, "Warning: unknown window type %s\n", window); tfree(win); return; } } names = ft_getpnames(wl, TRUE); first_name = names; vlist = NULL; ngood = 0; while (names) { vec = ft_evaluate(names); names = names->pn_next; while (vec) { if (vec->v_length != tlen) { fprintf(cp_err, "Error: lengths of %s vectors don't match: %d, %d\n", vec->v_name, vec->v_length, tlen); vec = vec->v_link2; continue; } if (!isreal(vec)) { fprintf(cp_err, "Error: %s isn't real!\n", vec->v_name); vec = vec->v_link2; continue; } if (vec->v_type == SV_TIME) { vec = vec->v_link2; continue; } if (!vlist) vlist = vec; else lv->v_link2 = vec; lv = vec; vec = vec->v_link2; ngood++; } } free_pnode_o(first_name); if (!ngood) { tfree(win); return; } plot_cur = plot_alloc("spectrum"); plot_cur->pl_next = plot_list; plot_list = plot_cur; plot_cur->pl_title = copy((plot_cur->pl_next)->pl_title); plot_cur->pl_name = copy("Spectrum"); plot_cur->pl_date = copy(datestring( )); freq = TMALLOC(double, fpts); f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = copy("frequency"); f->v_type = SV_FREQUENCY; f->v_flags = (VF_REAL | VF_PERMANENT | VF_PRINT); f->v_length = fpts; f->v_realdata = freq; vec_new(f); for (i = 0; iv_realdata; /* real input data */ fdvec[i] = TMALLOC(ngcomplex_t, fpts); /* complex output data */ f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = vec_basename(vec); f->v_type = SV_NOTYPE; f->v_flags = (VF_COMPLEX | VF_PERMANENT); f->v_length = fpts; f->v_compdata = fdvec[i]; vec_new(f); vec = vec->v_link2; } sign = 1; printf("FFT: Time span: %g s, input length: %d, zero padding: %d\n", span, size, size-tlen); printf("FFT: Freq. resolution: %g Hz, output length: %d\n", 1.0/span*tlen/size, fpts); reald = TMALLOC(double, size); imagd = TMALLOC(double, size); for (i = 0; ipl_scale) { fprintf(cp_err, "Error: no vectors loaded.\n"); return; } if (!isreal(plot_cur->pl_scale) || ((plot_cur->pl_scale)->v_type != SV_TIME)) { fprintf(cp_err, "Error: fft needs real time scale\n"); return; } tlen = (plot_cur->pl_scale)->v_length; time = (plot_cur->pl_scale)->v_realdata; span = time[tlen-1] - time[0]; delta_t = span/(tlen - 1); // get filter length from parameter input s = wl->wl_word; ave = ft_numparse(&s, FALSE); if (!ave || (*ave < 1.0)) { fprintf(cp_out, "Number of averaged data points: %d\n", 1); smooth = 1; } else smooth = (int)(*ave); wl = wl->wl_next; // size of input vector is power of two and larger than spice vector size = 1; mm = 0; while (size < tlen) { size <<= 1; mm++; } // output vector has length of size/2 fpts = size>>1; // window function win = TMALLOC(double, tlen); { char window[BSIZE_SP]; double maxt = time[tlen-1]; if (!cp_getvar("specwindow", CP_STRING, window)) strcpy(window,"blackman"); if (eq(window, "none")) for(i=0; i span) { win[i] = 0; } else { win[i] = 1; } } else if (eq(window, "hanning") || eq(window, "cosine")) for(i=0; i span) { win[i] = 0; } else { win[i] = 1 - cos(2*M_PI*(time[i]-maxt)/span); } } else if (eq(window, "hamming")) for(i=0; i span) { win[i] = 0; } else { win[i] = 1 - 0.92/1.08*cos(2*M_PI*(time[i]-maxt)/span); } } else if (eq(window, "triangle") || eq(window, "bartlet")) for(i=0; i span) { win[i] = 0; } else { win[i] = 2 - fabs(2+4*(time[i]-maxt)/span); } } else if (eq(window, "blackman")) { int order; if (!cp_getvar("specwindoworder", CP_NUM, &order)) order = 2; if (order < 2) order = 2; /* only order 2 supported here */ for(i=0; i span) { win[i] = 0; } else { win[i] = 1; win[i] -= 0.50/0.42*cos(2*M_PI*(time[i]-maxt)/span); win[i] += 0.08/0.42*cos(4*M_PI*(time[i]-maxt)/span); } } } else if (eq(window, "gaussian")) { if (!cp_getvar("specwindoworder", CP_NUM, &order)) order = 2; if (order < 2) order = 2; sigma=1.0/order; scale=0.83/sigma; for(i=0; i span) { win[i] = 0; } else { win[i] = scale*exp(-0.5*pow((time[i]-maxt/2)/(sigma*maxt/2),2)); } } /* int order; double scale; extern double erfc(double); if (!cp_getvar("specwindoworder", CP_NUM, &order)) order = 2; if (order < 2) order = 2; scale = pow(2*M_PI/order,0.5)*(0.5-erfc(pow(order,0.5))); for(i=0; i span) { win[i] = 0; } else { win[i] = exp(-0.5*order*(1-2*(maxt-time[i])/span) *(1-2*(maxt-time[i])/span))/scale; } } */ } else { fprintf(cp_err, "Warning: unknown window type %s\n", window); tfree(win); return; } } names = ft_getpnames(wl, TRUE); first_name = names; vlist = NULL; ngood = 0; while (names) { vec = ft_evaluate(names); names = names->pn_next; while (vec) { if (vec->v_length != (int)tlen) { fprintf(cp_err, "Error: lengths of %s vectors don't match: %d, %d\n", vec->v_name, vec->v_length, tlen); vec = vec->v_link2; continue; } if (!isreal(vec)) { fprintf(cp_err, "Error: %s isn't real!\n", vec->v_name); vec = vec->v_link2; continue; } if (vec->v_type == SV_TIME) { vec = vec->v_link2; continue; } if (!vlist) vlist = vec; else lv->v_link2 = vec; lv = vec; vec = vec->v_link2; ngood++; } } free_pnode_o(first_name); if (!ngood) { return; } plot_cur = plot_alloc("spectrum"); plot_cur->pl_next = plot_list; plot_list = plot_cur; plot_cur->pl_title = copy((plot_cur->pl_next)->pl_title); plot_cur->pl_name = copy("PSD"); plot_cur->pl_date = copy(datestring( )); freq = TMALLOC(double, fpts); f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = copy("frequency"); f->v_type = SV_FREQUENCY; f->v_flags = (VF_REAL | VF_PERMANENT | VF_PRINT); f->v_length = fpts; f->v_realdata = freq; vec_new(f); for (i = 0; iv_realdata; /* real input data */ fdvec[i] = TMALLOC(ngcomplex_t, fpts); /* complex output data */ f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = vec_basename(vec); f->v_type = SV_NOTYPE; //vec->v_type; f->v_flags = (VF_COMPLEX | VF_PERMANENT); f->v_length = fpts; f->v_compdata = fdvec[i]; vec_new(f); vec = vec->v_link2; } printf("PSD: Time span: %g s, input length: %d, zero padding: %d\n", span, size, size-tlen); printf("PSD: Freq. resolution: %g Hz, output length: %d\n", 1.0/span*tlen/size, fpts); sign = 1; isreal = 1; reald = TMALLOC(double, size); imagd = TMALLOC(double, size); // scale = 0.66; for (i = 0; i>1; for (j=0; j> 1; j = 0; for (i=0;i>= 1; } j += k; } /* Compute the FFT */ c1 = -1.0; c2 = 0.0; l2 = 1; for (l=0;l