NEURON
fourier.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /* (C) Copr. 1986-92 Numerical Recipes Software #.,. */
3 
4 /* Algorithms for Fourier Transform Spectral Methods */
5 
6 #define _USE_MATH_DEFINES
7 
8 #include <math.h>
9 #include <stdio.h>
10 #include <stddef.h>
11 #include <stdlib.h>
12 
13 // to print diagnostic statements
14 // #define DEBUG_SPCTRM
15 // otherwise
16 #undef DEBUG_SPCTRM
17 
18 #undef myfabs
19 #if MAC
20 #if __GNUC__ < 4
21 #define myfabs std::fabs
22 #else
23 #define myfabs ::fabs
24 #endif
25 #else
26 #define myfabs fabs
27 #endif
28 
29 // Apple LLVM version 5.1 (clang-503.0.38) generates "unsequenced modification warning".
30 // #define SQUARE(a) ((x_=(a)) == 0.0 ? 0.0 : x_*x_)
31 static inline double SQUARE(double a) { return a*a; }
32 
33 extern "C" {
34 void hoc_execerror(const char*, const char*);
35 extern void nrn_exit(int);
36 } // extern "C"
37 
38 #include "nrngsl_real_radix2.cpp"
39 #include "nrngsl_hc_radix2.cpp"
40 
41 void nrngsl_realft(double* data, unsigned long n, int direction) {
42  if (direction == 1) {
43  nrngsl_fft_real_radix2_transform(data, 1, n);
44  }else{
45  nrngsl_fft_halfcomplex_radix2_inverse(data, 1, n);
46  }
47 }
48 
49 /*
50  convlv() -- convolution of a read data set with a response function
51  the respns function must be stored in wrap-around order
52 */
53 
54 /* frequency domain format copy from gsl fft to NRC fft */
55 void nrn_gsl2nrc(double* x, double* y, unsigned long n) {
56  unsigned long i, n2;
57  n2 = n/2;
58  y[0] = x[0];
59  if (n < 2) { return; }
60  y[1] = x[n2];
61  for (i=1; i < n2; ++i) {
62  y[2*i] = x[i];
63  y[2*i+1] = -x[n-i];
64  }
65 }
66 void nrn_nrc2gsl(double* x, double* y, unsigned long n) {
67  double xn, xn2;
68  unsigned long i, n2;
69  n2 = n/2;
70  xn = n;
71  xn2 = .5*xn;
72  y[0] = x[0]*xn2;
73  if (n < 2) { return; }
74  y[n2] = x[1]*xn2;
75  for (i=1; i < n2; ++i) {
76  y[i] = x[2*i]*xn2;
77  y[n-i] = -x[2*i+1]*xn2;
78  }
79 }
80 
81 void nrn_convlv(double* data, unsigned long n, double* respns, unsigned long m,
82  int isign, double* ans)
83 {
84  // data and respns are modified.
85  unsigned long i;
86  double scl, x_;
87 
88  int n2 = n/2;
89  for (i=1;i<=(m-1)/2;i++) {
90  respns[n-i]=respns[m-i];
91  }
92  for (i=(m+1)/2;i < n-(m-1)/2;i++) {
93  respns[i]=0.0;
94  }
95  nrngsl_realft(data, n, 1);
96  nrngsl_realft(respns, n, 1);
97  ans[0] = data[0]*respns[0];
98  for (i=1; i < n2; ++i) {
99  if (isign == 1) {
100  ans[i] = data[i]*respns[i] - data[n-i]*respns[n-i];
101  ans[n-i] = data[i]*respns[n-i] + data[n-i]*respns[i];
102  } else if (isign == -1) {
103  if ((scl = SQUARE(ans[i-1])+SQUARE(ans[i])) == 0.0) {
104 hoc_execerror("Deconvolving at response zero in nrn_convlv", 0);
105  }
106  scl *= 2.0;
107  ans[i] = (data[i]*respns[i] + data[n-i]*respns[n-i])/scl;
108  ans[i]=(data[i]*respns[n-i] - data[n-i]*respns[i])/scl;
109  } else {
110 hoc_execerror("No meaning for isign in nrn_convlv", 0);
111  }
112  }
113  ans[n2] = data[n2]*respns[n2];
114  nrngsl_realft(ans, n, -1);
115 }
116 
117 
118 /*
119  correl() -- correlation of two real data sets
120  see http://www.cv.nrao.edu/course/astr534/FourierTransforms.html SF16
121 */
122 void nrn_correl(double* x, double* y, unsigned long n, double* z)
123 {
124  nrngsl_realft(x, n, 1);
125  nrngsl_realft(y, n, 1);
126  z[0] = x[0]*y[0];
127  int n2 = n/2;
128  for (int i=1; i < n2; ++i) {
129  z[i] = x[i]*y[i] + x[n-i]*y[n-i];
130  // with following sign, produces same result as old NRC code
131  z[n-i] = y[i]*x[n-i] - y[n-i]*x[i];
132  }
133  z[n2] = x[n2]*y[n2];
134  nrngsl_realft(z, n, -1);
135 }
136 
137 
138 /*
139  spctrm() -- power spectrum using fourier transforms
140  modified to take array rather than data stream.
141 */
142 
143 #define WINDOW(j,a,b) (1.0-myfabs((((j)-1)-(a))*(b))) /* Bartlett */
144 
145 // void nrn_spctrm(double* data, double* p, int m, int k)
146 void nrn_spctrm(double* data, double* psd, int setsize, int numsegpairs)
147 {
148  int j, k, cx, n;
149  double a, ainv, wfac, x_;
150  double *fftv;
151 
152  // 0 is index of first meaningful element of power spectral density
153  for (j=0;j<=setsize-1;j++) psd[j]=0.0; // zero out any prior result
154 
155  // calc factor used to correct for window's effect on psd
156  a = setsize;
157  ainv = 1.0/a;
158 
159  n = 2*setsize;
160  wfac = 0.0;
161  for (j=1;j<=n;j++) wfac += SQUARE(WINDOW(j,a,1/a));
162 
163 #ifdef DEBUG_SPCTRM
164  printf("setsize %d, numsegpairs %d\n", setsize, numsegpairs);
165  printf("=============\n");
166  printf("window values\n");
167  for (j=1;j<=n;j++) printf("%d %f\n", j, WINDOW(j,a,1/a));
168  printf("initial wfac %f\n", wfac);
169 #endif
170 
171  // storage for a data segment
172  fftv = (double *)malloc((size_t) (n*sizeof(double)));
173 
174  cx = 0; // data index
175  for (k=1;k<=numsegpairs*2;k++) {
176 
177 #ifdef DEBUG_SPCTRM
178  printf("==============\n");
179  printf("segment %d\n", k);
180 #endif
181 
182  // fill fftv with a segment of data
183  for (j=0; j<n; j++) fftv[j] = data[cx++];
184 #ifdef DEBUG_SPCTRM
185  for (j=0; j<n; j++) printf("datum %d %f\n", j, fftv[j]);
186  printf("--------------\n");
187 #endif
188 
189  cx -= setsize; // next segment overlaps by this much
190 
191  // apply window
192  for (j=1; j<=n;j++) fftv[j-1]*=WINDOW(j,a,1/a);
193 
194  // apply fft
195  nrngsl_realft(fftv, n, 1);
196 #ifdef DEBUG_SPCTRM
197  printf("\nfftv:\n");
198  for (j=0; j<n;j++) printf("%f ",fftv[j]);
199  printf("\n");
200 #endif
201 
202  // add to psd
203  psd[0] += SQUARE(fftv[0]);
204  for (j=1; j<setsize; j++) {
205  psd[j] += (SQUARE(fftv[j]) + SQUARE(fftv[n - j]));
206  }
207  }
208 
209  wfac = 1 / (wfac*n*numsegpairs);
210  for (j=0; j<setsize; j++) psd[j] *= wfac;
211  psd[0] *= 0.5;
212 
213 #ifdef DEBUG_SPCTRM
214  printf("1/wfac for all but DC = %f\n", 1./wfac);
215  printf("1/wfac for DC = %f\n", 2./wfac);
216  printf("final results--\n");
217  for (j=0; j<setsize;j++) printf("%d %f\n",j, psd[j]);
218  printf("\ndone\n");
219 #endif
220 
221  free(fftv);
222 }
223 #undef WINDOW
#define data
Definition: rbtqueue.cpp:49
void nrn_spctrm(double *data, double *psd, int setsize, int numsegpairs)
Definition: fourier.cpp:146
void nrn_gsl2nrc(double *x, double *y, unsigned long n)
Definition: fourier.cpp:55
void nrngsl_realft(double *data, unsigned long n, int direction)
Definition: fourier.cpp:41
static philox4x32_key_t k
Definition: nrnran123.cpp:11
int const size_t const size_t n
Definition: nrngsl.h:12
#define WINDOW(j, a, b)
Definition: fourier.cpp:143
#define printf
Definition: mwprefix.h:26
static N_Vector x_
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
size_t j
void nrn_convlv(double *data, unsigned long n, double *respns, unsigned long m, int isign, double *ans)
Definition: fourier.cpp:81
void nrn_nrc2gsl(double *x, double *y, unsigned long n)
Definition: fourier.cpp:66
#define i
Definition: md1redef.h:12
void nrn_exit(int)
Definition: hoc.cpp:219
static double SQUARE(double a)
Definition: fourier.cpp:31
void nrn_correl(double *x, double *y, unsigned long n, double *z)
Definition: fourier.cpp:122