ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/globalhs/apps/jtsfiddle.c
Revision: 1.15
Committed: Tue Jul 2 20:33:16 2013 UTC (10 years, 2 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.14: +13 -4 lines
Log Message:
add VERSION parameter, correct bug to now properly reinitialize array msum

File Contents

# Content
1 /* this JSOC module is a port of an SOI module written by Rasmus Larsen.
2 * ported by Tim Larson.
3 * tim doubts this works correctly with nskip or navg
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 = "jtsfiddle";
28 char *cvsinfo_jtsfiddle = "cvsinfo: $Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jtsfiddle.c,v 1.14 2013/04/28 08:05:21 tplarson Exp $";
29
30 /* Command line arguments: */
31 ModuleArgs_t module_args[] =
32 {
33 {ARG_STRING, "in", "", "input data records"},
34 {ARG_STRING, "tsout", kNOTSPECIFIED, "output dataseries for timeseries"},
35 {ARG_STRING, "powout", kNOTSPECIFIED, "output dataseries for power spectra"},
36 {ARG_STRING, "fftout", kNOTSPECIFIED, "output dataseries for fft's"},
37 {ARG_STRING, "fft1out", kNOTSPECIFIED, "output dataseries for fft's reordered"},
38 {ARG_STRING, "arpowout", kNOTSPECIFIED, "output dataseries for AR power"},
39 {ARG_STRING, "mavgout", kNOTSPECIFIED, "output dataseries for m-averaged power spectra"},
40 // {ARG_STRING, "out", "", "output data series"},
41 {ARG_STRING, "segin" , kNOTSPECIFIED, "name of input segment if not using segment 0"},
42 {ARG_STRING, "segout", kNOTSPECIFIED, "name of output segment if not using segment 0"},
43 {ARG_STRING, "histlink", "HISTORY", "name of link to ancillary dataseries for processing metadata"},
44 {ARG_STRING, "srclink", "SRCDATA", "name of link to source data"},
45 {ARG_INT, "PERM", "1", "set to 0 for transient records, nonzero for permanent records"},
46 {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},
47 {ARG_STRING, "TAG", kNOTSPECIFIED, "this parameter sets a keyword of the same name to the same value, usually used as an additional primekey"},
48 {ARG_STRING, "VERSION", kNOTSPECIFIED, "this parameter sets a keyword of the same name to the same value, useful for selecting obsolete records"},
49
50 {ARG_STRING, "LOGFILE", "stdout", ""},
51 {ARG_STRING, "GAPFILE", "", "record or file containing window function"},
52 {ARG_STRING, "SECTIONFILE", kNOTSPECIFIED, "record or file specifying continuous sections of data"},
53
54 {ARG_INT, "NDT", "-1", "", ""},
55 // {ARG_FLOAT, "TSAMPLE", "60", "", ""},
56 {ARG_INT, "IFILL", "1", "", ""},
57 {ARG_INT, "IFIRST", "0", "", ""},
58 // {ARG_INT, "FLIPM", "0", "", ""},
59 {ARG_INT, "MAX_AR_ORDER", "360", "", ""},
60 {ARG_INT, "FU_FIT_EDGES", "1", "", ""},
61 {ARG_INT, "FU_ITER", "3", "", ""},
62 {ARG_INT, "FU_MIN_PERCENT", "90", "", ""},
63 {ARG_FLOAT, "CDETREND", "50.0", "", ""},
64 {ARG_INT, "DETREND_LENGTH", "1600", "", ""},
65 {ARG_INT, "DETREND_SKIP", "1440", "", ""},
66 {ARG_INT, "DETREND_FIRST", "0", "", ""},
67 /*
68 {ARG_INT, "TSOUT", "0", "", ""},
69 {ARG_INT, "FFTOUT", "0", "", ""},
70 {ARG_INT, "FFT1OUT", "0", "", ""},
71 {ARG_INT, "POWOUT", "0", "", ""},
72 {ARG_INT, "ARPOWOUT", "0", "", ""},
73 {ARG_INT, "MAVGOUT", "0", "", ""},
74 */
75 {ARG_INT, "NAVG", "0", "", ""},
76 {ARG_INT, "NSKIP", "0", "", ""},
77 {ARG_INT, "NOFF", "0", "", ""},
78 {ARG_INT, "IMIN", "0", "", ""},
79 {ARG_INT, "IMAX", "-1", "", ""},
80 {ARG_END},
81 };
82
83 #include "saveparm.c"
84 #include "timing.c"
85 #include "set_history.c"
86
87 extern void cdetrend_discontig( int n, _Complex float *data, int *isgood,
88 int degree, int length, int skip,
89 int m, int *sect_last, int detrend_first);
90
91 int cfahlman_ulrych(int n, _Complex float *data, int *isgood,
92 int minpercentage, int maxorder, int iterations,
93 int padends, int *order, _Complex float *ar_coeff);
94
95 //char *getdetrendversion(void);
96 //char *getgapfillversion(void);
97
98 /* global variables holding the values of the command line variables. */
99 static char *logfile, *gapfile, *sectionfile;
100 static int lmode, n_sampled_out, ifill, flipm;
101 static int ar_order, max_ar_order, fu_iter, fu_fit_edges;
102 static int fu_min_percent;
103 static int detrend_length, detrend_skip, detrend_first;
104 static float tsample, detrend_const;
105 static int ifirst, tsout,fftout, fft1out, powout, arpowout, mavgout;
106 static int navg, nskip, noff, imin, imax;
107
108
109 /* Prototypes for local functions. */
110 static double splitting(int l, int m);
111
112 /* Prototypes for external functions */
113 extern void cffti_(int *, float *);
114 extern void cfftb_(int *, float *, float *);
115 static int extract_gaps(int n_in, int *gaps_in, int *n_out, int *gaps_out,
116 float tsample_in, float *tsample_out,
117 int *num_sections, int *sections);
118 static void extract_data(int n_in, int *gaps, float *data_in, float *data_out);
119 static int read_section_file(char *filename, int *num_section, int **section);
120
121 /************ Here begins the main module **************/
122 int DoIt(void)
123 {
124 int i;
125 int m, n_in, n_sampled_in;
126 TIME epoch, step, start, stop;
127 int gapsize, istart, istop, data_dim, detrend_order;
128 int npow, mshift;
129 float tsamplex, df1, c;
130 int *agaps;
131 int *gaps, *gaps2;
132 float *msum, *pow;
133 float *data, *out_data, *in_data;
134 fftwf_plan plan;
135 int num_sections, *sections;
136 float *ar_coeff=NULL;
137 float *datarr, *datptr, *outptr;
138 float *datahold;
139 char tstartstr[100];
140 int lmin, lmax;
141
142 int fstatus = 0;
143 fitsfile *fitsptr;
144 long fdims[1];
145 long fpixel[]={1};
146 int *anynul=0;
147
148 int instart[2], inend[2];
149 int tslength[2], tsstart[2], tsend[2], tstotal[2];
150 int fft1length[2], fft1start[2], fft1end[2], fft1total[2];
151 int powlength[2], powstart[2], powend[2], powtotal[2];
152 int status=DRMS_SUCCESS;
153 int newstat=0;
154
155 DRMS_Segment_t *segin = NULL;
156 DRMS_Segment_t *segout = NULL;
157 DRMS_Array_t *inarr = NULL;
158 DRMS_Array_t *outarr = NULL;
159 DRMS_Record_t *inrec = NULL;
160 DRMS_Record_t *outrec = NULL;
161 DRMS_Type_t usetype = DRMS_TYPE_FLOAT;
162 DRMS_RecLifetime_t lifetime;
163 long long histrecnum = -1;
164 DRMS_Segment_t *gapseg = NULL;
165 DRMS_Array_t *gaparr = NULL;
166
167 HIterator_t outKey_list;
168 DRMS_Keyword_t *outKey;
169 TIME tnow, UNIX_epoch = -220924792.000; /* 1970.01.01_00:00:00_UTC */
170
171 int errbufstat=setvbuf(stderr, NULL, _IONBF, BUFSIZ);
172 int outbufstat=setvbuf(stdout, NULL, _IONBF, BUFSIZ);
173
174 double tstart, tstartsave, tstop, tstopsave, cadence, tstartout, tstopout;
175 double wt0, wt1, wt2, wt3, wt;
176 double ut0, ut1, ut2, ut3, ut;
177 double st0, st1, st2, st3, st;
178 double ct0, ct1, ct2, ct3, ct;
179
180 wt0=getwalltime();
181 ct0=getcputime(&ut0, &st0);
182
183 /* Read input parameters. */
184 logfile = (char *)cmdparams_save_str (&cmdparams, "LOGFILE", &newstat);
185 gapfile = (char *)cmdparams_save_str (&cmdparams, "GAPFILE", &newstat);
186 sectionfile = (char *)cmdparams_save_str (&cmdparams, "SECTIONFILE", &newstat);
187 n_sampled_out = cmdparams_save_int (&cmdparams, "NDT", &newstat);
188 // tsample = cmdparams_save_float (&cmdparams, "TSAMPLE", &newstat);
189 ifill = cmdparams_save_int (&cmdparams, "IFILL", &newstat);
190 max_ar_order= cmdparams_save_int (&cmdparams, "MAX_AR_ORDER", &newstat);
191 fu_fit_edges= cmdparams_save_int (&cmdparams, "FU_FIT_EDGES", &newstat);
192 fu_iter = cmdparams_save_int (&cmdparams, "FU_ITER", &newstat);
193 fu_min_percent = cmdparams_save_int (&cmdparams, "FU_MIN_PERCENT", &newstat);
194 ifirst = cmdparams_save_int (&cmdparams, "IFIRST", &newstat);
195 // flipm = cmdparams_save_int (&cmdparams, "FLIPM", &newstat);
196 detrend_const = cmdparams_save_float(&cmdparams, "CDETREND", &newstat);
197 detrend_length = cmdparams_save_int (&cmdparams, "DETREND_LENGTH", &newstat);
198 detrend_skip = cmdparams_save_int (&cmdparams, "DETREND_SKIP", &newstat);
199 detrend_first = cmdparams_save_int (&cmdparams, "DETREND_FIRST", &newstat);
200 /*
201 tsout = cmdparams_save_int (&cmdparams, "TSOUT", &newstat);
202 fftout = cmdparams_save_int (&cmdparams, "FFTOUT", &newstat);
203 fft1out = cmdparams_save_int (&cmdparams, "FFT1OUT", &newstat);
204 powout = cmdparams_save_int (&cmdparams, "POWOUT", &newstat);
205 arpowout = cmdparams_save_int (&cmdparams, "ARPOWOUT", &newstat);
206 mavgout = cmdparams_save_int (&cmdparams, "MAVGOUT", &newstat);
207 */
208 navg = cmdparams_save_int (&cmdparams, "NAVG", &newstat);
209 nskip = cmdparams_save_int (&cmdparams, "NSKIP", &newstat);
210 noff = cmdparams_save_int (&cmdparams, "NOFF", &newstat);
211 imin = cmdparams_save_int (&cmdparams, "IMIN", &newstat);
212 imax = cmdparams_save_int (&cmdparams, "IMAX", &newstat);
213
214 char *inrecquery = (char *)cmdparams_save_str(&cmdparams, "in", &newstat);
215 // char *outseries = (char *)cmdparams_save_str(&cmdparams, "out", &newstat);
216 char *segnamein = (char *)cmdparams_save_str(&cmdparams, "segin", &newstat);
217 char *segnameout = (char *)cmdparams_save_str(&cmdparams, "segout", &newstat);
218 int seginflag = strcmp(kNOTSPECIFIED, segnamein);
219 int segoutflag = strcmp(kNOTSPECIFIED, segnameout);
220 char *histlinkname = (char *)cmdparams_save_str(&cmdparams, "histlink", &newstat);
221 char *srclinkname = (char *)cmdparams_save_str(&cmdparams, "srclink", &newstat);
222 int verbflag = cmdparams_save_int(&cmdparams, "VERB", &newstat);
223 int permflag = cmdparams_save_int(&cmdparams, "PERM", &newstat);
224 if (permflag)
225 lifetime = DRMS_PERMANENT;
226 else
227 lifetime = DRMS_TRANSIENT;
228
229 char *tag = (char *)cmdparams_save_str(&cmdparams, "TAG", &newstat);
230 int tagflag = strcmp(kNOTSPECIFIED, tag);
231 char *version = (char *)cmdparams_save_str(&cmdparams, "VERSION", &newstat);
232 int verflag = strcmp(kNOTSPECIFIED, version);
233
234 char *tsseries = (char *)cmdparams_save_str(&cmdparams, "tsout", &newstat);
235 tsout = strcmp(kNOTSPECIFIED, tsseries);
236 char *powseries = (char *)cmdparams_save_str(&cmdparams, "powout", &newstat);
237 powout = strcmp(kNOTSPECIFIED, powseries);
238 char *fftseries = (char *)cmdparams_save_str(&cmdparams, "fftout", &newstat);
239 fftout = strcmp(kNOTSPECIFIED, fftseries);
240 char *fft1series = (char *)cmdparams_save_str(&cmdparams, "fft1out", &newstat);
241 fft1out = strcmp(kNOTSPECIFIED, fft1series);
242 char *arpowseries = (char *)cmdparams_save_str(&cmdparams, "arpowout", &newstat);
243 arpowout = strcmp(kNOTSPECIFIED, arpowseries);
244 char *mavgseries = (char *)cmdparams_save_str(&cmdparams, "mavgout", &newstat);
245 mavgout = strcmp(kNOTSPECIFIED, mavgseries);
246
247 char *serieslist[6];
248 enum seriesindex {TSOUT, FFTOUT, FFT1OUT, POWOUT, ARPOWOUT, MAVGOUT};
249 int flagarr[6] = {tsout, fftout, fft1out, powout, arpowout, mavgout};
250 int mfliparr[6] = {0, 0, 0, 0, 0, 0};
251 int msignarr[6] = {0, 0, 0, 0, 0, 0};
252 serieslist[TSOUT]=tsseries;
253 serieslist[FFTOUT]=fftseries;
254 serieslist[FFT1OUT]=fft1series;
255 serieslist[POWOUT]=powseries;
256 serieslist[ARPOWOUT]=arpowseries;
257 serieslist[MAVGOUT]=mavgseries;
258 long long histrecnumarr[6]={-1, -1, -1, -1, -1, -1};
259 DRMS_RecordSet_t *outrecsetarr[6]={NULL, NULL, NULL, NULL, NULL, NULL};
260 DRMS_Record_t *outrecarr[6]={NULL, NULL, NULL, NULL, NULL, NULL};
261 DRMS_Segment_t *segoutarr[6]={NULL, NULL, NULL, NULL, NULL, NULL};
262
263 /**** Sanity check of input parameters. ****/
264
265 if ((tsout == 0) && (fftout == 0) && (fft1out == 0) && (powout == 0) && (mavgout == 0) && (arpowout == 0))
266 {
267 fprintf(stderr, "ERROR: must specify an output dataseries\n");
268 return 1;
269 }
270
271 if (navg <= 0)
272 navg=1;
273 if (nskip <= 0)
274 nskip=1;
275 if ((navg != 1) && (nskip != 1))
276 {
277 fprintf(stderr, "ERROR: one of navg and nskip must equal 1\n");
278 return 1;
279 }
280 if (noff < 0 || noff >= nskip)
281 {
282 fprintf(stderr, "ERROR: noff must be >= 0 and < nskip\n");
283 return 1;
284 }
285 if (arpowout && !ifill)
286 {
287 fprintf(stderr, "ERROR: must have nonzero ifill with arpowout\n");
288 return 1;
289 }
290 if (fu_min_percent <= 0 || fu_min_percent > 100)
291 {
292 fprintf(stderr, "ERROR: FU_MIN_PERCENT must be > 0 and <= 100\n");
293 return 1;
294 }
295
296 if (newstat)
297 {
298 fprintf(stderr, "ERROR: problem with input arguments, status = %d, diagnosis follows\n", newstat);
299 cpsave_decode_error(newstat);
300 return 1;
301 }
302 else if (savestrlen != strlen(savestr))
303 {
304 fprintf(stderr, "ERROR: problem with savestr, savestrlen = %d, strlen(savestr) = %d\n", savestrlen, (int)strlen(savestr));
305 return 1;
306 }
307
308
309 // these must be present in the output dataseries and variable, not links or constants
310 // the loop is only necessary if the output series don't all link to the same history series, which they usually will, but just in case...
311 char *outchecklist[] = {"T_START", "QUALITY", "LMIN", "LMAX", "NDT"};
312 int is, ishold, itest, mflip;
313 char *holdseries="";
314 /*
315 char *cvsinfo;
316 cvsinfo = (char *)malloc(1024);
317 strcpy(cvsinfo,"$Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/apps/jtsfiddle.c,v 1.14 2013/04/28 08:05:21 tplarson Exp $");
318 strcat(cvsinfo,"\n");
319 strcat(cvsinfo,getdetrendversion());
320 strcat(cvsinfo,"\n");
321 strcat(cvsinfo,getgapfillversion());
322 */
323 for (is=0;is<6;is++)
324 {
325
326 if (!flagarr[is])
327 continue;
328
329 DRMS_Record_t *tempoutrec = drms_create_record(drms_env,
330 serieslist[is],
331 DRMS_TRANSIENT,
332 &status);
333
334 if (status != DRMS_SUCCESS)
335 {
336 fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", serieslist[is], status);
337 return 1;
338 }
339
340 DRMS_Link_t *histlink = hcon_lookup_lower(&tempoutrec->links, histlinkname);
341
342
343 // set up ancillary dataseries for processing metadata
344 if (histlink != NULL)
345 {
346 if (strcmp(holdseries, histlink->info->target_series))
347 {
348 ishold=is;
349 holdseries=strdup(histlink->info->target_series);
350 histrecnumarr[is]=set_history(histlink);
351 if (histrecnumarr[is] < 0)
352 {
353 fprintf(stderr, "ERROR: problem creating record in history dataseries for output dataseries %s\n", serieslist[is]);
354 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
355 return 1;
356 }
357 }
358 else
359 {
360 histrecnumarr[is]=histrecnumarr[ishold];
361 }
362 }
363 else
364 {
365 fprintf(stderr,"WARNING: could not find history link in output dataseries %s\n", serieslist[is]);
366 }
367
368 for (itest=0; itest < ARRLENGTH(outchecklist); itest++)
369 {
370 DRMS_Keyword_t *outkeytest = hcon_lookup_lower(&tempoutrec->keywords, outchecklist[itest]);
371 if (outkeytest == NULL || outkeytest->info->islink || outkeytest->info->recscope == 1)
372 {
373 fprintf(stderr, "ERROR: output keyword %s in series %s is either missing, constant, or a link\n", outchecklist[itest], serieslist[is]);
374 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
375 return 1;
376 }
377 }
378
379 mflip = drms_getkey_int(tempoutrec, "MFLIPPED", &status);
380 if (status == DRMS_SUCCESS)
381 mfliparr[is]=mflip;
382
383 drms_close_record(tempoutrec, DRMS_FREE_RECORD);
384 }
385
386 // for efficiency require that tsseries and fftseries have the same value of MFLIPPED. this restriction may be lifted as noted below.
387 if ((tsout && fftout) && (mfliparr[TSOUT] != mfliparr[FFTOUT]))
388 {
389 fprintf(stderr, "ERROR: series %s and %s must have the same value of MFLIPPED\n", tsseries, fftseries);
390 return 1;
391 }
392
393 if (fits_open_file(&fitsptr, gapfile, READONLY, &fstatus))
394 {
395 DRMS_RecordSet_t *gaprecset = drms_open_records(drms_env, gapfile, &status);
396 if (status != DRMS_SUCCESS || gaprecset == NULL)
397 {
398 fprintf(stderr,"ERROR: problem reading gaps: file status = %d, DRMS status = %d\n",fstatus,status);
399 return 1;
400 }
401 if (gaprecset->n == 0)
402 {
403 fprintf(stderr,"ERROR: gapfile recordset contains no records\n");
404 return 1;
405 }
406 if (gaprecset->n > 1)
407 {
408 fprintf(stderr,"ERROR: gapfile recordset with more than 1 record not yet supported.\n");
409 return 1;
410 }
411 gapseg = drms_segment_lookupnum(gaprecset->records[0], 0);
412 if (gapseg != NULL)
413 gaparr = drms_segment_read(gapseg, DRMS_TYPE_INT, &status);
414 if (status != DRMS_SUCCESS || gaparr == NULL || gapseg == NULL)
415 {
416 fprintf(stderr, "problem reading gaps segment: status = %d\n", status);
417 return 1;
418 }
419 agaps=(int *)(gaparr->data);
420 gapsize=gaparr->axis[0];
421 }
422 else
423 {
424 fits_get_img_size(fitsptr, 1, fdims, &fstatus);
425 gapsize=fdims[0];
426 agaps=(int *)(malloc(gapsize*sizeof(int)));
427 fits_read_pix(fitsptr, TINT, fpixel, gapsize, NULL, agaps, anynul, &fstatus);
428 fits_close_file(fitsptr, &fstatus);
429 if (fstatus)
430 {
431 fits_report_error(stderr, fstatus);
432 return 1;
433 }
434 }
435
436 if (verbflag)
437 printf("gapfile read, gapsize = %d\n",gapsize);
438
439 data_dim=gapsize;
440 if (n_sampled_out>gapsize)
441 data_dim=n_sampled_out;
442
443 /* allocate temporary storage */
444 gaps=(int *)(malloc(gapsize*sizeof(int)));
445 gaps2=(int *)(malloc(gapsize*sizeof(int)));
446 data=(float *)(fftwf_malloc(2*data_dim*sizeof(float)));
447 ar_coeff = (float *)malloc((max_ar_order+1)*2*sizeof(float));
448 // now done below
449 // if (fft1out || powout || mavgout || arpowout)
450 // pow=(float *)(malloc(n_sampled_out*sizeof(float)));
451
452 /* Read location of jumps. */
453 if (!strcmp(sectionfile,kNOTSPECIFIED))
454 {
455 /* No sections file specified. Assume that the whole
456 time series in one section. */
457 num_sections=1;
458 sections = malloc(2*sizeof(int));
459 sections[0] = 0;
460 sections[1] = data_dim-1;
461 }
462 else
463 {
464 int secstat;
465 if (secstat=read_section_file(sectionfile, &num_sections, &sections))
466 {
467 DRMS_RecordSet_t *secrecset = drms_open_records(drms_env, sectionfile, &status);
468 if (status != DRMS_SUCCESS || secrecset == NULL)
469 {
470 fprintf(stderr,"ERROR: problem reading sections: file status = %d, DRMS status = %d\n",secstat,status);
471 return 1;
472 }
473 if (secrecset->n == 0)
474 {
475 fprintf(stderr,"ERROR: sectionfile recordset contains no records\n");
476 return 1;
477 }
478 if (secrecset->n > 1)
479 {
480 fprintf(stderr,"ERROR: sectionfile recordset with more than 1 record not yet supported.\n");
481 return 1;
482 }
483 num_sections=drms_getkey_int(secrecset->records[0], "NSECS", NULL);
484 if (num_sections < 1)
485 {
486 fprintf(stderr,"ERROR: Invalid NSECS keywords\n");
487 return 1;
488 }
489 sections = (int *)malloc(2*(num_sections)*sizeof(int));
490 char *sectkey=drms_getkey_string(secrecset->records[0], "SECS", NULL);
491 sscanf(strtok(sectkey," \n"),"%d",&(sections[0]));
492 sscanf(strtok(NULL," \n"),"%d",&(sections[1]));
493 int i;
494 for (i=2 ;i<2*(num_sections); i+=2)
495 {
496 sscanf(strtok(NULL," \n"), "%d", &(sections)[i]);
497 sscanf(strtok(NULL," \n"), "%d", &(sections)[i+1]);
498
499 if (sections[i]>sections[i+1] || (i>0 && sections[i]<=sections[i-1]))
500 {
501 fprintf(stderr,"ERROR: Invalid SECS keyword, sections overlap.\n");
502 return 1;
503 }
504 }
505 free(sectkey);
506 }
507 }
508
509 if (verbflag)
510 printf("num_sections = %d\n",num_sections);
511
512 DRMS_RecordSet_t *inrecset = drms_open_records(drms_env, inrecquery, &status);
513
514 if (status != DRMS_SUCCESS || inrecset == NULL)
515 {
516 fprintf(stderr,"ERROR: problem opening input recordset: status = %d\n",status);
517 return 1;
518 }
519 if (inrecset->n == 0)
520 {
521 fprintf(stderr, "ERROR: input recordset contains no records\n");
522 return 1;
523 }
524
525 inrec=inrecset->records[0];
526 char *inchecklist[] = {"T_START", "T_STOP", "QUALITY", "LMIN", "LMAX", "T_STEP"};
527 for (itest=0; itest < ARRLENGTH(inchecklist); itest++)
528 {
529 DRMS_Keyword_t *inkeytest = hcon_lookup_lower(&inrec->keywords, inchecklist[itest]);
530 if (inkeytest == NULL)
531 {
532 fprintf(stderr, "ERROR: required input keyword %s is missing\n", inchecklist[itest]);
533 drms_close_records(inrecset, DRMS_FREE_RECORD);
534 return 1;
535 }
536 }
537
538 cadence=drms_getkey_float(inrec, "T_STEP", NULL); //assume constant across all input records
539 tsample=cadence;
540 tstartsave=drms_getkey_time(inrec, "T_START", NULL); //must be constant across all input records unless GAPFILE is implemented differently
541
542 int mflipin=drms_getkey_int(inrec, "MFLIPPED", &status);
543 if (status != DRMS_SUCCESS) mflipin=0;
544
545 // already required mfliparr[TSOUT] == mfliparr[FFTOUT] above
546 if (tsout && mfliparr[TSOUT] != mflipin)
547 flipm=1;
548 else if (fftout && mfliparr[FFTOUT] != mflipin)
549 flipm=1;
550 else
551 flipm=0;
552
553 for (is=2;is<5;is++)
554 {
555 if (!flagarr[is])
556 continue;
557 if (mfliparr[is] != (mflipin || flipm))
558 msignarr[is]=-1;
559 else
560 msignarr[is]=1;
561 }
562
563 if (mflipin)
564 msignarr[MAVGOUT]=1;
565 else
566 msignarr[MAVGOUT]=-1;
567
568 // changed n_in to gapsize in following call
569 if (extract_gaps(gapsize, agaps, &n_sampled_in, gaps, tsample, &tsamplex, &num_sections, sections))
570 {
571 fprintf(stderr, "ERROR: problem in extract_gaps\n");
572 return 1;
573 }
574
575 /* Adjust detrend parameters according to the number of
576 available points. */
577 if (n_sampled_in<detrend_length)
578 {
579 detrend_length = n_sampled_in;
580 detrend_skip = detrend_length;
581 }
582
583 int idtf;
584 if (detrend_first > 0)
585 {
586 for (idtf=0;idtf<detrend_first;idtf++)
587 gaps[idtf]=0;
588 }
589
590
591 if (n_sampled_out == -1)
592 n_sampled_out = n_sampled_in;
593 df1 = tsamplex*n_sampled_out;
594
595 if (fftout || fft1out || powout || arpowout || mavgout)
596 plan = fftwf_plan_dft_1d(n_sampled_out, (fftwf_complex *)data,
597 (fftwf_complex *)data, FFTW_BACKWARD, FFTW_MEASURE);
598
599 /* Set sum to zero before starting */
600 if (mavgout)
601 msum = (float *)malloc((n_sampled_out/2)*sizeof(float));
602
603 if (fft1out || powout || mavgout || arpowout)
604 {
605 /* Set first and last output index if not set as a parameter. */
606 if (imax < imin)
607 {
608 imin=0;
609 imax=n_sampled_out/2-1;
610 }
611 npow=imax-imin+1;
612 pow=(float *)(malloc(n_sampled_out*sizeof(float)));
613 datahold=(float *)malloc(2*npow*sizeof(float));
614 }
615
616 // needed to implement mfliparr[TSOUT] != mfliparr[FFTOUT]
617 // float *datatemp=(float *)malloc(2*n_sampled_out*sizeof(float));
618 float *tmpptr=data;
619
620 if (tsout || fftout)
621 {
622 tslength[0]=tstotal[0]=2*n_sampled_out;
623 tslength[1]=1;
624 tsstart[0]=0;
625 tsend[0]=2*n_sampled_out-1;
626 }
627 if (fft1out)
628 {
629 fft1length[0]=fft1total[0]=2*npow;
630 fft1length[1]=1;
631 fft1start[0]=0;
632 fft1end[0]=2*npow-1;
633 }
634 if (powout || arpowout || mavgout)
635 {
636 powlength[0]=powtotal[0]=npow;
637 powlength[1]=1;
638 powstart[0]=0;
639 powend[0]=npow-1;
640 }
641 instart[0]=0;
642 inend[0]=2*gapsize - 1;
643
644 status=drms_stage_records(inrecset, 1, 0);
645 if (status != DRMS_SUCCESS)
646 {
647 fprintf(stderr, "ERROR: drms_stage_records returned status = %d\n", status);
648 return 1;
649 }
650
651 for (is=0; is<6; is++)
652 {
653 if (!flagarr[is])
654 continue;
655
656 outrecsetarr[is] = drms_create_records(drms_env, inrecset->n, serieslist[is], DRMS_PERMANENT, &status);
657
658 if (status != DRMS_SUCCESS || outrecsetarr[is] == NULL)
659 {
660 fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", serieslist[is], status);
661 return 1;
662 }
663 }
664
665 int irec;
666 for (irec=0;irec<inrecset->n;irec++)
667 {
668
669 inrec = inrecset->records[irec];
670
671 lmin=drms_getkey_int(inrec, "LMIN", NULL);
672 lmax=drms_getkey_int(inrec, "LMAX", NULL);
673 if (lmin != lmax)
674 {
675 fprintf(stderr, "ERROR: lmin != lmax not yet supported.\n");
676 return 0;
677 }
678 lmode=lmin;
679
680 if (verbflag > 1)
681 {
682 printf("starting l=%d\n", lmode);
683 }
684
685 tstart=drms_getkey_time(inrec, "T_START", NULL);
686 tstop =drms_getkey_time(inrec, "T_STOP", NULL);
687 cadence=drms_getkey_float(inrec, "T_STEP", NULL);
688 if (tstart != tstartsave)
689 {
690 // to lift this restriction must be able to specify multiple gap files/records as input
691 sprint_time(tstartstr, tstart, "TAI", 0);
692 fprintf(stderr, "ERROR: all input records must have same T_START, record %d has %s\n", irec, tstartstr);
693 return 0;
694 }
695
696 n_in=(tstop-tstart)/cadence;
697 if (n_in != gapsize)
698 {
699 fprintf(stderr, "ERROR: gaps seem incompatible with timeseries, gapsize=%d, n_in=%d\n", gapsize, n_in);
700 return 0;
701 }
702
703 tstartout=tstart+ifirst*tsample;
704 tstopout=tstartout+df1;
705 sprint_time(tstartstr, tstartout, "TAI", 0);
706
707 if (seginflag)
708 segin = drms_segment_lookup(inrec, segnamein);
709 else
710 segin = drms_segment_lookupnum(inrec, 0);
711 if (segin == NULL)
712 {
713 fprintf(stderr, "ERROR: problem looking up input segment: recnum = %lld\n", inrec->recnum);
714 return 0;
715 }
716
717 for (is=0; is<6; is++)
718 {
719 if (!flagarr[is])
720 continue;
721 /*
722 outrecarr[is] = drms_create_record(drms_env, serieslist[is], DRMS_PERMANENT, &status);
723 if (status != DRMS_SUCCESS)
724 {
725 fprintf(stderr,"ERROR: couldn't open a record in output dataseries %s, status = %d\n", serieslist[is], status);
726 return 0;
727 }
728 */
729 outrec=outrecsetarr[is]->records[irec];
730 if (histrecnumarr[is] > 0)
731 drms_setlink_static(outrec, histlinkname, histrecnumarr[is]);
732 drms_setlink_static(outrec, srclinkname, inrec->recnum);
733
734 if (segoutflag)
735 segoutarr[is] = drms_segment_lookup(outrec, segnameout);
736 else
737 segoutarr[is] = drms_segment_lookupnum(outrec, 0);
738 if (segoutarr[is] == NULL)
739 {
740 fprintf(stderr, "ERROR: problem looking up outputput segment in series %s\n", serieslist[is]);
741 return 0;
742 }
743
744 // the following is not needed if at least one of the first N-1 dimensions are 0 in the jsd,
745 // or if the first N-1 dimensions in the jsd are always the dimensions desired.
746 // it *is* needed any time one must override the jsd defaults
747 /*
748 switch(is)
749 {
750 case TSOUT:
751 case FFTOUT:
752 segoutarr[is]->axis[0]=2*n_sampled_out;
753 segoutarr[is]->axis[1]=lmode+1;
754 break;
755 case FFT1OUT:
756 segoutarr[is]->axis[0]=2*npow;
757 segoutarr[is]->axis[1]=2*lmode+1;
758 break;
759 case POWOUT:
760 case ARPOWOUT:
761 segoutarr[is]->axis[0]=npow;
762 segoutarr[is]->axis[1]=2*lmode+1;
763 break;
764 case MAVGOUT:
765 segoutarr[is]->axis[0]=npow;
766 segoutarr[is]->axis[1]=1;
767 break;
768 default:
769 ;
770 }
771 */
772 switch(is)
773 {
774 case TSOUT:
775 case FFTOUT:
776 tstotal[1]=lmode+1;
777 break;
778 case FFT1OUT:
779 fft1total[1]=2*lmode+1;
780 break;
781 case POWOUT:
782 case ARPOWOUT:
783 powtotal[1]=2*lmode+1;
784 break;
785 case MAVGOUT:
786 default:
787 ;
788 }
789
790 }
791
792 if (mavgout)
793 for (i=0;i<n_sampled_out/2;i++)
794 msum[i] = 0.0;
795
796 /***** Main Loop over m: Detrend, gapfill and/or compute FFT/power spectrum *******/
797 for (m=0; m<=lmode; m++)
798 {
799
800 if (verbflag > 2)
801 {
802 printf("starting m=%d\n", m);
803 }
804
805 instart[1]=m;
806 inend[1]=m;
807 inarr = drms_segment_readslice(segin, usetype, instart, inend, &status);
808 if (status != DRMS_SUCCESS || inarr == NULL )
809 {
810 fprintf(stderr, "ERROR: problem reading input segment: status = %d, recnum = %lld\n", status, inrec->recnum);
811 return 0;
812 }
813 in_data=(float *)(inarr->data);
814
815 /* Extracts data copy */
816 extract_data(n_sampled_in, gaps, in_data, data);
817
818 /* Detrend entire time series if required */
819 if (detrend_const != 0)
820 {
821 detrend_order = floor(detrend_length/detrend_const)+2;
822 cdetrend_discontig(n_sampled_in, (_Complex float *)data, gaps,
823 detrend_order, detrend_length, detrend_skip,
824 num_sections, sections, detrend_first);
825 }
826
827 /* Fill gaps in entire time series if required */
828 memcpy(gaps2, gaps, n_sampled_in*sizeof(int));
829 if (ifill != 0 && max_ar_order > 0)
830 {
831 cfahlman_ulrych(n_sampled_in, (_Complex float *)data, gaps2,
832 fu_min_percent, max_ar_order, fu_iter, fu_fit_edges,
833 &ar_order, (_Complex float *)ar_coeff);
834 }
835
836 drms_free_array(inarr);
837
838 memmove(data, &data[2*ifirst], 2*(n_sampled_in-ifirst)*sizeof(float));
839 if ((ifirst+n_sampled_out) >= n_sampled_in)
840 memset(&data[2*(n_sampled_in-ifirst)], 0, 2*(n_sampled_out+ifirst-n_sampled_in)*sizeof(float));
841
842 if (tsout)
843 {
844 // code to flip m on this output separately. in the present code this has already been accomplished by setting flipm.
845 /*
846 if (mfliparr[TSOUT] != mflipin)
847 {
848 for (i = 0; i < n_sampled_out; i++)
849 {
850 datatemp[2*i]=data[2*i];
851 datatemp[2*i+1]=-data[2*i+1];
852 }
853 tmpptr=datatemp;
854 }
855 else
856 tmpptr=data;
857 */
858 tsstart[1]=m;
859 tsend[1]=m;
860 outarr = drms_array_create(usetype, 2, tslength, tmpptr, &status);
861 outarr->bzero=segoutarr[TSOUT]->bzero;
862 outarr->bscale=segoutarr[TSOUT]->bscale;
863 status=drms_segment_writeslice_ext(segoutarr[TSOUT], outarr, tsstart, tsend, tstotal, 0);
864 free(outarr);
865 if (status != DRMS_SUCCESS)
866 {
867 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[TSOUT], status, m, tstartstr, lmode, histrecnumarr[TSOUT]);
868 return 0;
869 }
870 }
871
872 if (fftout || fft1out || powout || mavgout)
873 fftwf_execute(plan);
874
875 if (fftout)
876 {
877 // code to flip m on this output separately. in the present code this has already been accomplished by setting flipm.
878 /*
879 if (mfliparr[FFTOUT] != mflipin)
880 {
881 datatemp[0]=data[0];
882 datatemp[1]=-data[1];
883 for (i = 1; i < n_sampled_out; i++)
884 {
885 datatemp[2*i]=data[2*(n_sampled_out-i)];
886 datatemp[2*i+1]=-data[2*(n_sampled_out-i)+1];
887 }
888 tmpptr=datatemp;
889 }
890 else
891 tmpptr=data;
892 */
893 tsstart[1]=m;
894 tsend[1]=m;
895 outarr = drms_array_create(usetype, 2, tslength, tmpptr, &status);
896 outarr->bzero=segoutarr[FFTOUT]->bzero;
897 outarr->bscale=segoutarr[FFTOUT]->bscale;
898 status=drms_segment_writeslice_ext(segoutarr[FFTOUT], outarr, tsstart, tsend, tstotal, 0);
899 free(outarr);
900 if (status != DRMS_SUCCESS)
901 {
902 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[FFTOUT], status, m, tstartstr, lmode, histrecnumarr[FFTOUT]);
903 return 0;
904 }
905 }
906
907 if (fft1out)
908 {
909
910 fft1start[1]=lmode+m*msignarr[FFT1OUT];
911 fft1end[1]=lmode+m*msignarr[FFT1OUT];
912 outarr = drms_array_create(usetype, 2, fft1length, data+2*imin, &status);
913 outarr->bzero=segoutarr[FFT1OUT]->bzero;
914 outarr->bscale=segoutarr[FFT1OUT]->bscale;
915 status=drms_segment_writeslice_ext(segoutarr[FFT1OUT], outarr, fft1start, fft1end, fft1total, 0);
916 free(outarr);
917 if (status != DRMS_SUCCESS)
918 {
919 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[FFT1OUT], status, m, tstartstr, lmode, histrecnumarr[FFT1OUT]);
920 return 0;
921 }
922
923 if (m > 0)
924 {
925 /* Do negative m */
926 for (i=0; i<npow; i++)
927 {
928 /* Conjugate for negative m */
929 datahold[2*i] = data[2*(n_sampled_out-imin-i)];
930 datahold[2*i+1] = -data[2*(n_sampled_out-imin-i)+1];
931 }
932 fft1start[1]=lmode-m*msignarr[FFT1OUT];
933 fft1end[1]=lmode-m*msignarr[FFT1OUT];
934 outarr = drms_array_create(usetype, 2, fft1length, datahold, &status);
935 outarr->bzero=segoutarr[FFT1OUT]->bzero;
936 outarr->bscale=segoutarr[FFT1OUT]->bscale;
937 status=drms_segment_writeslice_ext(segoutarr[FFT1OUT], outarr, fft1start, fft1end, fft1total, 0);
938 free(outarr);
939 if (status != DRMS_SUCCESS)
940 {
941 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[FFT1OUT], status, m, tstartstr, lmode, histrecnumarr[FFT1OUT]);
942 return 0;
943 }
944 }
945 }
946
947 if (powout || mavgout)
948 for (i = 0; i < n_sampled_out; i++)
949 pow[i] = data[2*i]*data[2*i] + data[2*i+1]*data[2*i+1];
950
951 if (powout)
952 {
953 powstart[1]=lmode+m*msignarr[POWOUT];
954 powend[1]=lmode+m*msignarr[POWOUT];
955 outarr = drms_array_create(usetype, 2, powlength, pow+imin, &status);
956 outarr->bzero=segoutarr[POWOUT]->bzero;
957 outarr->bscale=segoutarr[POWOUT]->bscale;
958 status=drms_segment_writeslice_ext(segoutarr[POWOUT], outarr, powstart, powend, powtotal, 0);
959 free(outarr);
960 if (status != DRMS_SUCCESS)
961 {
962 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[POWOUT], status, m, tstartstr, lmode, histrecnumarr[POWOUT]);
963 return 0;
964 }
965
966 if (m > 0)
967 {
968 /* Do negative m */
969 if (imin)
970 datahold[0] = pow[n_sampled_out-imin];
971 else
972 datahold[0] = pow[0];
973 for (i=1; i<npow;i++)
974 datahold[i] = pow[n_sampled_out-imin-i];
975
976 powstart[1]=lmode-m*msignarr[POWOUT];
977 powend[1]=lmode-m*msignarr[POWOUT];
978 outarr = drms_array_create(usetype, 2, powlength, datahold, &status);
979 outarr->bzero=segoutarr[POWOUT]->bzero;
980 outarr->bscale=segoutarr[POWOUT]->bscale;
981 status=drms_segment_writeslice_ext(segoutarr[POWOUT], outarr, powstart, powend, powtotal, 0);
982 free(outarr);
983 if (status != DRMS_SUCCESS)
984 {
985 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[POWOUT], status, m, tstartstr, lmode, histrecnumarr[POWOUT]);
986 return 0;
987 }
988 }
989 }
990
991 if (mavgout)
992 {
993 mshift = floor(df1*splitting(lmode,m*msignarr[MAVGOUT])+0.5f);
994 if (mshift >= 0)
995 for (i=0; i<n_sampled_out/2-mshift; i++)
996 msum[i] += pow[mshift+i];
997 else
998 for (i=0; i<n_sampled_out/2+mshift; i++)
999 msum[i-mshift] += pow[i];
1000 if (m > 0)
1001 {
1002 /* Do negative m */
1003 mshift = floor(df1*splitting(lmode,-m*msignarr[MAVGOUT])+0.5f);
1004 if (mshift >=0)
1005 for (i=1; i<n_sampled_out/2-mshift;i++)
1006 msum[i] += pow[n_sampled_out-mshift-i];
1007 else
1008 for (i=1; i<n_sampled_out/2+mshift; i++)
1009 msum[i-mshift] += pow[n_sampled_out-i];
1010 }
1011 }
1012
1013 if (arpowout)
1014 {
1015 memmove(data, ar_coeff, 2*(ar_order+1)*sizeof(float));
1016 memset(&data[2*(ar_order+1)],0,2*(n_sampled_out-ar_order-1)*sizeof(float));
1017 fftwf_execute(plan);
1018 for (i = 0; i < n_sampled_out; i++)
1019 pow[i] = 1.0/(data[2*i]*data[2*i] + data[2*i+1]*data[2*i+1]);
1020
1021 powstart[1]=lmode+m*msignarr[ARPOWOUT];
1022 powend[1]=lmode+m*msignarr[ARPOWOUT];
1023 outarr = drms_array_create(usetype, 2, powlength, pow+imin, &status);
1024 outarr->bzero=segoutarr[ARPOWOUT]->bzero;
1025 outarr->bscale=segoutarr[ARPOWOUT]->bscale;
1026 status=drms_segment_writeslice_ext(segoutarr[ARPOWOUT], outarr, powstart, powend, powtotal, 0);
1027 free(outarr);
1028 if (status != DRMS_SUCCESS)
1029 {
1030 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[ARPOWOUT], status, m, tstartstr, lmode, histrecnumarr[ARPOWOUT]);
1031 return 0;
1032 }
1033
1034 if (m > 0)
1035 {
1036 /* Do negative m */
1037 if (imin)
1038 datahold[0] = pow[n_sampled_out-imin];
1039 else
1040 datahold[0] = pow[0];
1041 for (i=1; i<npow;i++)
1042 datahold[i] = pow[n_sampled_out-imin-i];
1043
1044 powstart[1]=lmode-m*msignarr[ARPOWOUT];
1045 powend[1]=lmode-m*msignarr[ARPOWOUT];
1046 outarr = drms_array_create(usetype, 2, powlength, datahold, &status);
1047 outarr->bzero=segoutarr[ARPOWOUT]->bzero;
1048 outarr->bscale=segoutarr[ARPOWOUT]->bscale;
1049 status=drms_segment_writeslice_ext(segoutarr[ARPOWOUT], outarr, powstart, powend, powtotal, 0);
1050 free(outarr);
1051 if (status != DRMS_SUCCESS)
1052 {
1053 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, m = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[ARPOWOUT], status, m, tstartstr, lmode, histrecnumarr[ARPOWOUT]);
1054 return 0;
1055 }
1056 }
1057 }
1058
1059 } //end of loop over m
1060
1061 if (mavgout)
1062 {
1063 c=1.0f/(2*lmode+1);
1064 for (i=0; i<npow; i++)
1065 datahold[i] = msum[imin+i] * c;
1066 outarr = drms_array_create(usetype, 2, powlength, datahold, &status);
1067 outarr->bzero=segoutarr[MAVGOUT]->bzero;
1068 outarr->bscale=segoutarr[MAVGOUT]->bscale;
1069 status=drms_segment_write(segoutarr[MAVGOUT], outarr, 0);
1070 free(outarr);
1071 if (status != DRMS_SUCCESS)
1072 {
1073 fprintf(stderr, "ERROR: problem writing output segment in series %s: status = %d, T_START = %s, LMODE = %d, histrecnum = %lld\n", serieslist[MAVGOUT], status, tstartstr, lmode, histrecnum);
1074 return 0;
1075 }
1076 }
1077
1078 for (is=0;is<6;is++)
1079 {
1080 if (!flagarr[is])
1081 continue;
1082
1083 outrec=outrecsetarr[is]->records[irec];
1084 drms_copykeys(outrec, inrec, 0, kDRMS_KeyClass_Explicit);
1085 drms_setkey_int(outrec, "QUALITY", 0);
1086 drms_setkey_time(outrec, "T_START", tstartout);
1087 drms_setkey_time(outrec, "T_STOP", tstopout);
1088 drms_setkey_time(outrec, "T_OBS", (tstartout + tstopout)/2);
1089 drms_setkey_float(outrec, "T_STEP", tsamplex);
1090 drms_setkey_int(outrec, "NDT", n_sampled_out);
1091 if (tagflag)
1092 drms_setkey_string(outrec, "TAG", tag);
1093 if (verflag)
1094 drms_setkey_string(outrec, "VERSION", version);
1095
1096 tnow = (double)time(NULL);
1097 tnow += UNIX_epoch;
1098 drms_setkey_time(outrec, "DATE", tnow);
1099
1100 // drms_close_record(outrec, DRMS_INSERT_RECORD);
1101
1102 }
1103
1104 }
1105
1106 drms_close_records(inrecset, DRMS_FREE_RECORD);
1107 for (is=0;is<6;is++)
1108 {
1109 if (!flagarr[is])
1110 continue;
1111 drms_close_records(outrecsetarr[is], DRMS_INSERT_RECORD);
1112 }
1113
1114 if(ar_coeff != NULL)
1115 free(ar_coeff);
1116
1117 if (fftout || fft1out || powout || arpowout || mavgout)
1118 fftwf_destroy_plan(plan);
1119
1120 wt=getwalltime();
1121 ct=getcputime(&ut, &st);
1122 if (verbflag)
1123 {
1124 printf("total time spent: %.2f ms wall time, %.2f ms cpu time\n",
1125 wt-wt0, ct-ct0);
1126 }
1127
1128 printf("module %s successful completion\n", cmdparams.argv[0]);
1129 return 0;
1130 }
1131
1132
1133 static double splitting(int l, int m)
1134 {
1135 double a1x[] = {406.0,407.0,408.0,410.5,412.0,411.5,409.0,406.0,406.0};
1136 double a3x[] = {10.0,10.0,15.0,19.5,21.0,21.3,21.3,21.3,21.8};
1137 double a5x[] = {0.0,0.0,0.0,-1.5,-2.5,-3.5,-4.0,-4.0,-4.5};
1138 /* f0 is the frequency used for generating the above a-coeff */
1139 double f0 = 1500.0;
1140 /* fcol is the frequency for which to optimize the collaps */
1141 double fcol = 800.0;
1142
1143 double ll,x,x3,x5,a1,a2,a3,a5,frac,lx;
1144 int ix;
1145
1146 if (l == 0)
1147 ll = 1;
1148 else
1149 ll = sqrt(l*(l+1.));
1150 x = m/ll;
1151 x3 = x*x*x;
1152 x5 = x3*x*x;
1153 lx = 5*log10(l*f0/fcol)-4;
1154 ix = floor(lx);
1155 frac = lx-ix;
1156 if (lx <= 0) {
1157 ix = 0;
1158 frac = 0.0;
1159 }
1160 if (lx >=8) {
1161 ix = 7;
1162 frac = 1.0;
1163 }
1164 a1 = (1.0-frac)*a1x[ix]+frac*a1x[ix+1];
1165 a2 = 0.0;
1166 a3 = (1.0-frac)*a3x[ix]+frac*a3x[ix+1];
1167 a5 = (1.0-frac)*a5x[ix]+frac*a5x[ix+1];
1168
1169 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;
1170 }
1171
1172
1173
1174 /* Extract the data samples actually used by skipping or averaging
1175 data. Replace missing data that are not marked as gaps with zero. */
1176 void extract_data(int n_in, int *gaps, float *data_in, float *data_out)
1177 {
1178 int i,j, nmiss = 0;
1179 // the following check will be skipped in production executables since they will be built with NDEBUG defined.
1180 // it doesn't matter because the check is already done in DoIt().
1181 assert(nskip==1 || navg==1);
1182 if ((navg == 1) && (nskip == 1))
1183 {
1184 for (i=0; i<n_in; i++)
1185 {
1186 if (gaps[i]==0 )
1187 {
1188 data_out[2*i] = 0.0f;
1189 data_out[2*i+1] = 0.0f;
1190 }
1191 else
1192 {
1193 if (isnan(data_in[2*i]) || isnan(data_in[2*i+1]))
1194 {
1195 data_out[2*i] = 0.0f;
1196 data_out[2*i+1] = 0.0f;
1197 gaps[i] = 0;
1198 nmiss++;
1199 }
1200 else
1201 {
1202 data_out[2*i] = data_in[2*i];
1203 data_out[2*i+1] = flipm ? -data_in[2*i+1] : data_in[2*i+1];
1204 }
1205 }
1206 }
1207 }
1208 else if (nskip != 1)
1209 {
1210 for (i = 0; i<n_in; i++)
1211 {
1212 if (gaps[i]==0 )
1213 {
1214 data_out[2*i] = 0.0f;
1215 data_out[2*i+1] = 0.0f;
1216 }
1217 else
1218 {
1219 int ix = nskip*i+noff;
1220 if (isnan(data_in[2*ix]) || isnan(data_in[2*ix+1]))
1221 {
1222 data_out[2*i] = 0.0f;
1223 data_out[2*i+1] = 0.0f;
1224 gaps[i] = 0;
1225 nmiss++;
1226 }
1227 else
1228 {
1229 data_out[2*i] = data_in[2*ix];
1230 data_out[2*i+1] = flipm ? -data_in[2*ix+1] : data_in[2*ix+1];
1231 }
1232 }
1233 }
1234 }
1235 else if (navg != 1)
1236 {
1237 for (i = 0; i<n_in; i++)
1238 {
1239 if (gaps[i]==0 )
1240 {
1241 data_out[2*i] = 0.0f;
1242 data_out[2*i+1] = 0.0f;
1243 }
1244 else
1245 {
1246 float avgr = 0.0f;
1247 float avgi = 0.0f;
1248 for (j=0; j<navg; j++)
1249 {
1250 int ix = navg*i+j;
1251 if (isnan(data_in[2*ix]) || isnan(data_in[2*ix+1]))
1252 {
1253 data_out[2*i] = 0.0f;
1254 data_out[2*i+1] = 0.0f;
1255 gaps[i] = 0;
1256 nmiss++;
1257 break;
1258 }
1259 else
1260 {
1261 avgr += data_in[2*ix];
1262 avgi += data_in[2*ix+1];
1263 }
1264 }
1265 if (j == navg)
1266 {
1267 data_out[2*i] = avgr/navg;
1268 data_out[2*i+1] = avgi/navg;
1269 }
1270 }
1271 }
1272 }
1273 }
1274
1275 /* Extract the windows function for the samples actually used after
1276 subsampling or averaging. Modify the list of continous sections
1277 accordingly, and make sure we do not average across section boundaries. */
1278 static int extract_gaps(int n_in, int *gaps_in, int *n_out, int *gaps_out,
1279 float tsample_in, float *tsample_out,
1280 int *num_sections, int *sections)
1281 {
1282 // the following check will be skipped in production executables since they will be built with NDEBUG defined.
1283 // it doesn't matter because the check is already done in DoIt().
1284 assert(nskip==1 || navg==1);
1285 int i,j,sect, start,stop;
1286
1287
1288 if (*num_sections<1)
1289 {
1290 fprintf(stderr,"Apparantly no sections of data available.");
1291 return 1;
1292 }
1293 /* Mask out data that in between sections if this hasn't already been
1294 done in gapfile. */
1295 for (i=0; i<sections[0] && i<n_in; i++)
1296 gaps_in[i] = 0;
1297 for (sect=1; sect<(*num_sections); sect++)
1298 {
1299 for (i=sections[2*sect-1]+1; i<sections[2*sect] && i<n_in; i++)
1300 gaps_in[i] = 0;
1301 }
1302 for (i=sections[2*(*num_sections-1)+1]+1; i<n_in; i++)
1303 gaps_in[i] = 0;
1304
1305
1306 if ((navg == 1) && (nskip == 1))
1307 {
1308 *n_out = n_in;
1309 *tsample_out = tsample_in;
1310 for (i=0; i<*n_out; i++)
1311 gaps_out[i] = gaps_in[i];
1312 }
1313 else if (nskip != 1)
1314 {
1315 *n_out = n_in/nskip;
1316 *tsample_out = nskip*tsample_in;
1317 for (i=0; i<*n_out; i++)
1318 {
1319 gaps_out[i] = gaps_in[nskip*i+noff];
1320 }
1321 for (i=0; i<2*(*num_sections); i+=2)
1322 {
1323 start = (int)ceilf(((float)(sections[i]-noff))/nskip);
1324 stop = (int)floorf(((float)(sections[i+1]-noff))/nskip);
1325 if (start <= stop)
1326 {
1327 sections[i] = start;
1328 sections[i+1] = stop;
1329 }
1330 else
1331 {
1332 /* This section was skipped entirely. */
1333 for (j=i; j< 2*(*num_sections-1); j+=2)
1334 {
1335 sections[j] = sections[j+2];
1336 sections[j+1] = sections[j+3];
1337 }
1338 *num_sections -= 1;
1339 }
1340 }
1341 }
1342 else if (navg != 1)
1343 {
1344 sect = 0;
1345 *n_out = n_in/navg;
1346 *tsample_out = tsample*navg;
1347 for (i=0; i<*n_out; i++)
1348 {
1349 int igx = 1;
1350 while (sect < *num_sections &&
1351 !(navg*i >= sections[2*sect] && navg*i >= sections[2*sect+1]))
1352 sect++;
1353
1354 /* Don't allow averaging of data from different sections. */
1355 if (navg*i >= sections[2*sect] && (navg*i+navg-1)<=sections[2*sect+1])
1356 {
1357 for (j=0; j<navg; j++)
1358 igx *= gaps_in[navg*i+j];
1359 gaps_out[i] = igx;
1360 }
1361 else
1362 gaps_out[i] = 0;
1363 }
1364 for (i=0; i<2*(*num_sections); i+=2)
1365 {
1366 start = (int)ceilf(((float)sections[i])/navg);
1367 stop = (int)floorf(((float)sections[i+1])/navg);
1368 if (start <= stop)
1369 {
1370 sections[i] = start;
1371 sections[i+1] = stop;
1372 }
1373 else
1374 {
1375 /* This section was skipped entirely. */
1376 for (j=i; j< 2*(*num_sections-1); j+=2)
1377 {
1378 sections[j] = sections[j+2];
1379 sections[j+1] = sections[j+3];
1380 }
1381 *num_sections -= 1;
1382 }
1383 }
1384 }
1385 return 0;
1386 }
1387
1388
1389 /*
1390 Read a list of sections [start_sample:end_sample] that should
1391 contain continuous data. When detrending, jumps are allow to
1392 occur between sections. The sections file should be a text file
1393 of the form:
1394
1395 num
1396 start_1 end_1
1397 start_2 end_2
1398 ...
1399 start_num end_num
1400 */
1401 static int read_section_file(char *filename, int *num_sections, int **sections)
1402 {
1403 FILE *fh;
1404 int i;
1405
1406 fh = fopen(filename,"r");
1407 if (fh!=NULL)
1408 {
1409 fscanf(fh,"%d",num_sections);
1410 *sections = (int *)malloc(2*(*num_sections)*sizeof(int));
1411
1412 for (i=0 ;i<2*(*num_sections); i+=2)
1413 {
1414 fscanf(fh,"%d",&(*sections)[i]);
1415 fscanf(fh,"%d",&(*sections)[i+1]);
1416
1417 if ((*sections)[i]>(*sections)[i+1] ||
1418 (i>0 && (*sections)[i]<=(*sections)[i-1]))
1419 {
1420 fprintf(stderr,"Invalid sections file, sections overlap.\n");
1421 return 2;
1422 }
1423 }
1424 fclose(fh);
1425 return 0;
1426 }
1427 else
1428 return 1;
1429 }
1430