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, ',', ©keylist); |
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 |
*/ |