ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/globalhs/apps/jtsslice.c
Revision: 1.12
Committed: Sun Apr 28 08:05:21 2013 UTC (10 years, 4 months ago) by tplarson
Content type: text/plain
Branch: MAIN
CVS Tags: globalhs_version_5, Ver_8-7, Ver_8-5, globalhs_version_23, globalhs_version_22, globalhs_version_21, globalhs_version_20, Ver_LATEST, globalhs_version_24, Ver_8-3, globalhs_version_8, globalhs_version_9, globalhs_version_0, globalhs_version_1, globalhs_version_2, globalhs_version_3, globalhs_version_4, Ver_9-41, globalhs_version_6, globalhs_version_7, Ver_9-5, Ver_8-8, globalhs_version_19, Ver_8-2, Ver_8-10, Ver_8-1, Ver_8-6, Ver_9-1, Ver_8-4, Ver_9-2, globalhs_version_12, globalhs_version_13, globalhs_version_10, globalhs_version_11, globalhs_version_16, globalhs_version_17, globalhs_version_14, globalhs_version_15, globalhs_version_18, Ver_9-4, Ver_9-3, Ver_8-11, Ver_8-12, Ver_9-0, HEAD
Changes since 1.11: +3 -2 lines
Log Message:
changed how cvs versions are tracked.

File Contents

