Linuxpops  3.01.04
Spectral Anaysis Package for Single Dish Data
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
fft.c
Go to the documentation of this file.
1 /*
2 Copyright 2021 Arizona Board of Regents on behalf of the University of Arizona.
3 
4 For commercial uses, to obtain a license to sell and or sublicense copies of
5 the Software please contact the University of Arizona at Tech Launch Arizona:
6 lewish@tla.arizona.edu.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction for non-commercial use educational and
11 research purposes, including without limitation the rights to use, copy,
12 modify, merge, publish, distribute, and to permit persons to whom the Software
13 is furnished to do so, subject to the following conditions:
14 
15 The entire above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25 
26 1. Additional Required Provisions
27 
28 1.1. Arbitration. The parties agree that if a dispute arises between them
29 concerning this Agreement, the parties may be required to submit the matter to
30 arbitration pursuant to Arizona law.
31 
32 1.2. Applicable Law and Venue. This Agreement shall be interpreted pursuant
33 to the laws of the State of Arizona. Any arbitration or litigation between the
34 Parties shall be conducted in Pima County, ARIZONA, and LICENSEE hereby
35 submits to venue and jurisdiction in Pima County, ARIZONA.
36 
37 1.3. Non-Discrimination. The Parties agree to be bound by state and federal
38 laws and regulations governing equal opportunity and non-discrimination and
39 immigration.
40 
41 1.4. Appropriation of Funds. The Parties recognize that performance by
42 ARIZONA may depend upon appropriation of funds by the State Legislature of
43 ARIZONA. If the Legislature fails to appropriate the necessary funds, or if
44 ARIZONA’S appropriation is reduced during the fiscal year, ARIZONA may cancel
45 this Agreement without further duty or obligation. ARIZONA will notify
46 LICENSEE as soon as reasonably possible after it knows of the loss of funds.
47 
48 1.5. Conflict of Interest. This Agreement is subject to the provisions of
49 A.R.S. 38-511 and other conflict of interest regulations. Within three years
50 of the EFFECTIVE DATE, ARIZONA may cancel this Agreement if any person
51 significantly involved in initiating, negotiating, drafting, securing, or
52 creating this Agreement for or on behalf of ARIZONA becomes an employee or
53 consultant in any capacity of LICENSEE with respect to the subject matter of
54 this Agreement.
55 
56  */
57 
58 
59 #include "extern.h"
60 
61 #include <gsl/gsl_errno.h>
62 #include <gsl/gsl_fft_real.h>
63 #include <gsl/gsl_fft_halfcomplex.h>
64 
65 /* Changes:
66 
67  Added last_plot to fft plot; twf; Jan 05, 2016
68 
69  Added the xb and xe axis to fft plot; twf; Jan 05, 2016
70 
71  */
72 
73 unsigned int powerOfTwo;
74 
75 gsl_fft_real_wavetable *fft_real = NULL;
76 gsl_fft_real_workspace *fft_work = NULL;
77 gsl_fft_halfcomplex_wavetable *fft_hc = NULL;
79 
81 
83 {
84  int i, n, ret;
85  double fr, f, bw;
86  struct LP_IMAGE_INFO *image = h0;
87 
88  n = (int)image->head.noint;
89 
90  if(n == 0)
91  {
92  st_fail("No data loaded");
93 
94  return(0);
95  }
96 
97  bzero((char *)&fft_data[0], sizeof(fft_data));
98 
99  st_report("FFT: N = %d", n);
100 
101  /* Copy floats to double array */
102  for(i=0;i<n;i++)
103  {
104  fft_data[i] = image->yplot1[i];
105  }
106 
107  /* Free up work and real structs if already allocated */
108  if(fft_work)
109  {
110  gsl_fft_real_workspace_free (fft_work);
111 
112  fft_work = NULL;
113  }
114 
115  if(fft_real)
116  {
117  gsl_fft_real_wavetable_free (fft_real);
118 
119  fft_real = NULL;
120  }
121 
122  fft_work = gsl_fft_real_workspace_alloc (n);
123  fft_real = gsl_fft_real_wavetable_alloc (n);
124 
125  ret = gsl_fft_real_transform (fft_data, 1, n, fft_real, fft_work);
126 
127  st_report("FFT: Function returned %d", ret);
128 
129  if(!ret)
130  {
131  fr = fabs(image->head.freqres);
132 
133  /* Double the n because that's the original BW */
134  /* in this version of fft the results are 4 times??? */
135  bw = (fr * (double)n * 2.0);
136  f = 1.0 / bw;
137 
138  st_report("Freqres = %f MHz / Chan, BW = %f MHz", fr, fr * (double)n);
139 
140  strcpy(last_fft.magic, "FFT_INFO");
141 
142  bcopy((char *)&image->head, (char *)&last_fft.head, sizeof(last_fft.head));
143 
144  /* Skip the 0th lag */
145  for(i=0;i<n/2;i++)
146  {
147  last_fft.xdata[i] = (double)i * f;
148  last_fft.ydata[i] = fft_data[i] / bw * 2.0;
149  }
150 
151  last_fft.num = n/2;
152 
153  if(env->fft_xb || env->fft_xe)
154  {
155  st_report("FFT Display Truncated");
156  last_fft.xset = 1;
157  last_fft.xb = env->fft_xb;
158  last_fft.xe = env->fft_xe;
159  }
160  else
161  {
162  last_fft.xset = 0;
163  last_fft.xb = 0.0;
164  last_fft.xe = 0.0;
165  }
166 
167  if(xgraphic)
168  {
169  sock_write(xgraphic, (char *)&last_fft, sizeof(last_fft));
170 
172 
173  st_report("Sent FFT to xgraphic");
174  }
175  }
176  else
177  {
178  st_fail("FFT Failed");
179  }
180 
181  return(0);
182 }
183 
184 
186 double mx;
187 {
188  int i, n, mindx=0;
189  double min = 999999999.9;
190 
191  n = last_fft.num;
192 
193  st_report("FFT Num of Values %d", n);
194  for(i=0;i<n;i++)
195  {
196  if(fabs(last_fft.xdata[i] - mx) < min)
197  {
198  min = fabs(last_fft.xdata[i] - mx);
199  mindx = i;
200 
201  }
202  }
203 
204  st_report("FFT Found Index %d", mindx);
205 
206  return(mindx);
207 }
208 
209 
211 {
212  int i, n, nc, fft_indx;
213  float *f1;
214  double f, freeD, wireD, fft_freq;
215 
216  do
217  {
218  nc = getNumericResponse("Enter Number of Freqs [ Up to 8]: ");
219  }
220  while(nc < 0);
221 
222  if(nc > 8)
223  {
224  st_fail("Count out of range: 0x%x", nc);
225 
226  return(1);
227  }
228 
229  for(i=0;i<nc;i++)
230  {
231  _doTCur("Click the Left Mouse Button on Desired Freq");
232 
233  fft_indx = findExactFFTFreq(last_mouse_x);
234  fft_freq = last_fft.xdata[fft_indx];
235 
236  f = 1.0 / fft_freq;
237 
238  f *= 1e6; /* Convert to Hz */
239 
240  freeD = 1.0 / f * SPEED_OF_LIGHT;
241  wireD = 1.0 / f * SPEED_OF_LIGHT_COAX;
242 
243  freeD /= 2.0;
244  wireD /= 2.0;
245 
246  st_report("MHz-1 Selected: %7.4f uS", fft_freq);
247  st_report("Freq Selected: %7.4f MHz", f /= 1e6);
248  st_report("Free Space Distance: %7.4f Meters", freeD);
249  st_report("Coaxial Wire Distance: %7.4f Meters", wireD);
250 
251  /* Zero out the bad freq */
252  fft_data[fft_indx] = 0.0;
253  }
254 
255  if(nc)
256  {
257  n = last_fft.num * 2;
258 
259  if(fft_work->n != n)
260  {
261  st_fail("FFT Elements don't match: %d vs %d", n, fft_work->n);
262  return(0);
263  }
264 
265  /* Convert back to Freq domain */
266  fft_hc = gsl_fft_halfcomplex_wavetable_alloc(n);
267 
268  gsl_fft_halfcomplex_inverse(fft_data, 1, n, fft_hc, fft_work);
269 
270  gsl_fft_halfcomplex_wavetable_free(fft_hc);
271 
272  f1 = &h0->yplot1[0];
273  for(i=0;i<n;i++,f1++)
274  {
275  *f1 = (float)fft_data[i];
276  }
277 
278  xx();
279  }
280 
281  return(0);
282 }
283 
284 
286 {
287  int start, end;
288  int i, n;
289  float *f1;
290 
291  _doTCur("Click the Left Mouse Button on Left Freq");
292 
294 
295  _doTCur("Click the Left Mouse Button on Right Freq");
296 
298 
299  if(end > start)
300  {
301  for(i=start;i<end;i++)
302  {
303  fft_data[i] = 0.0;
304  }
305  }
306  else
307  {
308  st_fail("Ending freq < Starting");
309  return(1);
310  }
311 
312  n = last_fft.num * 2;
313 
314  if(fft_work->n != n)
315  {
316  st_fail("FFT Elements don't match: %d vs %d", n, fft_work->n);
317  return(0);
318  }
319 
320  /* Convert back to Freq domain */
321  fft_hc = gsl_fft_halfcomplex_wavetable_alloc(n);
322 
323  gsl_fft_halfcomplex_inverse(fft_data, 1, n, fft_hc, fft_work);
324 
325  gsl_fft_halfcomplex_wavetable_free(fft_hc);
326 
327  f1 = &h0->yplot1[0];
328  for(i=0;i<n;i++,f1++)
329  {
330  *f1 = (float)fft_data[i];
331  }
332 
333  xx();
334 
335  return(0);
336 }
337 
338 
339 int lp_fft()
340 {
341  if(isSet(PF_A_FLAG))
342  {
343  if(strlen(args->secondArg))
344  {
345  env->fft_xb = atof(args->secondArg);
346  }
347  else
348  {
349  st_fail("Missing arg for 'fft /a xx.x xx.x'");
350  return(1);
351  }
352 
353  if(strlen(args->thirdArg))
354  {
355  env->fft_xe = atof(args->thirdArg);
356  }
357  else
358  {
359  st_fail("Missing arg for 'fft /a xx.x xx.x'");
360  return(1);
361  }
362 
363  return(0);
364  }
365 
366  if(isSet(PF_C_FLAG))
367  {
368  lp_fftcut();
369  return(0);
370  }
371 
372  if(isSet(PF_P_FLAG))
373  {
374  lp_fftpick();
375  return(0);
376  }
377 
378  if(isSet(PF_R_FLAG))
379  {
380  st_report("Reseting fft plot axis to defaults");
381 
382  env->fft_xb = 0.0;
383  env->fft_xe = 0.0;
384 
385  return(0);
386  }
387 
388  /* else do an actual fft */
389  lp_fftcomp();
390 
391  return(0);
392 }
struct SOCK * xgraphic
Definition: linuxpops.c:75
int lp_fftcut()
Definition: fft.c:285
float yplot1[MAX_CHANS]
Definition: image.h:110
struct LP_IMAGE_INFO * h0
Definition: image.c:74
int xx()
Definition: linuxpops.c:605
int sock_write(struct SOCK *s, char *message, int l)
struct PARSE_STACK * args
Definition: parse.h:196
gsl_fft_real_wavetable * fft_real
Definition: fft.c:75
double noint
Definition: header.h:211
#define SPEED_OF_LIGHT
Definition: defines.h:126
Definition: parse.h:8
double last_mouse_x
Definition: env.c:82
#define MAX_CHANS
Definition: defines.h:38
double fft_xe
Definition: env.h:192
#define min(a, b)
Definition: cactus.h:114
#define SPEED_OF_LIGHT_COAX
Definition: defines.h:127
int lp_fft()
Definition: fft.c:339
int lp_fftcomp()
Definition: fft.c:82
gsl_fft_halfcomplex_wavetable * fft_hc
Definition: fft.c:77
double fft_data[MAX_CHANS]
Definition: fft.c:78
struct ENVIRONMENT * env
Definition: linuxpops.c:71
char * thirdArg
Definition: parse.h:182
int isSet(int flag)
Definition: parse.c:646
#define LAST_PLOT_SPEC_FFT
Definition: defines.h:157
struct HEADER head
Definition: image.h:104
float xe
Definition: lp_fft.h:13
unsigned int powerOfTwo
Definition: fft.c:73
float ydata[MAX_FFT_LENGTH]
Definition: lp_fft.h:18
int xset
Definition: lp_fft.h:11
void st_fail()
struct HEADER head
Definition: lp_fft.h:15
int getNumericResponse()
float xdata[MAX_FFT_LENGTH]
Definition: lp_fft.h:17
int findExactFFTFreq(double mx)
Definition: fft.c:185
char magic[32]
Definition: lp_fft.h:8
int num
Definition: lp_fft.h:9
void st_report()
int last_plot
Definition: env.c:93
struct FFT_INFO last_fft
Definition: fft.c:80
int lp_fftpick()
Definition: fft.c:210
double fft_xb
Definition: env.h:191
gsl_fft_real_workspace * fft_work
Definition: fft.c:76
float xb
Definition: lp_fft.h:12
char * secondArg
Definition: parse.h:181
int _doTCur(char *msg)
Definition: linuxpops.c:2580
double freqres
Definition: header.h:199
Definition: lp_fft.h:7