1 tplarson 1.3 /*
2 this module creates power spectra out of slices of timeseries
3 based on jtsfiddle, but no detrending or gapfilling
4 */
|
5 tplarson 1.1
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 kehcheng 1.7 #include "fitsio.h"
|
23 tplarson 1.1
24 #define ARRLENGTH(ARR) (sizeof(ARR)/sizeof(ARR[0]))
25 #define kNOTSPECIFIED "not specified"
26
|
27 tplarson 1.5 char *module_name = "jtsslice";
|
28 tplarson 1.12 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 tplarson 1.1
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 tplarson 1.3 {ARG_STRING, "TTOTAL", NULL, "total length of time in output"},
45
|
46 tplarson 1.1 {ARG_INT, "IFIRST", "0", "", ""},
|
47 tplarson 1.3 // {ARG_INT, "FLIPM", "0", "", ""},
48
|
49 tplarson 1.1 {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 tplarson 1.3 #include "set_history.c"
|
65 tplarson 1.1
|
66 tplarson 1.2 #define DIE(code) { fprintf(stderr,"jtsslice died with error code %d\n",(code)); return 0;}
|
67 tplarson 1.1
68 /* global variables holding the values of the command line variables. */
|
69 tplarson 1.3 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 tplarson 1.1 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 tplarson 1.1 int gapsize, istart, istop, data_dim, detrend_order;
95 int npow, mshift;
96 float tsamplex, df1, c;
97 int *agaps;
|
98 tplarson 1.3 int *gaps;
|
99 tplarson 1.1 float *msum, *pow;
100 float *data, *out_data, *in_data;
101 fftwf_plan plan;
102 int num_sections, *sections;
|
103 tplarson 1.2 char tstartstr[100];
|
104 tplarson 1.1
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 tplarson 1.3 char *ttotal;
116 double nseconds;
|
117 tplarson 1.1
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 tplarson 1.6 double tstart, tstartsave, tstop, tstopsave, cadence, tstartout, tstopout;
|
138 tplarson 1.1 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 tplarson 1.2 gapfile = (char *)cmdparams_save_str (&cmdparams, "GAPFILE", &newstat);
|
148 tplarson 1.1 n_sampled_out = cmdparams_save_int (&cmdparams, "NDT", &newstat);
149 ifirst = cmdparams_save_int (&cmdparams, "IFIRST", &newstat);
|
150 tplarson 1.3 // flipm = cmdparams_save_int (&cmdparams, "FLIPM", &newstat);
|
151 tplarson 1.1 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 tplarson 1.2 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 tplarson 1.1 int seginflag = strcmp(kNOTSPECIFIED, segnamein);
167 int segoutflag = strcmp(kNOTSPECIFIED, segnameout);
|
168 tplarson 1.2 char *histlinkname = (char *)cmdparams_save_str(&cmdparams, "histlink", &newstat);
169 char *srclinkname = (char *)cmdparams_save_str(&cmdparams, "srclink", &newstat);
|
170 tplarson 1.1 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 tplarson 1.3 ttotal=(char *)cmdparams_save_str(&cmdparams, "TTOTAL", &newstat);
178 status=drms_names_parseduration(&ttotal, &nseconds, 1);
|
179 tplarson 1.9 if (status != DRMS_SUCCESS)
|
180 tplarson 1.2 {
|
181 tplarson 1.3 fprintf(stderr, "ERROR: problem parsing TTOTAL, = %s\n", ttotal);
182 return 1;
|
183 tplarson 1.2 }
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 tplarson 1.1
198 /**** Sanity check of input parameters. ****/
199
200 /* Default is to just output the timeseries. */
|
201 tplarson 1.3 if ((tsout == 0) && (fftout == 0) && (fft1out == 0) && (powout == 0) && (mavgout == 0))
|
202 tplarson 1.1 tsout=1;
203 /* Only one type of output allowed at a time */
|
204 tplarson 1.3 if ((tsout+fftout+fft1out+powout+mavgout) !=1)
|
205 tplarson 1.1 {
206 fprintf(stderr, "ERROR: only one type of output allowed at a time\n");
|
207 tplarson 1.2 return 1;
|
208 tplarson 1.1 }
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 tplarson 1.2 return 1;
|
217 tplarson 1.1 }
218 if (noff < 0 || noff >= nskip)
219 {
220 fprintf(stderr, "ERROR: noff must be >= 0 and < nskip\n");
|
221 tplarson 1.2 return 1;
|
222 tplarson 1.1 }
|
223 tplarson 1.3
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 tplarson 1.1 {
|
232 tplarson 1.3 fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", outseries, status);
|
233 tplarson 1.2 return 1;
|
234 tplarson 1.1 }
235
|
236 tplarson 1.3 DRMS_Link_t *histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
237 DRMS_Link_t *srclink = hcon_lookup_lower(&tempoutrec->links, srclinkname);
238
|
239 tplarson 1.12 // 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 tplarson 1.3 if (histlink != NULL)
241 {
|
242 tplarson 1.12 histrecnum=set_history(histlink);
|
243 tplarson 1.3 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 tplarson 1.1
254 // these must be present in the output dataseries and variable, not links or constants
|
255 tplarson 1.5 char *outchecklist[] = {"T_START", "QUALITY", "LMIN", "LMAX", "NDT"};
|
256 tplarson 1.1
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 tplarson 1.9 if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1)
|
262 tplarson 1.1 {
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 tplarson 1.2 return 1;
|
266 tplarson 1.1 }
267 }
268
|
269 tplarson 1.6 cadence=drms_getkey_float(tempoutrec, "T_STEP", &status);
270 double chunksecs = n_sampled_out*cadence;
|
271 tplarson 1.3 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 tplarson 1.6 tsample=cadence;
|
279 tplarson 1.3
280 int mflipout = drms_getkey_int(tempoutrec, "MFLIPPED", &status);
281 if (status != DRMS_SUCCESS) mflipout=0;
282
|
283 tplarson 1.1 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 tplarson 1.2 return 1;
|
293 tplarson 1.1 }
294 if (gaprecset->n == 0)
295 {
296 fprintf(stderr,"ERROR: gapfile recordset contains no records\n");
|
297 tplarson 1.2 return 1;
|
298 tplarson 1.1 }
299 if (gaprecset->n > 1)
300 {
301 fprintf(stderr,"ERROR: gapfile recordset with more than 1 record not yet supported.\n");
|
302 tplarson 1.2 return 1;
|
303 tplarson 1.1 }
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 tplarson 1.2 return 1;
|
311 tplarson 1.1 }
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 tplarson 1.2 return 1;
|
327 tplarson 1.1 }
328 }
329
|
330 tplarson 1.9 if (verbflag)
331 printf("gapfile read, gapsize = %d\n",gapsize);
|
332 tplarson 1.1
333 data_dim=gapsize;
334 if (n_sampled_out>gapsize)
335 data_dim=n_sampled_out;
336
|
337 tplarson 1.3 num_sections=1;
338 sections = malloc(2*sizeof(int));
339 sections[0] = 0;
340 sections[1] = data_dim-1;
|
341 tplarson 1.1
342 /* allocate temporary storage */
343 gaps=(int *)(malloc(gapsize*sizeof(int)));
344 data=(float *)(fftwf_malloc(2*data_dim*sizeof(float)));
345
|
346 tplarson 1.2 DRMS_RecordSet_t *inrecset = drms_open_records(drms_env, inrecquery, &status);
|
347 tplarson 1.1
|
348 tplarson 1.2 if (status != DRMS_SUCCESS || inrecset == NULL)
|
349 tplarson 1.1 {
350 fprintf(stderr,"ERROR: problem opening input recordset: status = %d\n",status);
|
351 tplarson 1.2 return 1;
|
352 tplarson 1.1 }
353
|
354 tplarson 1.2 if (inrecset->n == 0)
|
355 tplarson 1.1 {
|
356 tplarson 1.4 fprintf(stderr, "ERROR: input recordset contains no records\n");
|
357 tplarson 1.2 return 1;
|
358 tplarson 1.1 }
359
|
360 tplarson 1.2 inrec=inrecset->records[0];
|
361 tplarson 1.1 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 tplarson 1.9 if (inkeytest == NULL)
|
367 tplarson 1.1 {
368 fprintf(stderr, "ERROR: required input keyword %s is missing\n", inchecklist[itest]);
|
369 tplarson 1.2 drms_close_records(inrecset, DRMS_FREE_RECORD);
370 return 1;
|
371 tplarson 1.1 }
372 }
373
|
374 tplarson 1.6 tstartsave=drms_getkey_time(inrec, "T_START", NULL); //must be constant across all input records unless GAPFILE is implemented differently
375
|
376 tplarson 1.3 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 tplarson 1.1 // 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 tplarson 1.3 if (fftout || fft1out || powout || mavgout)
|
396 tplarson 1.1 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 tplarson 1.5 if (fft1out || powout || mavgout)
|
404 tplarson 1.1 {
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 tplarson 1.5 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 tplarson 1.1
|
423 tplarson 1.5 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 tplarson 1.1 {
|
427 tplarson 1.5 fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", outseries, status);
428 return 1;
|
429 tplarson 1.1 }
430
|
431 tplarson 1.9 int gapoffset, gapoffset0 = ifirst;
|
432 tplarson 1.8 double tstart0 = tstartsave+ifirst*tsample;
|
433 tplarson 1.6 int irec;
|
434 tplarson 1.5 for (irec=0;irec<inrecset->n;irec++)
|
435 tplarson 1.3 {
436
|
437 tplarson 1.5 inrec = inrecset->records[irec];
|
438 tplarson 1.1
|
439 tplarson 1.5 int lmin=drms_getkey_int(inrec, "LMIN", NULL);
440 int lmax=drms_getkey_int(inrec, "LMAX", NULL);
441 if (lmin != lmax)
|
442 tplarson 1.3 {
|
443 tplarson 1.5 fprintf(stderr, "ERROR: lmin != lmax not yet supported.\n");
|
444 tplarson 1.3 return 0;
445 }
|
446 tplarson 1.5 lmode=lmin;
|
447 tplarson 1.3
|
448 tplarson 1.9 if (verbflag)
449 printf("starting l=%d\n",lmode);
450
|
451 tplarson 1.6 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 tplarson 1.1
|
462 tplarson 1.6 n_in=(tstop-tstart)/cadence;
|
463 tplarson 1.5 if (n_in != gapsize)
|
464 tplarson 1.3 {
|
465 tplarson 1.5 fprintf(stderr, "ERROR: gaps seem incompatible with time-series, gapsize=%d, n_in=%d\n", gapsize, n_in);
466 return 0;
|
467 tplarson 1.3 }
|
468 tplarson 1.1
|
469 tplarson 1.5 /* 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 tplarson 1.1
|
487 tplarson 1.5 startind[1]=0;
488 endind[1]=lmode;
489
490 if (seginflag)
491 segin = drms_segment_lookup(inrec, segnamein);
|
492 tplarson 1.3 else
|
493 tplarson 1.5 segin = drms_segment_lookupnum(inrec, 0);
494 if (segin == NULL)
|
495 tplarson 1.3 {
|
496 tplarson 1.5 fprintf(stderr, "ERROR: problem reading input segment: recnum = %ld\n", inrec->recnum);
497 return 0;
|
498 tplarson 1.3 }
|
499 tplarson 1.5
|
500 tplarson 1.6 int iset;
|
501 tplarson 1.5 for (iset=0; iset < ntimechunks; iset++)
502 {
503 tstartout=tstart0 + iset * chunksecs;
504 tstopout=tstartout+chunksecs;
505 sprint_time(tstartstr, tstartout, "TAI", 0);
|
506 tplarson 1.9 gapoffset = gapoffset0 + iset*n_sampled_out;
507
508 if (verbflag>1)
509 {
510 printf(" starting tstart = %s, ",tstartstr);
|
511 tplarson 1.11 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 tplarson 1.9 }
|
520 tplarson 1.5
|
521 tplarson 1.9 // set ifirst to gapoffset for reading slice
|
522 tplarson 1.6 ifirst=gapoffset;
|
523 tplarson 1.9 startind[0]=2*(ifirst);
524 endind[0]=2*(ifirst + n_sampled_out) - 1;
|
525 tplarson 1.6 // set ifirst=0 because data is read starting at ifirst by drms_segment_readslice
526 ifirst=0;
|
527 tplarson 1.5
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 tplarson 1.6 // outrec = outrecset->records[ntimechunks*irec+iset];
545 outrec = outrecset->records[iset*inrecset->n + irec];
|
546 tplarson 1.5
|
547 tplarson 1.9 if (histlink != NULL)
|
548 tplarson 1.5 drms_setlink_static(outrec, histlinkname, histrecnum);
|
549 tplarson 1.9 if (srclink != NULL)
|
550 tplarson 1.5 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 tplarson 1.1
564 /***** Main Loop over m: Detrend, gapfill and/or compute FFT/power spectrum *******/
|
565 tplarson 1.5 for (m=0; m<=lmode; m++)
566 {
|
567 tplarson 1.1
|
568 tplarson 1.9 if (verbflag>2)
569 printf(" starting m=%d\n",m);
570
|
571 tplarson 1.5 in_data=datarr + m*2*n_sampled_out;
|
572 tplarson 1.1
|
573 tplarson 1.5 /* Extracts data copy */
574 extract_data(n_sampled_out, gaps+gapoffset, in_data, data);
|
575 tplarson 1.1
|
576 tplarson 1.5 /* 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 tplarson 1.1
|
582 tplarson 1.5 if (fftout || fft1out || powout || mavgout)
583 fftwf_execute(plan);
|
584 tplarson 1.1
|
585 tplarson 1.5 if (tsout || fftout)
586 memcpy(&out_data[2*m*n_sampled_out], &data[2*ifirst], 2*n_sampled_out*sizeof(float));
|
587 tplarson 1.1
|
588 tplarson 1.5 else if (fft1out)
|
589 tplarson 1.3 {
|
590 tplarson 1.5 /* Do positive m */
591 memcpy(&out_data[2*(lmode+m)*npow], &data[2*imin], 2*npow*sizeof(float));
592 if (m > 0)
|
593 tplarson 1.3 {
|
594 tplarson 1.5 /* 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 tplarson 1.3 }
602 }
603 else
604 {
|
605 tplarson 1.5 /* 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 tplarson 1.3 {
|
625 tplarson 1.5 /* 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 tplarson 1.3 else
|
634 tplarson 1.5 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 tplarson 1.3 }
648 }
649
|
650 tplarson 1.5 } /* 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 tplarson 1.3
|
664 tplarson 1.5 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 tplarson 1.3
|
671 tplarson 1.9 outarr->bzero=segout->bzero;
672 outarr->bscale=segout->bscale;
|
673 tplarson 1.5 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 tplarson 1.8 drms_free_array(outarr);
680 drms_free_array(inarr);
|
681 tplarson 1.5 // drms_close_record(outrec, DRMS_INSERT_RECORD);
|
682 tplarson 1.1
|
683 tplarson 1.3 }
|
684 tplarson 1.1
|
685 tplarson 1.3 }
|
686 tplarson 1.1
|
687 tplarson 1.5 drms_close_records(inrecset, DRMS_FREE_RECORD);
688 drms_close_records(outrecset, DRMS_INSERT_RECORD);
|
689 tplarson 1.2
|
690 tplarson 1.3 if (fftout || fft1out || powout || mavgout)
|
691 tplarson 1.1 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 tplarson 1.3 printf("module %s successful completion\n", cmdparams.argv[0]);
|
702 tplarson 1.1 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 tplarson 1.1 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 tplarson 1.1
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 tplarson 1.2 // 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 tplarson 1.1 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 tplarson 1.1 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 tplarson 1.1 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 tplarson 1.1 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 tplarson 1.1 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 tplarson 1.2 // 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 tplarson 1.1 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 tplarson 1.1
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 tplarson 1.1 {
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 tplarson 1.1 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 tplarson 1.1 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
|