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