ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/farside/apps/drms_rebin.c
Revision: 1.3
Committed: Tue Nov 15 23:06:41 2011 UTC (11 years, 10 months ago) by rick
Content type: text/plain
Branch: MAIN
CVS Tags: Ver_6-0, Ver_6-1, Ver_6-2, Ver_6-3, Ver_6-4, Ver_9-1, Ver_9-3, Ver_9-2, Ver_8-8, Ver_8-2, Ver_8-3, Ver_8-0, Ver_8-1, Ver_8-6, Ver_8-7, Ver_8-4, Ver_8-5, Ver_7-1, Ver_7-0, Ver_9-4, Ver_8-10, Ver_8-11, Ver_8-12, Ver_9-0
Changes since 1.2: +440 -102 lines
Log Message:
modified for JSOC release 6.0

File Contents

# Content
1 /*
2 * drms_rebin.c ~rick/src/drms
3 *
4 * Rebin the values of selected segments of selected records to a desired
5 * grid (and location)
6 *
7 * Responsible: Rick Bogart RBogart@spd.aas.org
8 *
9 * Usage:
10 * drms_rebin [-nv] in= ...
11 *
12 * Arguments: (type default description)
13 * in DataSet - Input dataset
14 * out DataSeries in Output dataseries
15 * seg String "Not Specified Output data segment if required
16 * copy String "+" List of keys to propagate from
17 * input to output records, if possible
18 *
19 * Flags
20 * -c collapse output rank if possible
21 * -n do not save results (diagnostic only)
22 * -o remove radial component of orbital velocity from signal
23 * -O remove radial component of vector orbital velocity from signal
24 * (unimplemented)
25 * -v run verbose
26 *
27 * Notes:
28 * The output segment structure needs to be checked for consistency with
29 * the input segment and bin and extract paremeters as follows for the
30 * different protocol cases:
31 * in variable/constant out variable/constant once at beginning
32 * in variable/constant out vardim never
33 * in vardim out variable/constant always
34 * in vardim out vardim never
35 *
36 * Bugs:
37 * Status of keyword setting not checked
38 * The collapse option is a quick hack and has not been well tested
39 * Recalculation of target arrays for vardim input has not been tested
40 * Only one input segment and one output segment can be processed; there
41 * is currently no way of dealing with the situation when there are
42 * multiple possible candidate segments and the input segments must
43 * be specified in the input dataset specfiers
44 * The option for removal of full orbital velocity is only a stub, and
45 * unimplemented; the option for removal of radial velocity is superfluous,
46 * as it is the same as specifying offset= -OBS_VR
47 * Has not been tested with arrays of rank > 3
48 * There may be some inconsistency about use of long long's for indexing in
49 * large arrays
50 *
51 * Revision history is at end of file.
52 */
53 #include <jsoc_main.h>
54 #include <fftw3.h>
55 #include "keystuff.c"
56
57 char *module_name = "drms_rebin";
58 char *version_id = "1.0";
59 char *module_desc = "rectangular region binning";
60
61 ModuleArgs_t module_args[] = {
62 {ARG_STRING, "in", "", "input data set"},
63 {ARG_STRING, "out", "", "output data series"},
64 {ARG_STRING, "seg", "Not Specified", "output data segment"},
65 {ARG_INTS, "bin", "{1}", "array of per-axis bin widths"},
66 {ARG_INTS, "start", "{0}", "array of input axis starting pixels"},
67 {ARG_INTS, "stop", "{-1}", "array of input axis ending pixels"},
68 {ARG_FLOATS, "wmin", "{NaN}",
69 "minimum wavelengths per axis for low-pass filtering"},
70 {ARG_STRING, "copy", "+",
71 "comma separated list of keys to propagate forward"},
72 {ARG_STRING, "scale", "Not Specified", "scaling value (number or keyword)"},
73 {ARG_STRING, "offset", "Not Specified", "offset value (number or keyword)"},
74 {ARG_INT, "qmask", "0x80000000", "quality bit mask for image rejection"},
75 {ARG_STRING, "qual_key", "Quality", "keyname for 32-bit input image quality field"},
76 {ARG_FLAG, "c", "", "collapse rank of output for unit axes"},
77 {ARG_FLAG, "n", "", "do not save output (for testing)"},
78 {ARG_FLAG, "o", "",
79 "remove orbital velocity from signal (radial component only)"},
80 {ARG_FLAG, "O", "", "remove orbital velocity from signal"},
81 {ARG_FLAG, "v", "", "run in verbose mode"},
82 {ARG_END}
83 };
84 /* list of keywords to propagate by default (if possible)
85 from input to output */
86 char *propagate[] = {"T_REC", "T_OBS", "DATE__OBS", "TELESCOP", "INSTRUME"};
87
88 /* the following belong in external utility files */
89 /* parse a string of the form [*|/][+|-]keyname */
90 char *parse_as_arith_key (const char *str, int *mult, int *add) {
91 char *parsed = strdup (str);
92 *mult = *add = 1;
93 if (parsed[0] == '*') parsed++;
94 else if (parsed[0] == '/') {
95 *mult = -1;
96 parsed++;
97 }
98 if (parsed[0] == '+') parsed++;
99 else if (parsed[0] == '-') {
100 *add = -1;
101 parsed++;
102 }
103 return parsed;
104 }
105
106 int set_stats_keys (DRMS_Record_t *rec, DRMS_Array_t *v, long long ntot) {
107 double *vavg = (double *)v->data;
108
109 double vmin, vmax, norm, norm2, scale, sig, var;
110 double sumv1, sum2, sum3, sum4;
111 long long n;
112 int sumv0;
113 int valmin = ntot, valmax = 0;
114 int kstat = 0;
115
116 vmin = HUGE;
117 vmax = -HUGE;
118 sumv1 = 0.0;
119 sumv0 = 0;
120 for (n = 0; n < ntot; n++) {
121 if (vavg[n] < vmin) vmin = vavg[n];
122 if (vavg[n] > vmax) vmax = vavg[n];
123 if (isfinite (vavg[n])) {
124 sumv0++;
125 sumv1 += vavg[n];
126 }
127 }
128
129 kstat += check_and_set_key_double (rec, "DataMin", vmin);
130 kstat += check_and_set_key_double (rec, "DataMax", vmax);
131
132 if (sumv0) {
133 scale = 1.0 / sumv0;
134 sumv1 *= scale;
135 sum2 = sum3 = sum4 = 0.0;
136 kstat += check_and_set_key_double (rec, "DataMean", sumv1);
137 for (n = 0; n < ntot; n++) {
138 if (isfinite (vavg[n])) {
139 norm = vavg[n] - sumv1;
140 norm2 = norm * norm;
141 sum2 += norm2;
142 sum3 += norm * norm2;
143 sum4 += norm2 * norm2;
144 }
145 }
146 kstat += check_and_set_key_double (rec, "DataRMS", sqrt (sum2 / sumv0));
147 if (sumv0 > 1) {
148 var = sum2 / (sumv0 - 1);
149 sig = sqrt (var);
150 kstat += check_and_set_key_double (rec, "DataSkew",
151 scale * sum3 / (var * sig));
152 kstat += check_and_set_key_double (rec, "DataKurt",
153 scale * sum4 / (var * var) - 3.0);
154 }
155 }
156
157 return kstat;
158 }
159
160 static int data_filter (DRMS_Array_t *data) {
161 double *wdata = (double *)data->data;
162 double norm;
163 float *xdata = (float *)data->data;
164 long long n, ntot;
165 int dp_calc;
166 int *axes = data->axis;
167 int rank = data->naxis;
168 static char *valid = NULL;
169 /* Declarations for FFTW library calls */
170 fftw_plan fplan, iplan;
171 fftwf_plan rfplan, riplan;
172 static fftw_complex *wform = NULL;
173 static fftwf_complex *xform = NULL;
174
175 if (data->type == DRMS_TYPE_DOUBLE) dp_calc = 1;
176 else if (data->type == DRMS_TYPE_FLOAT) dp_calc = 0;
177 else {
178 fprintf (stderr, "Error: filtering of data of type %s not supported\n",
179 drms_type_names[data->type]);
180 return 1;
181 }
182
183 ntot = 1;
184 for (n = 0; n < rank; n++) ntot *= axes[n];
185 norm = 1.0 / ntot;
186 valid = (char *)realloc (valid, ntot * sizeof (char));
187
188 if (dp_calc) {
189 wform = (fftw_complex *)realloc (wform, (ntot + 1) * sizeof (fftw_complex));
190 fplan = fftw_plan_dft_r2c (rank, axes, wdata, wform, FFTW_ESTIMATE);
191 iplan = fftw_plan_dft_c2r (rank, axes, wform, wdata, FFTW_ESTIMATE);
192 } else {
193 xform = (fftwf_complex *)realloc (xform, (ntot + 1) * sizeof (fftwf_complex));
194 rfplan = fftwf_plan_dft_r2c (rank, axes, xdata, xform, FFTW_ESTIMATE);
195 riplan = fftwf_plan_dft_c2r (rank, axes, xform, xdata, FFTW_ESTIMATE);
196 }
197 /* forward transform */
198 if (dp_calc) {
199 for (n = 0; n < ntot; n++)
200 if (isnan (wdata[n])) valid[n] = wdata[n] = 0;
201 else valid[n] = 1;
202 fftw_execute (fplan);
203 } else {
204 for (n = 0; n < ntot; n++)
205 if (isnan (xdata[n])) valid[n] = xdata[n] = 0;
206 else valid[n] = 1;
207 fftwf_execute (rfplan);
208 }
209 double rx2, rxfac, ry2, ryfac, rfilt;
210 int col, hcols, cols = axes[0];
211 int row, hrows, rows = axes[1];
212 hrows = (rows + 1) / 2;
213 hcols = cols / 2; /* possible bug if cols odd */
214 rxfac = 1.0 / cols;
215 ryfac = 1.0 / rows;
216 if (dp_calc) {
217 for (row = 0, n = 0; row < hrows; row++) {
218 ry2 = row * ryfac;
219 ry2 *= ry2;
220 for (col = 0; col < cols; col++, n+=2) {
221 rx2 = col * rxfac;
222 rx2 *= rx2;
223 rfilt = sqrt (rx2 + ry2);
224 if (rfilt > 0.1) wform[n] = wform[n+1] = 0.0;
225 }
226 }
227 } else {
228 for (row = 0, n = 0; row < hrows; row++) {
229 ry2 = row * ryfac;
230 ry2 *= ry2;
231 for (col = 0; col < cols; col++, n+=2) {
232 rx2 = col * rxfac;
233 rx2 *= rx2;
234 rfilt = sqrt (rx2 + ry2);
235 if (rfilt > 0.1) xform[n] = xform[n+1] = 0.0;
236 }
237 }
238 }
239 /* inverse transform */
240 if (dp_calc) {
241 fftw_execute (iplan);
242 for (n = 0; n < ntot; n++) {
243 if (!valid[n]) wdata[n] = NAN;
244 else wdata[n] *= norm;
245 }
246 } else {
247 fftwf_execute (riplan);
248 for (n = 0; n < ntot; n++) {
249 if (!valid[n]) xdata[n] = NAN;
250 else xdata[n] *= norm;
251 }
252 }
253 return 0;
254 }
255
256 static int check_input_series (char *inds, int *segnum) {
257 /*
258 * Check input data series structure for the existence of a unique segment of
259 * appropriate protocol for array segment reads, if the segment is not
260 * named as part of the dataset specification; otherwise check that the
261 * named segment has the appropriate protocol
262 */
263 DRMS_RecordSet_t *drs = NULL;
264 DRMS_Record_t *irec;
265 DRMS_Segment_t *iseg;
266 HIterator_t *lastseg = NULL;
267 int rec_ct;
268 int status = 0, valid_ct = 0;
269
270 *segnum = 0;
271 drs = drms_open_records (drms_env, inds, &status);
272 if (!drs) {
273 fprintf (stderr, "Error: unable to open record set %s\n", inds);
274 return 1;
275 }
276 irec = drs->records[0];
277 /* must use iterator in case segment name is included
278 as part of record set specifier */
279 while (iseg = drms_record_nextseg (irec, &lastseg, 1)) {
280 if (iseg->info->protocol == DRMS_PROTOCOL_INVALID ||
281 iseg->info->protocol == DRMS_GENERIC) continue;
282 if (!valid_ct) *segnum = iseg->info->segnum;
283 valid_ct++;
284 }
285 if (valid_ct > 1) {
286 fprintf (stderr, "Error: input data set %s\n", inds);
287 fprintf (stderr,
288 " contains multiple segments of appropriate protocol;\n");
289 fprintf (stderr, " in segment must be specified\n");
290 status = 1;
291 }
292 if (valid_ct < 1) {
293 fprintf (stderr, "Error: input data set %s\n", inds);
294 fprintf (stderr, " contains no segments of appropriate protocol\n");
295 status = 1;
296 }
297 rec_ct = drs->n;
298 if (rec_ct < 1) {
299 fprintf (stderr, "No records in selected set %s\n", inds);
300 status = 1;
301 }
302 drms_close_records (drs, DRMS_FREE_RECORD);
303 return status;
304 }
305
306 static int check_output_series (char *series, char *segname, int *segnum,
307 int *check) {
308 /*
309 * Check output data series structure for the existence of segments of
310 * appropriate protocol for array segment writes, if the segment is not
311 * explicitly named; otherwise check that the named segment has the
312 * appropriate protocol. If multiple acceptable output segments exist,
313 * set check argument.
314 */
315 DRMS_Record_t *orec;
316 DRMS_Segment_t *oseg;
317 int oseg_ct, seg_n;
318 int status;
319
320 orec = drms_create_record (drms_env, series, DRMS_TRANSIENT, &status);
321 if (!orec) {
322 fprintf (stderr, "Error: unable to create records in series %s\n", series);
323 fprintf (stderr, " drms_create_record() returned status %d\n",
324 status);
325 return 1;
326 }
327
328 *check = 0;
329 if (strcmp (segname, "Not Specified")) {
330 /* make sure the named output segment is writeable from an array */
331 oseg = drms_segment_lookup (orec, segname);
332 if (!oseg) {
333 fprintf (stderr, "Error: no such data segment %s in series %s\n", segname,
334 series);
335 drms_free_record (orec);
336 return 1;
337 }
338 if (oseg->info->protocol == DRMS_PROTOCOL_INVALID ||
339 oseg->info->protocol == DRMS_GENERIC) {
340 fprintf (stderr, "Error: output data segment %s\n", segname);
341 fprintf (stderr, " is not of appropriate protocol\n");
342 drms_free_record (orec);
343 return 1;
344 }
345 *segnum = oseg->info->segnum;
346 } else {
347 int valid_ct = 0;
348 oseg_ct = drms_record_numsegments (orec);
349 /* find the (only) output segment writeable from an array */
350 for (seg_n = 0; seg_n < oseg_ct; seg_n++) {
351 oseg = drms_segment_lookupnum (orec, seg_n);
352 if (oseg->info->protocol == DRMS_PROTOCOL_INVALID ||
353 oseg->info->protocol == DRMS_GENERIC) continue;
354 if (!valid_ct) *segnum = seg_n;
355 valid_ct++;
356 }
357 if (valid_ct > 1) *check = 1;
358 if (valid_ct < 1) {
359 fprintf (stderr, "Error: output data series %s\n", series);
360 fprintf (stderr, " contains no segments of appropriate protocol\n");
361 drms_free_record (orec);
362 return 1;
363 }
364 }
365 drms_free_record (orec);
366 return 0;
367 }
368
369 static int check_output_segment (DRMS_Segment_t *seg, int rank, int *axes) {
370 return 0;
371 }
372
373 static int find_output_segment (char *series, int rank, int *axes) {
374 /*
375 * Find the unique (or first) output data segment matching the requirements
376 * for appropriate protocol for array segment writes
377 */
378 DRMS_Record_t *orec;
379 DRMS_Segment_t *oseg;
380 int oseg_ct, seg_n, n;
381 int status;
382 int valid_ct = 0, segnum = -1;
383
384 orec = drms_create_record (drms_env, series, DRMS_TRANSIENT, &status);
385 oseg_ct = drms_record_numsegments (orec);
386 for (seg_n = 0; seg_n < oseg_ct; seg_n++) {
387 oseg = drms_segment_lookupnum (orec, seg_n);
388 if (oseg->info->protocol == DRMS_PROTOCOL_INVALID ||
389 oseg->info->protocol == DRMS_GENERIC) continue;
390 if (oseg->info->naxis != rank) continue;
391 if (oseg->info->scope != DRMS_VARDIM) {
392 for (n = 0; n < rank; n++) {
393 /* the output segment has fixed axis sizes, so check them */
394 if (axes[n] != oseg->axis[n]) continue;
395 }
396 }
397 if (!valid_ct) segnum = seg_n;
398 valid_ct++;
399 }
400
401 drms_free_record (orec);
402 if (valid_ct > 1) {
403 oseg = drms_segment_lookupnum (orec, segnum);
404 fprintf (stderr, "Warning: output data series %s\n", series);
405 fprintf (stderr,
406 " contains multiple segments of appropriate protocol and dimensions;\n");
407 fprintf (stderr,
408 " using first matching segment: %s.\n", oseg->info->name);
409 fprintf (stderr,
410 " To use another, seg must be specified\n");
411 }
412 drms_free_record (orec);
413 return segnum;
414 }
415 /* main module body */
416 int DoIt (void) {
417 CmdParams_t *params = &cmdparams;
418 int propct;
419 char **copykeylist;
420 char module_ident[128];
421 DRMS_RecordSet_t *drs = NULL;
422 DRMS_Record_t *irec, *orec;
423 DRMS_Segment_t *iseg, *oseg;
424 DRMS_Array_t *orig_array, *bind_array;
425 double *vdat, *vbin;
426 double crpix, cdelt;
427 double scale, bias, vr, vw, vn;
428 float *wmin;
429 long long *nssub, *ntsub;
430 long long nn, ntdat, ntbin;
431 unsigned int qual_inp, qual_out;
432 int **loc;
433 int *np;
434 int *in_axes, *out_axes;
435 int *bin, *strt, *stop, *strt0, *stop0;
436 int axis, npmax;
437 int m, n, key_n, rec_n, rec_ct;
438 int isegnum, osegnum, rank, crank, axis_check;
439 int bias_mult, bias_sign, scale_mult, scale_sign;
440 int prefilter;
441 int kstat, status = 0;
442 int keyct = sizeof (propagate) / sizeof (char *);
443 char *key_scale, *key_bias;
444 char source[DRMS_MAXQUERYLEN];
445 char key[256], valuestr[256];
446
447 double missing_val = 0.0 / 0.0;
448
449 char *inds = strdup (params_get_str (params, "in"));
450 char *outser = strdup (params_get_str (params, "out"));
451 char *out_segname = strdup (params_get_str (params, "seg"));
452 int binvals = params_get_int (params, "bin_nvals");
453 int strtvals = params_get_int (params, "start_nvals");
454 int stopvals = params_get_int (params, "stop_nvals");
455 int wminvals = params_get_int (params, "wmin_nvals");
456 char *propagate_req = strdup (params_get_str (params, "copy"));
457 unsigned int qmask = cmdparams_get_int64 (params, "qmask", &status);
458 char *qual_key = strdup (params_get_str (params, "qual_key"));
459 int collapse = params_isflagset (params, "c");
460 int no_save = params_isflagset (params, "n");
461 int add_orbital_vr = params_isflagset (params, "o");
462 int add_orbital_full = params_isflagset (params, "O");
463 int scale_values = strcmp (params_get_str (params, "scale"), "Not Specified");
464 int bias_values = strcmp (params_get_str (params, "offset"), "Not Specified");
465 int verbose = params_isflagset (params, "v");
466 int dispose = (no_save) ? DRMS_FREE_RECORD : DRMS_INSERT_RECORD;
467
468 snprintf (module_ident, 128, "%s v %s", module_name, version_id);
469 if (verbose) printf ("%s:\n", module_ident);
470
471 /* check input data series structure */
472 if (check_input_series (inds, &isegnum)) return 1;
473
474 if (!strcmp (outser, "in")) {
475 outser = strdup (inds);
476 for (n = 0; n < strlen (outser); n++) if (outser[n] == '[') {
477 outser[n] = '\0';
478 break;
479 }
480 }
481 /* check output data series structure */
482 if (check_output_series (outser, out_segname, &osegnum, &axis_check)) {
483 drms_close_records (drs, DRMS_FREE_RECORD);
484 return 1;
485 }
486 /* open input data set */
487 drs = drms_open_records (drms_env, inds, &status);
488 rec_ct = drs->n;
489 irec = drs->records[0];
490 iseg = drms_segment_lookupnum (irec, isegnum);
491 crank = rank = iseg->info->naxis;
492 /* fill the per-axis arrays of bin, start, stop, and wmin values,
493 extending with the last element as necessary */
494 bin = (int *)malloc (rank * sizeof (int));
495 strt = (int *)malloc (rank * sizeof (int));
496 stop = (int *)malloc (rank * sizeof (int));
497 strt0 = (int *)malloc (rank * sizeof (int));
498 stop0 = (int *)malloc (rank * sizeof (int));
499 wmin = (float *)malloc (rank * sizeof (float));
500 if (binvals > rank) binvals = rank;
501 if (strtvals > rank) strtvals = rank;
502 if (stopvals > rank) stopvals = rank;
503 if (wminvals > rank) wminvals = rank;
504 for (n = 0; n < binvals; n++) {
505 sprintf (key, "bin_%d_value", n);
506 bin[n] = params_get_int (params, key);
507 }
508 while (n < rank) {
509 bin[n] = bin[n-1];
510 n++;
511 }
512 for (n = 0; n < strtvals; n++) {
513 sprintf (key, "start_%d_value", n);
514 strt[n] = params_get_int (params, key);
515 }
516 while (n < rank) {
517 strt[n] = strt[n-1];
518 n++;
519 }
520 for (n = 0; n < stopvals; n++) {
521 sprintf (key, "stop_%d_value", n);
522 stop[n] = params_get_int (params, key);
523 }
524 while (n < rank) {
525 stop[n] = stop[n-1];
526 n++;
527 }
528 for (n = 0; n < wminvals; n++) {
529 sprintf (key, "wmin_%d_value", n);
530 wmin[n] = params_get_float (params, key);
531 }
532 while (n < rank) {
533 wmin[n] = wmin[n-1];
534 n++;
535 }
536 /* save argument values for case of vardim input */
537 for (n = 0; n < rank; n++) {
538 strt0[n] = strt[n];
539 stop0[n] = stop[n];
540 }
541 /* initialize arrays and calculate target pixel lists for first record */
542 /* determine source locations for each binned target pixel */
543 in_axes = (int *)malloc (rank * sizeof (int));
544 out_axes = (int *)malloc (rank * sizeof (int));
545 nssub = (long long *)malloc (rank * sizeof (long long));
546 ntsub = (long long *)malloc (rank * sizeof (long long));
547 ntdat = ntbin = npmax = 1;
548 nssub[0] = ntsub[0] = 1;
549 for (n = 0; n < rank; n++) {
550 in_axes[n] = iseg->axis[n];
551 /* adjust start and stop values */
552 while (strt[n] < 0) strt[n] += in_axes[n];
553 while (stop[n] < 0) stop[n] += in_axes[n];
554 while (strt[n] >= in_axes[n]) strt[n] -= in_axes[n];
555 while (stop[n] >= in_axes[n]) stop[n] -= in_axes[n];
556 if (stop[n] < strt[n]) {
557 int save = strt[n];
558 strt[n] = stop[n];
559 stop[n] = save;
560 }
561
562 axis = stop[n] - strt[n] + 1;
563 out_axes[n] = axis / bin[n];
564 if (axis % bin[n]) out_axes[n]++;
565 ntdat *= in_axes[n];
566 ntbin *= out_axes[n];
567 npmax *= bin[n];
568 if (n) {
569 nssub[n] = nssub[n-1] * in_axes[n-1];
570 ntsub[n] = ntsub[n-1] * out_axes[n-1];
571 }
572 }
573 if (collapse) {
574 for (n = 0; n < rank; n++) {
575 if (out_axes[n] == 1) {
576 crank--;
577 for (m = n; m < crank; m++) out_axes[m] = out_axes[m + 1];
578 }
579 }
580 if (crank == rank) collapse = 0;
581 }
582 /* use first input record segment to find appropriate output segment
583 if needed */
584 if (axis_check) {
585 osegnum = find_output_segment (outser, crank, out_axes);
586 if (osegnum < 0) return 1;
587 }
588 /* create sample output series record */
589 orec = drms_create_record (drms_env, outser, DRMS_PERMANENT, &status);
590 oseg = drms_segment_lookupnum (orec, osegnum);
591 axis_check = (oseg->info->scope != DRMS_VARDIM);
592 /* check input data series keywords */
593 if (scale_values) {
594 char *endptr;
595 scale = strtod (params_get_str (params, "scale"), &endptr);
596 if (strlen (endptr)) {
597 key_scale = parse_as_arith_key (params_get_str (params, "scale"),
598 &scale_mult, &scale_sign);
599 if (!drms_keyword_lookup (irec, key_scale, 1)) {
600 fprintf (stderr, "Warning: required keyword %s not found\n", key_scale);
601 fprintf (stderr, " no scaling applied\n");
602 scale_values = 0;
603 }
604 } else scale_mult = scale_sign = 0;
605 }
606 if (bias_values) {
607 char *endptr;
608 bias = strtod (params_get_str (params, "offset"), &endptr);
609 if (strlen (endptr)) {
610 key_bias = parse_as_arith_key (params_get_str (params, "offset"),
611 &bias_mult, &bias_sign);
612 if (!drms_keyword_lookup (irec, key_bias, 1)) {
613 fprintf (stderr, "Warning: required keyword %s not found\n", key_bias);
614 fprintf (stderr, " no offset applied\n");
615 bias_values = 0;
616 }
617 } else bias_mult = bias_sign = 0;
618 }
619
620 if (add_orbital_vr || add_orbital_full) {
621 if (!drms_keyword_lookup (irec, "OBS_VR", 1)) {
622 fprintf (stderr, "Warning: required keyword %s not found\n", "OBS_VR");
623 fprintf (stderr, " no correction applied for observer velocity\n");
624 add_orbital_vr = add_orbital_full = 0;
625 }
626 if (add_orbital_full) {
627 add_orbital_vr = 0;
628 if (!drms_keyword_lookup (irec, "OBS_VW", 1)) {
629 fprintf (stderr, "Warning: required keyword %s not found\n", "OBS_VW");
630 fprintf (stderr, " no correction applied for observer velocity\n");
631 add_orbital_full = 0;
632 }
633 if (!drms_keyword_lookup (irec, "OBS_VW", 1)) {
634 fprintf (stderr, "Warning: required keyword %s not found\n", "OBS_VN");
635 fprintf (stderr, " no correction applied for observer velocity\n");
636 add_orbital_full = 0;
637 }
638 if (rank != 2) {
639 fprintf (stderr, "Warning: input data not image type\n");
640 fprintf (stderr,
641 " full correction of orbital velocity not supported\n");
642 add_orbital_full = 0;
643 }
644 fprintf (stderr,
645 "Warning: full correction of orbital velocity not implemented\n");
646 add_orbital_full = 0;
647 }
648 }
649 if (!collapse && oseg->info->naxis != rank) {
650 fprintf (stderr,
651 "Error: ranks of input and output data segments do not match\n");
652 drms_free_record (orec);
653 drms_close_records (drs, DRMS_FREE_RECORD);
654 return 1;
655 }
656 axis_check = (oseg->info->scope != DRMS_VARDIM);
657 /* fill the per-axis arrays of bin, start, stop, and wmin values,
658 extending with the last element as necessary */
659 /*
660 bin = (int *)malloc (rank * sizeof (int));
661 strt = (int *)malloc (rank * sizeof (int));
662 stop = (int *)malloc (rank * sizeof (int));
663 strt0 = (int *)malloc (rank * sizeof (int));
664 stop0 = (int *)malloc (rank * sizeof (int));
665 wmin = (float *)malloc (rank * sizeof (float));
666 if (binvals > rank) binvals = rank;
667 if (strtvals > rank) strtvals = rank;
668 if (stopvals > rank) stopvals = rank;
669 if (wminvals > rank) wminvals = rank;
670 for (n = 0; n < binvals; n++) {
671 sprintf (key, "bin_%d_value", n);
672 bin[n] = params_get_int (params, key);
673 }
674 while (n < rank) {
675 bin[n] = bin[n-1];
676 n++;
677 }
678 for (n = 0; n < strtvals; n++) {
679 sprintf (key, "start_%d_value", n);
680 strt[n] = params_get_int (params, key);
681 }
682 while (n < rank) {
683 strt[n] = strt[n-1];
684 n++;
685 }
686 for (n = 0; n < stopvals; n++) {
687 sprintf (key, "stop_%d_value", n);
688 stop[n] = params_get_int (params, key);
689 }
690 while (n < rank) {
691 stop[n] = stop[n-1];
692 n++;
693 }
694 for (n = 0; n < wminvals; n++) {
695 sprintf (key, "wmin_%d_value", n);
696 wmin[n] = params_get_float (params, key);
697 }
698 while (n < rank) {
699 wmin[n] = wmin[n-1];
700 n++;
701 }
702 */
703 /* save argument values for case of vardim input */
704 /*
705 for (n = 0; n < rank; n++) {
706 strt0[n] = strt[n];
707 stop0[n] = stop[n];
708 }
709 */
710 /* prefilter to be applied? */
711 prefilter = isfinite (wmin[0]);
712 for (n = 1; n < rank; n++) {
713 if (prefilter && isnan (wmin[n])) {
714 fprintf (stderr, "Warning: not all wmin values valid\n");
715 fprintf (stderr, " filtering turned off\n");
716 prefilter = 0;
717 break;
718 }
719 if (isfinite (wmin[n])) prefilter = 1;
720 }
721 /* initialize arrays and calculate target pixel lists for first record */
722 /* determine source locations for each binned target pixel */
723 in_axes = (int *)malloc (rank * sizeof (int));
724 out_axes = (int *)malloc (rank * sizeof (int));
725 nssub = (long long *)malloc (rank * sizeof (long long));
726 ntsub = (long long *)malloc (rank * sizeof (long long));
727 ntdat = ntbin = npmax = 1;
728 nssub[0] = ntsub[0] = 1;
729 for (n = 0; n < rank; n++) {
730 in_axes[n] = iseg->axis[n];
731 /* adjust start and stop values */
732 while (strt[n] < 0) strt[n] += in_axes[n];
733 while (stop[n] < 0) stop[n] += in_axes[n];
734 while (strt[n] >= in_axes[n]) strt[n] -= in_axes[n];
735 while (stop[n] >= in_axes[n]) stop[n] -= in_axes[n];
736 if (stop[n] < strt[n]) {
737 int save = strt[n];
738 strt[n] = stop[n];
739 stop[n] = save;
740 }
741
742 axis = stop[n] - strt[n] + 1;
743 out_axes[n] = axis / bin[n];
744 if (axis % bin[n]) out_axes[n]++;
745 ntdat *= in_axes[n];
746 ntbin *= out_axes[n];
747 npmax *= bin[n];
748 if (n) {
749 nssub[n] = nssub[n-1] * in_axes[n-1];
750 ntsub[n] = ntsub[n-1] * out_axes[n-1];
751 }
752 }
753 /* this check also belongs below if input is vardim */
754 if (axis_check) {
755 /* the output and the input both have fixed sizes; they'd better match */
756 for (n = 0; n < rank; n++) {
757 if (out_axes[n] != oseg->axis[n]) {
758 fprintf (stderr,
759 "Error: array mismatch between output segment definition\n");
760 fprintf (stderr,
761 " and desired binning on fixed input segment definition\n");
762 fprintf (stderr, "axis[%d] = %d, should be %d\n", n, oseg->axis[n],
763 out_axes[n]);
764 drms_free_record (orec);
765 drms_close_records (drs, DRMS_FREE_RECORD);
766 return 1;
767 }
768 }
769 if (iseg->info->scope != DRMS_VARDIM) axis_check = 0;
770 }
771 np = (int *)calloc (ntbin, sizeof (int));
772 loc = (int **)malloc (ntbin * sizeof (int *));
773 for (nn = 0; nn < ntbin; nn++) loc[nn] = (int *)malloc (npmax * sizeof (int));
774 /* determine source locations for each binned target pixel */
775 for (nn = 0; nn < ntdat; nn++) {
776 int trgpix;
777 int intarget = 1;
778 int srcpix = (nn % in_axes[0]);
779 if (srcpix < strt[0] || srcpix > stop[0]) intarget = 0;
780 trgpix = (srcpix - strt[0]) / bin[0];
781 for (m = 1; m < rank; m++) {
782 srcpix = (nn / nssub[m]) % in_axes[m];
783 if (srcpix < strt[m] || srcpix > stop[m]) {
784 intarget = 0;
785 break;
786 }
787 trgpix += ((srcpix - strt[m]) / bin[m]) * ntsub[m];
788 }
789 if (intarget) {
790 loc[trgpix][np[trgpix]] = nn;
791 np[trgpix]++;
792 }
793 }
794
795 vbin = (double *)malloc (ntbin * sizeof (double));
796 int *bind_axes = (int *)malloc (rank * sizeof (int));
797 memcpy (bind_axes, out_axes, rank * sizeof (int));
798 bind_array = drms_array_create (DRMS_TYPE_DOUBLE, rank, out_axes,
799 (void *)vbin, &status);
800 bind_array->bscale = oseg->bscale;
801 bind_array->bzero = oseg->bzero;
802 drms_free_record (orec);
803
804 propct = construct_stringlist (propagate_req, ',', &copykeylist);
805 if (verbose) {
806 printf ("propagating %d key(s):\n", propct);
807 for (n = 0; n < propct; n++) printf (" %s\n", copykeylist[n]);
808 printf ("\nprocessing %d record(s) in series %s:\n", rec_ct, inds);
809 }
810
811 if (axis_check) {
812 fprintf (stderr,
813 "Warning: either input or output segment has protocol vardim\n");
814 fprintf (stderr,
815 " not currently supported; results may be garbage!\n");
816 /*
817 return 1;
818 */
819 }
820
821 for (rec_n = 0; rec_n < rec_ct; rec_n++) {
822 if (verbose) printf ("record %d:\n", rec_n);
823 irec = drs->records[rec_n];
824 drms_sprint_rec_query (source, irec);
825 orec = drms_create_record (drms_env, outser, DRMS_PERMANENT, &status);
826 if (verbose) printf (" processing record %d: %s\n", rec_n, source);
827 kstat = 0;
828 /* copy in values for new record's prime keys if possible
829 (they may be recopied or even overwritten later) */
830 kstat += copy_prime_keys (orec, irec);
831 for (key_n = 0; key_n < propct; key_n++) {
832 if (strcmp (copykeylist[key_n], "+"))
833 kstat += check_and_copy_key (orec, irec, copykeylist[key_n]);
834 else kstat += propagate_keys (orec, irec, propagate, keyct);
835 }
836 kstat += check_and_set_key_time (orec, "Date", CURRENT_SYSTEM_TIME);
837 kstat += check_and_set_key_time (orec, "Created", CURRENT_SYSTEM_TIME);
838 kstat += check_and_set_key_str (orec, "Module", module_ident);
839 kstat += check_and_set_key_str (orec, "Input", inds);
840 kstat += check_and_set_key_str (orec, "Source", source);
841 kstat += check_and_set_key_str (orec, "BLD_VERS", jsoc_version);
842 /* check quality flag for presence of data segment */
843 qual_inp = drms_getkey_int (irec, qual_key, &status);
844 if ((qual_inp & qmask) && !status) {
845 kstat += check_and_set_key_int (orec, "Quality", 0x80000000);
846 drms_close_record (orec, dispose);
847 continue;
848 }
849 qual_out = 0x00000000;
850 iseg = drms_segment_lookupnum (irec, isegnum);
851 if (!iseg) {
852 fprintf (stderr, "Warning: could not find segment # %d\n", isegnum);
853 fprintf (stderr, " in %s; skipped\n", source);
854 continue;
855 }
856 /* read data from segment into array as doubles
857 (will block until segment is staged) */
858 orig_array = drms_segment_read (iseg, DRMS_TYPE_DOUBLE, &status);
859 if (!orig_array) {
860 fprintf (stderr, "Warning: could not read segment # %d\n", isegnum);
861 fprintf (stderr, " in %s; skipped\n", source);
862 continue;
863 }
864 if (prefilter) {
865 /* apply optional prefilter to data */
866 status = data_filter (orig_array);
867 fprintf (stderr, "Warning: prefiltering not implemented\n");
868 }
869 vdat = (double *)orig_array->data;
870 oseg = drms_segment_lookupnum (orec, osegnum);
871 if (iseg->info->scope == DRMS_VARDIM) {
872 /* input series has variable dimensions; have they changed? */
873 int recalc = 0, recok = 1;
874 for (n = 0; n < rank; n++) {
875 if (in_axes[n] != iseg->axis[n]) recalc = 1;
876 in_axes[n] = iseg->axis[n];
877 }
878 if (recalc) {
879 /* yes, need to recalculate target array */
880 for (n = 0; n < rank; n++) {
881 strt[n] = strt0[n];
882 stop[n] = stop0[n];
883 }
884 ntdat = ntbin = npmax = 1;
885 ntsub[0] = nssub[0] = 1;
886 for (n = 0; n < rank; n++) {
887 /* adjust start and stop values */
888 while (strt[n] < 0) strt[n] += in_axes[n];
889 while (stop[n] < 0) stop[n] += in_axes[n];
890 while (strt[n] >= in_axes[n]) strt[n] -= in_axes[n];
891 while (stop[n] >= in_axes[n]) stop[n] -= in_axes[n];
892 if (stop[n] < strt[n]) {
893 int save = strt[n];
894 strt[n] = stop[n];
895 stop[n] = save;
896 }
897 axis = stop[n] - strt[n] + 1;
898 out_axes[n] = axis / bin[n];
899 if (axis % bin[n]) out_axes[n]++;
900 ntdat *= in_axes[n];
901 ntbin *= out_axes[n];
902 npmax *= bin[n];
903 if (n) {
904 nssub[n] = nssub[n-1] * in_axes[n-1];
905 ntsub[n] = ntsub[n-1] * out_axes[n-1];
906 }
907 }
908 if (axis_check) {
909 /* the output has fixed sizes, so check it */
910 for (n = 0; n < rank; n++) {
911 if (out_axes[n] != oseg->axis[n]) {
912 fprintf (stderr,
913 "Warning: array mismatch between output segment definition\n");
914 fprintf (stderr,
915 " and desired binning on input segment in\n");
916 fprintf (stderr, " %s; skipped\n", source);
917 drms_free_record (orec);
918 recok = 0;
919 break;
920 }
921 }
922 if (!recok) continue;
923 }
924
925 np = (int *)realloc (np, ntbin * sizeof (int));
926 for (nn = 0; nn < ntbin; nn++) np[nn] = 0;
927 loc = (int **)realloc (loc, ntbin * sizeof (int *));
928 for (nn = 0; nn < ntbin; nn++) {
929 if (loc[nn]) free (loc[nn]);
930 loc[nn] = (int *)malloc (npmax * sizeof (int));
931 }
932 for (nn = 0; nn < ntdat; nn++) {
933 int trgpix;
934 int intarget = 1;
935 int srcpix = (nn % in_axes[0]);
936 if (srcpix < strt[0] || srcpix >= stop[0]) intarget = 0;
937 trgpix = (srcpix - strt[0]) / bin[0];
938 for (m = 1; m < rank; m++) {
939 srcpix = (nn / nssub[m]) % in_axes[m];
940 if (srcpix < strt[m] || srcpix >= stop[m]) {
941 intarget = 0;
942 break;
943 }
944 trgpix += ((srcpix - strt[m]) / bin[m]) * ntsub[m];
945 }
946 if (intarget) {
947 loc[trgpix][np[trgpix]] = nn;
948 np[trgpix]++;
949 }
950 }
951 }
952 }
953 /* for now, match scaling of output to input */
954 /*
955 bind_array->bscale = orig_array->bscale;
956 bind_array->bzero = orig_array->bzero;
957 */
958 if (bias_values) {
959 if (bias_mult) {
960 bias = drms_getkey_double (irec, key_bias, &status);
961 if (bias_mult < 0) bias = 1.0 / bias;
962 bias *= bias_sign;
963 }
964 for (nn = 0; nn < ntdat; nn++) if (isfinite (bias)) vdat[nn] += bias;
965 }
966 if (scale_values) {
967 if (scale_mult) {
968 scale = drms_getkey_double (irec, key_scale, &status);
969 if (scale_mult < 0) scale = 1.0 / scale;
970 scale *= scale_sign;
971 }
972 for (nn = 0; nn < ntdat; nn++) if (isfinite (scale)) vdat[nn] *= scale;
973 }
974 if (add_orbital_vr) {
975 vr = drms_getkey_double (irec, "OBS_VR", &status);
976 for (nn = 0; nn < ntdat; nn++) if (isfinite (vr)) vdat[nn] -= vr;
977 }
978 if (add_orbital_full) {
979 vr = drms_getkey_double (irec, "OBS_VR", &status);
980 vw = drms_getkey_double (irec, "OBS_VW", &status);
981 vn = drms_getkey_double (irec, "OBS_VN", &status);
982 }
983 for (nn = 0; nn < ntbin; nn++) {
984 vbin[nn] = 0;
985 for (m = 0; m < np[nn]; m++) {
986 vbin[nn] += vdat[loc[nn][m]];
987 }
988 /* adjust scaling of binned array */
989 if (np[nn]) vbin[nn] /= np[nn];
990 else vbin[nn] = missing_val;
991 }
992 drms_free_array (orig_array);
993
994 if (collapse) {
995 DRMS_Array_t *coll_array;
996 int crank = rank;
997 for (n = 0; n < rank; n++) {
998 if (out_axes[n] == 1) {
999 crank--;
1000 for (m = n; m < crank; m++) out_axes[m] = out_axes[m + 1];
1001 }
1002 }
1003 coll_array = drms_array_create (DRMS_TYPE_DOUBLE, crank, out_axes,
1004 (void *)vbin, &status);
1005 coll_array->bscale = bind_array->bscale;
1006 coll_array->bzero = bind_array->bzero;
1007 drms_segment_write (oseg, coll_array, 0);
1008 } else drms_segment_write (oseg, bind_array, 0);
1009 kstat += check_and_set_key_int (orec, "Quality", qual_out);
1010 /* parameter keys */
1011 for (n = 0; n < rank; n++) {
1012 sprintf (key, "binwdth_%d", n);
1013 kstat += check_and_set_key_int (orec, key, bin[n]);
1014 sprintf (key, "startpx_%d", n);
1015 kstat += check_and_set_key_int (orec, key, strt[n]);
1016 sprintf (key, "stoppx_%d", n);
1017 kstat += check_and_set_key_int (orec, key, stop[n]);
1018 }
1019 /* adjust WCS keys */
1020 for (n = 0; n < rank; n++) {
1021 sprintf (key, "CTYPE%d", n + 1);
1022 kstat += check_and_copy_key (orec, irec, key);
1023 sprintf (key, "CRVAL%d", n + 1);
1024 kstat += check_and_copy_key (orec, irec, key);
1025 sprintf (key, "CRPIX%d", n + 1);
1026 crpix = drms_getkey_double (irec, key, &status);
1027 if (!status) {
1028 crpix -= strt[n];
1029 crpix /= bin[n];
1030 kstat += check_and_set_key_double (orec, key, crpix);
1031 }
1032 sprintf (key, "CDELT%d", n + 1);
1033 cdelt = drms_getkey_double (irec, key, &status);
1034 if (!status) {
1035 cdelt *= bin[n];
1036 kstat += check_and_set_key_double (orec, key, cdelt);
1037 }
1038 sprintf (key, "CROTA%d", n + 1);
1039 kstat += check_and_copy_key (orec, irec, key);
1040 }
1041 if (bias_values) {
1042 if (bias_mult) {
1043 if (bias_mult < 0) {
1044 if (bias_sign < 0) snprintf (valuestr, 256, "1/(-%s)", key_bias);
1045 else snprintf (valuestr, 256, "1/%s", key_scale);
1046 } else {
1047 if (bias_sign < 0) snprintf (valuestr, 256, "-%s", key_bias);
1048 else snprintf (valuestr, 256, "%s", key_bias);
1049 }
1050 } else snprintf (valuestr, 256, "%g", bias);
1051 kstat += check_and_set_key_str (orec, "OffsetBy", valuestr);
1052 if (verbose) {
1053 printf (" offset by ");
1054 if (bias_mult) printf ("%s = ", valuestr);
1055 printf ("%g\n", bias);
1056 }
1057 }
1058 if (scale_values) {
1059 if (scale_mult) {
1060 if (scale_mult < 0) {
1061 if (scale_sign < 0) snprintf (valuestr, 256, "1/(-%s)", key_scale);
1062 else snprintf (valuestr, 256, "1/%s", key_scale);
1063 } else {
1064 if (scale_sign < 0) snprintf (valuestr, 256, "-%s", key_scale);
1065 else snprintf (valuestr, 256, "%s", key_scale);
1066 }
1067 } else snprintf (valuestr, 256, "%g", scale);
1068 kstat += check_and_set_key_str (orec, "ScaledBy", valuestr);
1069 if (verbose) {
1070 printf (" scaled by ");
1071 if (scale_mult) printf ("%s = ", valuestr);
1072 printf ("%g\n", scale);
1073 }
1074 }
1075 /* statistics keys */
1076 kstat += set_stats_keys (orec, bind_array, ntbin);
1077 drms_close_record (orec, dispose);
1078 }
1079 drms_close_records (drs, DRMS_FREE_RECORD);
1080
1081 return 0;
1082 }
1083
1084 /*
1085 * Revision History (all mods by Rick Bogart unless otherwise noted)
1086 *
1087 * 10.01.22 File created by R Bogart
1088 * v 0.7 Binning, and setting of critical (WCS) keywords, but no
1089 * image extraction
1090 * v 0.7 frozen 2010.01.26
1091 * v 0.8 Modified call to drms_record_nextseg for DRMS 2.0
1092 * Changed indexing to quad long where appropriate
1093 * Added recalculation of target arrays for vardim input
1094 * v 0.8 frozen 2010.03.08
1095 * v 0.9 Put in hack to accept vardim segments on input, but not
1096 * actually deal with them
1097 * Added CROTAn, DATE__OBS, TELESCOP and INSTRUME to default
1098 * propagated keywords
1099 * Added copying of output's prime keys, setting of Input key
1100 * Fixed bug that was preventing last entry of slowest-index
1101 * from being properly filled
1102 * Added options for removal of orbital velocity (2nd-order only
1103 * a stub) and scaling and/or offset by fixed numerical value or keyword
1104 * value, and setting of appropriate keywords; added (unconditional)
1105 * setting of statistics keywords; added checking and setting of quality
1106 * flags
1107 * Moved construct_stringlist() function to keystuff
1108 * v 0.9 frozen 2010.08.20
1109 * v 1.0 Added stubs for optional pre-filtering
1110 * Added collapse option
1111 * Fixed setting of array bzero
1112 * v 1.0 frozen 2011.11.15
1113 */