# Content
1 /*
2 this module creates power spectra out of slices of timeseries
3 based on jtsfiddle, but no detrending or gapfilling
4 */
5
6 /*
7 * Detrending/gapfilling/differencing module
8 * ts_fiddle_rml upgrades ts_fiddle
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <strings.h>
14 #include <time.h>
15 #include <sys/time.h>
16 #include <sys/resource.h>
17 #include <math.h>
18 #include <assert.h>
19 #include <fftw3.h>
20
21 #include "jsoc_main.h"
22 #include "fitsio.h"
23
24 #define ARRLENGTH(ARR) (sizeof(ARR)/sizeof(ARR[0]))
25 #define kNOTSPECIFIED "not specified"
26
27 char *module_name = "jtsslice";
28 char *cvsinfo_jtsslice = "cvsinfo: $Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jtsslice.c,v 1.11 2012/09/24 20:06:23 tplarson Exp $";
29
30 /* Command line arguments: */
31 ModuleArgs_t module_args[] =
32 {
33 {ARG_STRING, "in", "", "input data records"},
34 {ARG_STRING, "out", "", "output data series"},
35 {ARG_STRING, "segin" , kNOTSPECIFIED, "name of input segment if not using segment 0"},
36 {ARG_STRING, "segout", kNOTSPECIFIED, "name of output segment if not using segment 0"},
37 {ARG_STRING, "histlink", "HISTORY", "name of link to ancillary dataseries for processing metadata"},
38 {ARG_STRING, "srclink", "SRCDATA", "name of link to source data"},
39 {ARG_INT, "PERM", "1", "set to 0 for transient records, nonzero for permanent records"},
40 {ARG_INT, "VERB", "1", "option for level of verbosity: 0=only error and warning messages; >0=print messages outside of loop; >1=print messages inside loop; >2=debugging output", NULL},
41 {ARG_STRING, "GAPFILE", "", "record or file containing window function"},
42
43 {ARG_INT, "NDT", "-1", "", ""},
44 {ARG_STRING, "TTOTAL", NULL, "total length of time in output"},
45
46 {ARG_INT, "IFIRST", "0", "", ""},
47 // {ARG_INT, "FLIPM", "0", "", ""},
48
49 {ARG_INT, "TSOUT", "0", "", ""},
50 {ARG_INT, "FFTOUT", "0", "", ""},
51 {ARG_INT, "FFT1OUT", "0", "", ""},
52 {ARG_INT, "POWOUT", "0", "", ""},
53 {ARG_INT, "MAVGOUT", "0", "", ""},
54 {ARG_INT, "NAVG", "0", "", ""},
55 {ARG_INT, "NSKIP", "0", "", ""},
56 {ARG_INT, "NOFF", "0", "", ""},
57 {ARG_INT, "IMIN", "0", "", ""},
58 {ARG_INT, "IMAX", "-1", "", ""},
59 {ARG_END},
60 };
61
62 #include "saveparm.c"
63 #include "timing.c"
64 #include "set_history.c"
65
66 #define DIE(code) { fprintf(stderr,"jtsslice died with error code %d\n",(code)); return 0;}
67
68 /* global variables holding the values of the command line variables. */
69 static char *gapfile;
70 static int lmode, n_sampled_out, flipm;
71 static float tsample;
72 static int ifirst, tsout,fftout, fft1out, powout, mavgout;
73 static int navg, nskip, noff, imin, imax;
74
75
76 /* Prototypes for local functions. */
77 static double splitting(int l, int m);
78
79 /* Prototypes for external functions */
80 extern void cffti_(int *, float *);
81 extern void cfftb_(int *, float *, float *);
82 static int extract_gaps(int n_in, int *gaps_in, int *n_out, int *gaps_out,
83 float tsample_in, float *tsample_out,
84 int *num_sections, int *sections);
85 static void extract_data(int n_in, int *gaps, float *data_in, float *data_out);
86
87 /************ Here begins the main module **************/
88 int DoIt(void)
89 {
90 int i;
91 int start_index[2], counts[2], intervals[2];
92 int m, n_in, n_sampled_in;
93 TIME epoch, step, start, stop;
94 int gapsize, istart, istop, data_dim, detrend_order;
95 int npow, mshift;
96 float tsamplex, df1, c;
97 int *agaps;
98 int *gaps;
99 float *msum, *pow;
100 float *data, *out_data, *in_data;
101 fftwf_plan plan;
102 int num_sections, *sections;
103 char tstartstr[100];
104
105 int fstatus = 0;
106 fitsfile *fitsptr;
107 long fdims[1];
108 long fpixel[]={1};
109 int *anynul=0;
110
111 int length[2], startind[2], endind[2];
112 float *datarr;
113 int status=DRMS_SUCCESS;
114 int newstat=0;
115 char *ttotal;
116 double nseconds;
117
118 DRMS_Segment_t *segin = NULL;
119 DRMS_Segment_t *segout = NULL;
120 DRMS_Array_t *inarr = NULL;
121 DRMS_Array_t *outarr = NULL;
122 DRMS_Record_t *inrec = NULL;
123 DRMS_Record_t *outrec = NULL;
124 DRMS_Type_t usetype = DRMS_TYPE_FLOAT;
125 DRMS_RecLifetime_t lifetime;
126 long long histrecnum = -1;
127 DRMS_Segment_t *gapseg = NULL;
128 DRMS_Array_t *gaparr = NULL;
129
130 HIterator_t outKey_list;
131 DRMS_Keyword_t *outKey;
132 TIME tnow, UNIX_epoch = -220924792.000; /* 1970.01.01_00:00:00_UTC */
133
134 int errbufstat=setvbuf(stderr, NULL, _IONBF, BUFSIZ);
135 int outbufstat=setvbuf(stdout, NULL, _IONBF, BUFSIZ);
136
137 double tstart, tstartsave, tstop, tstopsave, cadence, tstartout, tstopout;
138 double wt0, wt1, wt2, wt3, wt;
139 double ut0, ut1, ut2, ut3, ut;
140 double st0, st1, st2, st3, st;
141 double ct0, ct1, ct2, ct3, ct;
142
143 wt0=getwalltime();
144 ct0=getcputime(&ut0, &st0);
145
146 /* Read input parameters. */
147 gapfile = (char *)cmdparams_save_str (&cmdparams, "GAPFILE", &newstat);
148 n_sampled_out = cmdparams_save_int (&cmdparams, "NDT", &newstat);
149 ifirst = cmdparams_save_int (&cmdparams, "IFIRST", &newstat);
150 // flipm = cmdparams_save_int (&cmdparams, "FLIPM", &newstat);
151 tsout = cmdparams_save_int (&cmdparams, "TSOUT", &newstat);
152 fftout = cmdparams_save_int (&cmdparams, "FFTOUT", &newstat);
153 fft1out = cmdparams_save_int (&cmdparams, "FFT1OUT", &newstat);
154 powout = cmdparams_save_int (&cmdparams, "POWOUT", &newstat);
155 mavgout = cmdparams_save_int (&cmdparams, "MAVGOUT", &newstat);
156 navg = cmdparams_save_int (&cmdparams, "NAVG", &newstat);
157 nskip = cmdparams_save_int (&cmdparams, "NSKIP", &newstat);
158 noff = cmdparams_save_int (&cmdparams, "NOFF", &newstat);
159 imin = cmdparams_save_int (&cmdparams, "IMIN", &newstat);
160 imax = cmdparams_save_int (&cmdparams, "IMAX", &newstat);
161
162 char *inrecquery = (char *)cmdparams_save_str(&cmdparams, "in", &newstat);
163 char *outseries = (char *)cmdparams_save_str(&cmdparams, "out", &newstat);
164 char *segnamein = (char *)cmdparams_save_str(&cmdparams, "segin", &newstat);
165 char *segnameout = (char *)cmdparams_save_str(&cmdparams, "segout", &newstat);
166 int seginflag = strcmp(kNOTSPECIFIED, segnamein);
167 int segoutflag = strcmp(kNOTSPECIFIED, segnameout);
168 char *histlinkname = (char *)cmdparams_save_str(&cmdparams, "histlink", &newstat);
169 char *srclinkname = (char *)cmdparams_save_str(&cmdparams, "srclink", &newstat);
170 int verbflag = cmdparams_save_int(&cmdparams, "VERB", &newstat);
171 int permflag = cmdparams_save_int(&cmdparams, "PERM", &newstat);
172 if (permflag)
173 lifetime = DRMS_PERMANENT;
174 else
175 lifetime = DRMS_TRANSIENT;
176
177 ttotal=(char *)cmdparams_save_str(&cmdparams, "TTOTAL", &newstat);
178 status=drms_names_parseduration(&ttotal, &nseconds, 1);
179 if (status != DRMS_SUCCESS)
180 {
181 fprintf(stderr, "ERROR: problem parsing TTOTAL, = %s\n", ttotal);
182 return 1;
183 }
184
185 if (newstat)
186 {
187 fprintf(stderr, "ERROR: problem with input arguments, status = %d, diagnosis follows\n", newstat);
188 cpsave_decode_error(newstat);
189 return 1;
190 }
191 else if (savestrlen != strlen(savestr))
192 {
193 fprintf(stderr, "ERROR: problem with savestr, savestrlen = %d, strlen(savestr) = %d\n", savestrlen, (int)strlen(savestr));
194 return 1;
195 }
196
197
198 /**** Sanity check of input parameters. ****/
199
200 /* Default is to just output the timeseries. */
201 if ((tsout == 0) && (fftout == 0) && (fft1out == 0) && (powout == 0) && (mavgout == 0))
202 tsout=1;
203 /* Only one type of output allowed at a time */
204 if ((tsout+fftout+fft1out+powout+mavgout) !=1)
205 {
206 fprintf(stderr, "ERROR: only one type of output allowed at a time\n");
207 return 1;
208 }
209 if (navg <= 0)
210 navg=1;
211 if (nskip <= 0)
212 nskip=1;
213 if ((navg != 1) && (nskip != 1))
214 {
215 fprintf(stderr, "ERROR: one of navg and nskip must equal 1\n");
216 return 1;
217 }
218 if (noff < 0 || noff >= nskip)
219 {
220 fprintf(stderr, "ERROR: noff must be >= 0 and < nskip\n");
221 return 1;
222 }
223
224
225 DRMS_Record_t *tempoutrec = drms_create_record(drms_env,
226 outseries,
227 DRMS_TRANSIENT,
228 &status);
229
230 if (status != DRMS_SUCCESS)
231 {
232 fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", outseries, status);
233 return 1;
234 }
235
236 DRMS_Link_t *histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
237 DRMS_Link_t *srclink = hcon_lookup_lower(&tempoutrec->links, srclinkname);
238
239 // char *cvsinfo = strdup("$Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jtsslice.c,v 1.11 2012/09/24 20:06:23 tplarson Exp $");
240 if (histlink != NULL)
241 {
242 histrecnum=set_history(histlink);
243 if (histrecnum < 0)
244 {
245 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
246 return 1;
247 }
248 }
249 else
250 {
251 fprintf(stderr,"WARNING: could not find history link in output dataseries\n");
252 }
253
254 // these must be present in the output dataseries and variable, not links or constants
255 char *outchecklist[] = {"T_START", "QUALITY", "LMIN", "LMAX", "NDT"};
256
257 int itest;
258 for (itest=0; itest < ARRLENGTH(outchecklist); itest++)
259 {
260 DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]);
261 if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1)
262 {
263 fprintf(stderr, "ERROR: output keyword %s is either missing, constant, or a link\n", outchecklist[itest]);
264 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
265 return 1;
266 }
267 }
268
269 cadence=drms_getkey_float(tempoutrec, "T_STEP", &status);
270 double chunksecs = n_sampled_out*cadence;
271 if (fmod(nseconds,chunksecs) != 0.0)
272 {
273 fprintf(stderr, "ERROR: input parameters seem incompatible (chunksecs must divide nseconds): nseconds = %f, chunksecs = %f\n", nseconds, chunksecs);
274 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
275 return 1;
276 }
277 int ntimechunks = nseconds/chunksecs;
278 tsample=cadence;
279
280 int mflipout = drms_getkey_int(tempoutrec, "MFLIPPED", &status);
281 if (status != DRMS_SUCCESS) mflipout=0;
282
283 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
284
285
286 if (fits_open_file(&fitsptr, gapfile, READONLY, &fstatus))
287 {
288 DRMS_RecordSet_t *gaprecset = drms_open_records(drms_env, gapfile, &status);
289 if (status != DRMS_SUCCESS || gaprecset == NULL)
290 {
291 fprintf(stderr,"ERROR: problem reading gaps: file status = %d, DRMS status = %d\n",fstatus,status);
292 return 1;
293 }
294 if (gaprecset->n == 0)
295 {
296 fprintf(stderr,"ERROR: gapfile recordset contains no records\n");
297 return 1;
298 }
299 if (gaprecset->n > 1)
300 {
301 fprintf(stderr,"ERROR: gapfile recordset with more than 1 record not yet supported.\n");
302 return 1;
303 }
304 gapseg = drms_segment_lookupnum(gaprecset->records[0], 0);
305 if (gapseg != NULL)
306 gaparr = drms_segment_read(gapseg, DRMS_TYPE_INT, &status);
307 if (status != DRMS_SUCCESS || gaparr == NULL || gapseg == NULL)
308 {
309 fprintf(stderr, "ERROR: problem reading gaps segment: status = %d\n", status);
310 return 1;
311 }
312 agaps=(int *)(gaparr->data);
313 gapsize=gaparr->axis[0];
314 }
315 else
316 {
317 fits_get_img_size(fitsptr, 1, fdims, &fstatus);
318 gapsize=fdims[0];
319 agaps=(int *)(malloc(gapsize*sizeof(int)));
320 fits_read_pix(fitsptr, TINT, fpixel, gapsize, NULL, agaps, anynul, &fstatus);
321 fits_close_file(fitsptr, &fstatus);
322 if (fstatus)
323 {
324 fprintf(stderr, "ERROR: ");
325 fits_report_error(stderr, fstatus);
326 return 1;
327 }
328 }
329
330 if (verbflag)
331 printf("gapfile read, gapsize = %d\n",gapsize);
332
333 data_dim=gapsize;
334 if (n_sampled_out>gapsize)
335 data_dim=n_sampled_out;
336
337 num_sections=1;
338 sections = malloc(2*sizeof(int));
339 sections[0] = 0;
340 sections[1] = data_dim-1;
341
342 /* allocate temporary storage */
343 gaps=(int *)(malloc(gapsize*sizeof(int)));
344 data=(float *)(fftwf_malloc(2*data_dim*sizeof(float)));
345
346 DRMS_RecordSet_t *inrecset = drms_open_records(drms_env, inrecquery, &status);
347
348 if (status != DRMS_SUCCESS || inrecset == NULL)
349 {
350 fprintf(stderr,"ERROR: problem opening input recordset: status = %d\n",status);
351 return 1;
352 }
353
354 if (inrecset->n == 0)
355 {
356 fprintf(stderr, "ERROR: input recordset contains no records\n");
357 return 1;
358 }
359
360 inrec=inrecset->records[0];
361 char *inchecklist[] = {"T_START", "QUALITY", "LMIN", "LMAX", "T_STEP"};
362
363 for (itest=0; itest < ARRLENGTH(inchecklist); itest++)
364 {
365 DRMS_Keyword_t *inkeytest = hcon_lookup_lower(&inrec->keywords, inchecklist[itest]);
366 if (inkeytest == NULL)
367 {
368 fprintf(stderr, "ERROR: required input keyword %s is missing\n", inchecklist[itest]);
369 drms_close_records(inrecset, DRMS_FREE_RECORD);
370 return 1;
371 }
372 }
373
374 tstartsave=drms_getkey_time(inrec, "T_START", NULL); //must be constant across all input records unless GAPFILE is implemented differently
375
376 int mflipin = drms_getkey_int(inrec, "MFLIPPED", &status);
377 if (status != DRMS_SUCCESS) mflipin=0;
378
379 if (mflipout != mflipin)
380 flipm=1;
381 else
382 flipm=0;
383
384 // changed n_in to gapsize in following call
385 if (extract_gaps(gapsize, agaps, &n_sampled_in, gaps, tsample, &tsamplex, &num_sections, sections))
386 {
387 fprintf(stderr, "ERROR: problem in extract_gaps\n");
388 return 0;
389 }
390
391 if (n_sampled_out == -1)
392 n_sampled_out = n_sampled_in;
393 df1 = tsamplex*n_sampled_out;
394
395 if (fftout || fft1out || powout || mavgout)
396 plan = fftwf_plan_dft_1d(n_sampled_out, (fftwf_complex *)data,
397 (fftwf_complex *)data, FFTW_BACKWARD, FFTW_MEASURE);
398
399 /* Set sum to zero before starting */
400 if (mavgout)
401 msum = (float *)calloc(n_sampled_out/2,sizeof(float));
402
403 if (fft1out || powout || mavgout)
404 {
405 /* Set first and last output index if not set as a parameter. */
406 if (imax < imin)
407 {
408 imin=0;
409 imax=n_sampled_out/2-1;
410 }
411 npow=imax-imin+1;
412 pow=(float *)(malloc(n_sampled_out*sizeof(float)));
413 }
414
415
416 status=drms_stage_records(inrecset, 1, 0);
417 if (status != DRMS_SUCCESS)
418 {
419 fprintf(stderr, "ERROR: drms_stage_records returned status = %d\n", status);
420 return 1;
421 }
422
423 int nrecsout = ntimechunks * inrecset->n;
424 DRMS_RecordSet_t *outrecset = drms_create_records(drms_env, nrecsout, outseries, DRMS_PERMANENT, &status);
425 if (status != DRMS_SUCCESS || outrecset == NULL)
426 {
427 fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", outseries, status);
428 return 1;
429 }
430
431 int gapoffset, gapoffset0 = ifirst;
432 double tstart0 = tstartsave+ifirst*tsample;
433 int irec;
434 for (irec=0;irec<inrecset->n;irec++)
435 {
436
437 inrec = inrecset->records[irec];
438
439 int lmin=drms_getkey_int(inrec, "LMIN", NULL);
440 int lmax=drms_getkey_int(inrec, "LMAX", NULL);
441 if (lmin != lmax)
442 {
443 fprintf(stderr, "ERROR: lmin != lmax not yet supported.\n");
444 return 0;
445 }
446 lmode=lmin;
447
448 if (verbflag)
449 printf("starting l=%d\n",lmode);
450
451 tstart=drms_getkey_time(inrec, "T_START", NULL);
452 tstop =drms_getkey_time(inrec, "T_STOP", NULL);
453 cadence=drms_getkey_float(inrec, "T_STEP", NULL);
454 if (tstart != tstartsave)
455 {
456 // to lift this restriction must be able to specify multiple gap files/records as input
457 sprint_time(tstartstr, tstart, "TAI", 0);
458 fprintf(stderr, "ERROR: all input records must have same T_START, record %d has %s\n", irec, tstartstr);
459 return 0;
460 }
461
462 n_in=(tstop-tstart)/cadence;
463 if (n_in != gapsize)
464 {
465 fprintf(stderr, "ERROR: gaps seem incompatible with time-series, gapsize=%d, n_in=%d\n", gapsize, n_in);
466 return 0;
467 }
468
469 /* Create output data set. */
470 if (tsout || fftout)
471 {
472 length[0]=2*n_sampled_out;
473 length[1]=lmode+1;
474 }
475 else
476 {
477 if (fft1out)
478 length[0]=2*npow;
479 else
480 length[0]=npow;
481 if (powout || fft1out)
482 length[1]=2*lmode+1;
483 else
484 length[1]=1;
485 }
486
487 startind[1]=0;
488 endind[1]=lmode;
489
490 if (seginflag)
491 segin = drms_segment_lookup(inrec, segnamein);
492 else
493 segin = drms_segment_lookupnum(inrec, 0);
494 if (segin == NULL)
495 {
496 fprintf(stderr, "ERROR: problem reading input segment: recnum = %ld\n", inrec->recnum);
497 return 0;
498 }
499
500 int iset;
501 for (iset=0; iset < ntimechunks; iset++)
502 {
503 tstartout=tstart0 + iset * chunksecs;
504 tstopout=tstartout+chunksecs;
505 sprint_time(tstartstr, tstartout, "TAI", 0);
506 gapoffset = gapoffset0 + iset*n_sampled_out;
507
508 if (verbflag>1)
509 {
510 printf(" starting tstart = %s, ",tstartstr);
511 if (irec == 0)
512 {
513 int ig, gtotal=0;
514 for (ig=0;ig<n_sampled_out;ig++)
515 gtotal+=gaps[gapoffset+ig];
516 float dutycycle = (float)gtotal/n_sampled_out;
517 printf("dutycycle = %f\n", dutycycle);
518 }
519 }
520
521 // set ifirst to gapoffset for reading slice
522 ifirst=gapoffset;
523 startind[0]=2*(ifirst);
524 endind[0]=2*(ifirst + n_sampled_out) - 1;
525 // set ifirst=0 because data is read starting at ifirst by drms_segment_readslice
526 ifirst=0;
527
528 inarr = drms_segment_readslice(segin, usetype, startind, endind, &status);
529 if (status != DRMS_SUCCESS || inarr == NULL)
530 {
531 fprintf(stderr, "ERROR: problem reading input segment: recnum = %ld, status = %d\n", inrec->recnum, status);
532 return 0;
533 }
534 datarr=(float *)(inarr->data);
535
536 /*
537 outrec = drms_create_record(drms_env, outseries, lifetime, &status);
538 if (status != DRMS_SUCCESS || outrec==NULL)
539 {
540 fprintf(stderr,"ERROR: unable to open record in output dataseries, status = %d\n", status);
541 return 0;
542 }
543 */
544 // outrec = outrecset->records[ntimechunks*irec+iset];
545 outrec = outrecset->records[iset*inrecset->n + irec];
546
547 if (histlink != NULL)
548 drms_setlink_static(outrec, histlinkname, histrecnum);
549 if (srclink != NULL)
550 drms_setlink_static(outrec, srclinkname, inrec->recnum);
551
552 if (segoutflag)
553 segout = drms_segment_lookup(outrec, segnameout);
554 else
555 segout = drms_segment_lookupnum(outrec, 0);
556 outarr = drms_array_create(usetype, 2, length, NULL, &status);
557 if (status != DRMS_SUCCESS || outarr == NULL || segout == NULL)
558 {
559 fprintf(stderr,"ERROR: problem creating output array or segment: length = [%d, %d], status = %d", length[0], length[1], status);
560 return 0;
561 }
562 out_data = outarr->data;
563
564 /***** Main Loop over m: Detrend, gapfill and/or compute FFT/power spectrum *******/
565 for (m=0; m<=lmode; m++)
566 {
567
568 if (verbflag>2)
569 printf(" starting m=%d\n",m);
570
571 in_data=datarr + m*2*n_sampled_out;
572
573 /* Extracts data copy */
574 extract_data(n_sampled_out, gaps+gapoffset, in_data, data);
575
576 /* pad with zeros if the last point output (n_sampled_out+ifirst)
577 is after the last data points read in (nread). */
578 memmove(data, &data[2*ifirst], 2*(n_sampled_in-ifirst)*sizeof(float));
579 if ((ifirst+n_sampled_out) >= n_sampled_in)
580 memset(&data[2*n_sampled_in], 0, 2*(n_sampled_out+ifirst-n_sampled_in)*sizeof(float));
581
582 if (fftout || fft1out || powout || mavgout)
583 fftwf_execute(plan);
584
585 if (tsout || fftout)
586 memcpy(&out_data[2*m*n_sampled_out], &data[2*ifirst], 2*n_sampled_out*sizeof(float));
587
588 else if (fft1out)
589 {
590 /* Do positive m */
591 memcpy(&out_data[2*(lmode+m)*npow], &data[2*imin], 2*npow*sizeof(float));
592 if (m > 0)
593 {
594 /* Do negative m */
595 for (i=0; i<npow; i++)
596 {
597 /* Conjugate for negative m */
598 out_data[2*((lmode-m)*npow+i)] = data[2*(n_sampled_out-imin-i)];
599 out_data[2*((lmode-m)*npow+i)+1] = -data[2*(n_sampled_out-imin-i)+1];
600 }
601 }
602 }
603 else
604 {
605 /* Compute power spectrum from complex FFT. */
606 for (i = 0; i < n_sampled_out; i++)
607 pow[i] = data[2*i]*data[2*i] + data[2*i+1]*data[2*i+1];
608 if (powout)
609 {
610 /* Do positive m */
611 memcpy(&out_data[(lmode+m)*npow], &pow[imin], npow*sizeof(float));
612 if (m > 0)
613 {
614 /* Do negative m */
615 if (imin)
616 out_data[(lmode-m)*npow] = pow[n_sampled_out-imin];
617 else
618 out_data[(lmode-m)*npow] = pow[0];
619 for (i=1; i<npow;i++)
620 out_data[(lmode-m)*npow+i] = pow[n_sampled_out-imin-i];
621 }
622 }
623 else
624 {
625 /* m-averaged output */
626 /* Sum all freqs, not only those in output. Should be fixed. */
627 /* Maybe should allow for wrapping around Nyquist. */
628 /* Do positive m */
629 mshift = floor(df1*splitting(lmode,m)+0.5f);
630 if (mshift >= 0)
631 for (i=0; i<n_sampled_out/2-mshift; i++)
632 msum[i] += pow[mshift+i];
633 else
634 for (i=0; i<n_sampled_out/2+mshift; i++)
635 msum[i-mshift] += pow[i];
636 if (m > 0)
637 {
638 /* Do negative m */
639 mshift = floor(df1*splitting(lmode,-m)+0.5f);
640 if (mshift >=0)
641 for (i=1; i<n_sampled_out/2-mshift;i++)
642 msum[i] += pow[n_sampled_out-mshift-i];
643 else
644 for (i=1; i<n_sampled_out/2+mshift; i++)
645 msum[i-mshift] += pow[n_sampled_out-i];
646 }
647 }
648 }
649
650 } /* End of m loop */
651
652 drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit);
653 drms_setkey_int(outrec, "QUALITY", 0);
654 drms_setkey_time(outrec, "T_START", tstartout);
655 drms_setkey_time(outrec, "T_STOP", tstopout);
656 drms_setkey_time(outrec, "T_OBS", (tstartout + tstopout)/2);
657 drms_setkey_float(outrec, "T_STEP", tsamplex);
658 drms_setkey_int(outrec, "NDT", n_sampled_out);
659
660 tnow = (double)time(NULL);
661 tnow += UNIX_epoch;
662 drms_setkey_time(outrec, "DATE", tnow);
663
664 if (mavgout)
665 {
666 c=1.0f/(2*lmode+1);
667 for (i=0; i<npow; i++)
668 out_data[i] = msum[imin+i] * c;
669 }
670
671 outarr->bzero=segout->bzero;
672 outarr->bscale=segout->bscale;
673 status=drms_segment_write(segout, outarr, 0);
674 if (status != DRMS_SUCCESS)
675 {
676 fprintf(stderr, "ERROR: problem writing output segment: status = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", status, tstartstr, lmode, histrecnum);
677 return 0;
678 }
679 drms_free_array(outarr);
680 drms_free_array(inarr);
681 // drms_close_record(outrec, DRMS_INSERT_RECORD);
682
683 }
684
685 }
686
687 drms_close_records(inrecset, DRMS_FREE_RECORD);
688 drms_close_records(outrecset, DRMS_INSERT_RECORD);
689
690 if (fftout || fft1out || powout || mavgout)
691 fftwf_destroy_plan(plan);
692
693 wt=getwalltime();
694 ct=getcputime(&ut, &st);
695 if (verbflag)
696 {
697 fprintf(stdout, "total time spent: %.2f ms wall time, %.2f ms cpu time\n",
698 wt-wt0, ct-ct0);
699 }
700
701 printf("module %s successful completion\n", cmdparams.argv[0]);
702 return 0;
703 }
704
705
706 static double splitting(int l, int m)
707 {
708 double a1x[] = {406.0,407.0,408.0,410.5,412.0,411.5,409.0,406.0,406.0};
709 double a3x[] = {10.0,10.0,15.0,19.5,21.0,21.3,21.3,21.3,21.8};
710 double a5x[] = {0.0,0.0,0.0,-1.5,-2.5,-3.5,-4.0,-4.0,-4.5};
711 /* f0 is the frequency used for generating the above a-coeff */
712 double f0 = 1500.0;
713 /* fcol is the frequency for which to optimize the collaps */
714 double fcol = 800.0;
715
716 double ll,x,x3,x5,a1,a2,a3,a5,frac,lx;
717 int ix;
718
719 if (l == 0)
720 ll = 1;
721 else
722 ll = sqrt(l*(l+1.));
723 x = m/ll;
724 x3 = x*x*x;
725 x5 = x3*x*x;
726 lx = 5*log10(l*f0/fcol)-4;
727 ix = floor(lx);
728 frac = lx-ix;
729 if (lx <= 0) {
730 ix = 0;
731 frac = 0.0;
732 }
733 if (lx >=8) {
734 ix = 7;
735 frac = 1.0;
736 }
737 a1 = (1.0-frac)*a1x[ix]+frac*a1x[ix+1];
738 a2 = 0.0;
739 a3 = (1.0-frac)*a3x[ix]+frac*a3x[ix+1];
740 a5 = (1.0-frac)*a5x[ix]+frac*a5x[ix+1];
741
742 return ll*(a1*x+a2*(1.5*x*x-0.5)+a3*(2.5*x3-1.5*x)+a5*(63./8.*x5-70./8.*x3+15./8.*x))/1e9;
743 }
744
745
746
747 /* Extract the data samples actually used by skipping or averaging
748 data. Replace missing data that are not marked as gaps with zero. */
749 void extract_data(int n_in, int *gaps, float *data_in, float *data_out)
750 {
751 int i,j, nmiss = 0;
752 // the following check will be skipped in production executables since they will be built with NDEBUG defined.
753 // it doesn't matter because the check is already done in DoIt().
754 assert(nskip==1 || navg==1);
755 if ((navg == 1) && (nskip == 1))
756 {
757 for (i=0; i<n_in; i++)
758 {
759 if (gaps[i]==0 )
760 {
761 data_out[2*i] = 0.0f;
762 data_out[2*i+1] = 0.0f;
763 }
764 else
765 {
766 if (isnan(data_in[2*i]) || isnan(data_in[2*i+1]))
767 {
768 data_out[2*i] = 0.0f;
769 data_out[2*i+1] = 0.0f;
770 gaps[i] = 0;
771 nmiss++;
772 }
773 else
774 {
775 data_out[2*i] = data_in[2*i];
776 data_out[2*i+1] = flipm ? -data_in[2*i+1] : data_in[2*i+1];
777 }
778 }
779 }
780 }
781 else if (nskip != 1)
782 {
783 for (i = 0; i<n_in; i++)
784 {
785 if (gaps[i]==0 )
786 {
787 data_out[2*i] = 0.0f;
788 data_out[2*i+1] = 0.0f;
789 }
790 else
791 {
792 int ix = nskip*i+noff;
793 if (isnan(data_in[2*ix]) || isnan(data_in[2*ix+1]))
794 {
795 data_out[2*i] = 0.0f;
796 data_out[2*i+1] = 0.0f;
797 gaps[i] = 0;
798 nmiss++;
799 }
800 else
801 {
802 data_out[2*i] = data_in[2*ix];
803 data_out[2*i+1] = flipm ? -data_in[2*ix+1] : data_in[2*ix+1];
804 }
805 }
806 }
807 }
808 else if (navg != 1)
809 {
810 for (i = 0; i<n_in; i++)
811 {
812 if (gaps[i]==0 )
813 {
814 data_out[2*i] = 0.0f;
815 data_out[2*i+1] = 0.0f;
816 }
817 else
818 {
819 float avgr = 0.0f;
820 float avgi = 0.0f;
821 for (j=0; j<navg; j++)
822 {
823 int ix = navg*i+j;
824 if (isnan(data_in[2*ix]) || isnan(data_in[2*ix+1]))
825 {
826 data_out[2*i] = 0.0f;
827 data_out[2*i+1] = 0.0f;
828 gaps[i] = 0;
829 nmiss++;
830 break;
831 }
832 else
833 {
834 avgr += data_in[2*ix];
835 avgi += data_in[2*ix+1];
836 }
837 }
838 if (j == navg)
839 {
840 data_out[2*i] = avgr/navg;
841 data_out[2*i+1] = avgi/navg;
842 }
843 }
844 }
845 }
846 }
847
848 /* Extract the windows function for the samples actually used after
849 subsampling or averaging. Modify the list of continous sections
850 accordingly, and make sure we do not average across section boundaries. */
851 static int extract_gaps(int n_in, int *gaps_in, int *n_out, int *gaps_out,
852 float tsample_in, float *tsample_out,
853 int *num_sections, int *sections)
854 {
855 // the following check will be skipped in production executables since they will be built with NDEBUG defined.
856 // it doesn't matter because the check is already done in DoIt().
857 assert(nskip==1 || navg==1);
858 int i,j,sect, start,stop;
859
860
861 if (*num_sections<1)
862 {
863 fprintf(stderr,"Apparantly no sections of data available.");
864 return 1;
865 }
866 /* Mask out data that in between sections if this hasn't already been
867 done in gapfile. */
868 for (i=0; i<sections[0] && i<n_in; i++)
869 gaps_in[i] = 0;
870 for (sect=1; sect<(*num_sections); sect++)
871 {
872 for (i=sections[2*sect-1]+1; i<sections[2*sect] && i<n_in; i++)
873 gaps_in[i] = 0;
874 }
875 for (i=sections[2*(*num_sections-1)+1]+1; i<n_in; i++)
876 gaps_in[i] = 0;
877
878
879 if ((navg == 1) && (nskip == 1))
880 {
881 *n_out = n_in;
882 *tsample_out = tsample_in;
883 for (i=0; i<*n_out; i++)
884 gaps_out[i] = gaps_in[i];
885 }
886 else if (nskip != 1)
887 {
888 *n_out = n_in/nskip;
889 *tsample_out = nskip*tsample_in;
890 for (i=0; i<*n_out; i++)
891 {
892 gaps_out[i] = gaps_in[nskip*i+noff];
893 }
894 for (i=0; i<2*(*num_sections); i+=2)
895 {
896 start = (int)ceilf(((float)(sections[i]-noff))/nskip);
897 stop = (int)floorf(((float)(sections[i+1]-noff))/nskip);
898 if (start <= stop)
899 {
900 sections[i] = start;
901 sections[i+1] = stop;
902 }
903 else
904 {
905 /* This section was skipped entirely. */
906 for (j=i; j< 2*(*num_sections-1); j+=2)
907 {
908 sections[j] = sections[j+2];
909 sections[j+1] = sections[j+3];
910 }
911 *num_sections -= 1;
912 }
913 }
914 }
915 else if (navg != 1)
916 {
917 sect = 0;
918 *n_out = n_in/navg;
919 *tsample_out = tsample*navg;
920 for (i=0; i<*n_out; i++)
921 {
922 int igx = 1;
923 while (sect < *num_sections &&
924 !(navg*i >= sections[2*sect] && navg*i >= sections[2*sect+1]))
925 sect++;
926
927 /* Don't allow averaging of data from different sections. */
928 if (navg*i >= sections[2*sect] && (navg*i+navg-1)<=sections[2*sect+1])
929 {
930 for (j=0; j<navg; j++)
931 igx *= gaps_in[navg*i+j];
932 gaps_out[i] = igx;
933 }
934 else
935 gaps_out[i] = 0;
936 }
937 for (i=0; i<2*(*num_sections); i+=2)
938 {
939 start = (int)ceilf(((float)sections[i])/navg);
940 stop = (int)floorf(((float)sections[i+1])/navg);
941 if (start <= stop)
942 {
943 sections[i] = start;
944 sections[i+1] = stop;
945 }
946 else
947 {
948 /* This section was skipped entirely. */
949 for (j=i; j< 2*(*num_sections-1); j+=2)
950 {
951 sections[j] = sections[j+2];
952 sections[j+1] = sections[j+3];
953 }
954 *num_sections -= 1;
955 }
956 }
957 }
958 return 0;
959 }
960