156 {
158 char *inputFile, *outputFile, *xCol = "x", *yCol = "y", **zCol = NULL, *stdCol = "StdError", *pointsFile = NULL, **zColMatch = NULL;
159 char *pointsFileXName = NULL, *pointsFileYName = NULL;
160 long i, j, i_arg, k, scale, *rows, pages, merge = 0, point_pages = 0, writepage = 0, zColMatches = 0;
161 int32_t zCols = 1;
162 unsigned long dummyFlags = 0, pipeFlags = 0, majorOrderFlag;
163 SCANNED_ARG *s_arg;
164 double **x = NULL, **y = NULL, ***z = NULL, xmin = 0, xmax = 0, ymin = 0, ymax = 0, **std = NULL, *std_all = NULL;
165 specs *spec = specs_create();
166 int nin = 0;
167 point **pin = NULL;
168 int nout = 0;
169 point *pout = NULL;
171 short columnMajorOrder = -1;
172
173
174 spec->wmin = 0;
175 inputFile = outputFile = NULL;
177 argc =
scanargs(&s_arg, argc, argv);
178 if (argc < 2) {
179 fprintf(stderr, "%s", USAGE);
180 return EXIT_FAILURE;
181 }
182
183 for (i_arg = 1; i_arg < argc; i_arg++) {
184 if (s_arg[i_arg].arg_type == OPTION) {
186 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
187 case CLO_MAJOR_ORDER:
188 majorOrderFlag = 0;
189 s_arg[i_arg].n_items -= 1;
190 if (s_arg[i_arg].n_items > 0 &&
191 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
192 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
193 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
194 SDDS_Bomb(
"Invalid -majorOrder syntax/values");
195 }
196 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
197 columnMajorOrder = 1;
198 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
199 columnMajorOrder = 0;
200 break;
201 case CLO_FILE:
202 if (s_arg[i_arg].n_items != 2 && s_arg[i_arg].n_items != 4)
204 pointsFile = s_arg[i_arg].list[1];
205 if (s_arg[i_arg].n_items == 4) {
206 pointsFileXName = s_arg[i_arg].list[2];
207 pointsFileYName = s_arg[i_arg].list[3];
208 }
209 break;
210 case CLO_PIPE:
211 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
213 break;
214 case CLO_INDEPENDENT_COLUMN:
215 if (s_arg[i_arg].n_items < 3)
216 SDDS_Bomb(
"Invalid -independentColumn syntax.");
217 s_arg[i_arg].n_items--;
218 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
222 SDDS_Bomb(
"Invalid -independentColumn syntax");
223 s_arg[i_arg].n_items++;
224 break;
225 case CLO_DEPENDENT_COLUMN:
226 if (s_arg[i_arg].n_items < 2)
227 SDDS_Bomb(
"Invalid -dependentColumn syntax.");
228 zColMatches = s_arg[i_arg].n_items - 1;
229 zColMatch =
tmalloc(
sizeof(*zColMatch) * zColMatches);
230 for (i = 0; i < zColMatches; i++)
231 zColMatch[i] = s_arg[i_arg].list[i + 1];
232 break;
233 case CLO_SCALE:
234 if (s_arg[i_arg].n_items != 2)
236 if ((scale =
match_string(s_arg[i_arg].list[1], scale_option, SCALE_OPTIONS, 0)) == -1) {
237 fprintf(stderr, "Invalid scale option - %s provided.\n", s_arg[i_arg].list[1]);
238 exit(EXIT_FAILURE);
239 }
240 spec->square = !scale;
241 spec->invariant = scale;
242 break;
243 case CLO_OUT_DIMENSION:
244 if (s_arg[i_arg].n_items != 3)
245 SDDS_Bomb(
"Invalid -outDimension syntax.");
246 s_arg[i_arg].n_items--;
247 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
248 "xdimension",
SDDS_LONG, &spec->nx, 1, 0,
249 "ydimension",
SDDS_LONG, &spec->ny, 1, 0, NULL))
250 SDDS_Bomb(
"Invalid -outDimension syntax");
251 s_arg[i_arg].n_items++;
252 if (spec->nx <= 0 || spec->nx > NMAX || spec->ny <= 0 || spec->ny > NMAX)
253 SDDS_Bomb(
"Invalid size for output grid.");
254 spec->generate_points = 1;
255 break;
256 case CLO_RANGE:
257 if (s_arg[i_arg].n_items < 2)
259 s_arg[i_arg].n_items--;
260 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
266 s_arg[i_arg].n_items++;
267 if (spec->xmin > spec->xmax || spec->ymin > spec->ymax ||
268 isnan(spec->xmin) || isnan(spec->xmax) || isnan(spec->ymin) || isnan(spec->ymax))
270 spec->range = 1;
271 break;
272 case CLO_ZOOM:
273 if (s_arg[i_arg].n_items != 2)
275 if (!
get_double(&spec->zoom, s_arg[i_arg].list[1]))
276 SDDS_Bomb(
"Invalid -zoom value provided.");
277 break;
278 case CLO_DIMENSION_THIN:
279 if (s_arg[i_arg].n_items != 3)
280 SDDS_Bomb(
"Invalid -dimensionThin syntax.");
281 s_arg[i_arg].n_items--;
282 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
283 "xdimension",
SDDS_LONG, &spec->nxd, 1, 0,
284 "ydimension",
SDDS_LONG, &spec->nyd, 1, 0, NULL))
285 SDDS_Bomb(
"Invalid -dimensionThin syntax");
286 s_arg[i_arg].n_items++;
287 spec->thin = 1;
288 break;
289 case CLO_CLUSTER_THIN:
290 if (s_arg[i_arg].n_items != 2)
291 SDDS_Bomb(
"Invalid -clusterThin syntax.");
292 if (!
get_double(&spec->rmax, s_arg[i_arg].list[1]))
293 SDDS_Bomb(
"Invalid -clusterThin value provided.");
294 spec->thin = 2;
295 break;
296 case CLO_PREPROCESS:
297 spec->nointerp = 1;
298 break;
299 case CLO_ALGORITHM:
300 if (s_arg[i_arg].n_items < 2)
302 if ((spec->method =
match_string(s_arg[i_arg].list[1], algorithm_option, ALGORITHMS, 0)) == -1) {
303 fprintf(stderr, "Invalid algorithm - %s provided, has to be nn or csa.\n", s_arg[i_arg].list[1]);
304 exit(EXIT_FAILURE);
305 }
306 dummyFlags = 0;
307 s_arg[i_arg].n_items -= 2;
308 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
309 "linear", -1, NULL, 0, LINEAR_NN,
310 "sibson", -1, NULL, 0, SIBSON_NN,
311 "nonSibson", -1, NULL, 0, NONSIBSON_NN,
315 spec->linear = 0;
316 if (!dummyFlags || dummyFlags & LINEAR_NN) {
317 spec->linear = 1;
318 } else if (dummyFlags & SIBSON_NN) {
319 nn_rule = SIBSON;
320 } else if (dummyFlags & NONSIBSON_NN) {
321 nn_rule = NON_SIBSONIAN;
322 }
323 s_arg[i_arg].n_items += 2;
324 break;
325 case CLO_WEIGHT:
326 if (s_arg[i_arg].n_items != 2)
328 if (
match_string(s_arg[i_arg].list[1], INFINITY_OPTION, 1, 0) == 0)
329 spec->wmin = -DBL_MAX;
330 else {
331 if (!
get_double(&spec->wmin, s_arg[i_arg].list[1]))
332 SDDS_Bomb(
"Invalid weight value provided.");
333 }
334 break;
335 case CLO_VERTEX:
336 if (s_arg[i_arg].n_items != 2)
338 if (!
get_int(&nn_test_vertice, s_arg[i_arg].list[1]))
339 SDDS_Bomb(
"Invalid vertex value provided.");
340 nn_verbose = 1;
341 break;
342 case CLO_NPOINTS:
343 if (s_arg[i_arg].n_items != 2)
345 if (!
get_int(&spec->npoints, s_arg[i_arg].list[1]))
346 SDDS_Bomb(
"Invalid npoints value provided.");
347 break;
348 case CLO_VERBOSE:
349 nn_verbose = 2;
350 break;
351 case CLO_MERGE:
352 merge = 1;
353 break;
354 default:
355 fprintf(stderr, "Unknown option - %s provided.\n", s_arg[i_arg].list[0]);
356 exit(EXIT_FAILURE);
357 break;
358 }
359 } else {
360 if (!inputFile)
361 inputFile = s_arg[i_arg].list[0];
362 else if (!outputFile)
363 outputFile = s_arg[i_arg].list[0];
364 else
366 }
367 }
368
369 processFilenames(
"sdds2dinterpolate", &inputFile, &outputFile, pipeFlags, 0, NULL);
370 if (!spec->generate_points && !spec->nointerp && !pointsFile) {
371 fprintf(stderr, "No output grid specified.\n");
372 exit(EXIT_FAILURE);
373 }
374 if (spec->thin) {
375 if (spec->nxd == -1)
376 spec->nxd = spec->nx;
377 if (spec->nyd == -1)
378 spec->nyd = spec->ny;
379 if (spec->nxd <= 0 || spec->nyd <= 0) {
380 fprintf(stderr, "Invalid grid size for thinning.\n");
381 exit(EXIT_FAILURE);
382 }
383 }
384 if (spec->npoints == 1) {
385 if (spec->nx <= 0)
386 spec->npoints = 0;
387 else
388 spec->npoints = spec->nx * spec->ny;
389 }
390 ReadInputFile(inputFile, xCol, yCol, zColMatch, zColMatches, &zCol, &zCols, stdCol, &pages, &rows, &x, &y, &z, &std, &SDDS_in);
391 if (!spec->nointerp)
392 SetupOutputFile(&SDDS_out, &SDDS_in, outputFile, xCol, yCol, pointsFileXName, pointsFileYName,
393 zCol, zCols, columnMajorOrder);
396 if (pointsFile)
397 ReadPointFile(pointsFile, pointsFileXName ? pointsFileXName : xCol, pointsFileYName ? pointsFileYName : yCol,
398 &point_pages, &out_point);
399 pin =
tmalloc(
sizeof(*pin) * zCols);
400 if (merge) {
401 for (i = 0; i < pages; i++) {
402 if (!i) {
403 xmin = xmax = x[0][0];
404 ymin = ymax = y[0][0];
405 }
406 for (k = 0; k < zCols; k++)
407 pin[k] =
SDDS_Realloc(pin[k],
sizeof(**pin) * (nin + rows[i]));
408 if (std)
409 std_all =
SDDS_Realloc(std_all,
sizeof(*std_all) * (nin + rows[i]));
410 for (j = 0; j < rows[i]; j++) {
411 if (x[i][j] < xmin)
412 xmin = x[i][j];
413 else if (x[i][j] > xmax)
414 xmax = x[i][j];
415 if (y[i][j] < ymin)
416 ymin = y[i][j];
417 else if (y[i][j] > ymax)
418 ymax = y[i][j];
419 for (k = 0; k < zCols; k++) {
420 pin[k][nin + j].x = x[i][j];
421 pin[k][nin + j].y = y[i][j];
422 pin[k][nin + j].z = z[k][i][j];
423 }
424 if (std)
425 std_all[nin + j] = std[i][j];
426 }
427 nin += rows[i];
428 free(x[i]);
429 free(y[i]);
430 for (k = 0; k < zCols; k++) {
431 free(z[k][i]);
432 z[k][i] = NULL;
433 }
434 if (std && std[i]) {
435 free(std[i]);
436 std[i] = NULL;
437 }
438 x[i] = y[i] = NULL;
439 }
440 free(x);
441 free(y);
442 x = y = NULL;
443 for (k = 0; k < zCols; k++) {
444 free(z[k]);
445 z[k] = NULL;
446 }
447 free(z);
448 z = NULL;
449 if (std)
450 free(std);
451 std = NULL;
452 if (!spec->range) {
453 spec->xmin = xmin;
454 spec->ymin = ymin;
455 spec->xmax = xmax;
456 spec->ymax = ymax;
457 }
458 if (pointsFile) {
459 if (!interpolate_output_points(nin, pin, std_all, xCol, yCol, pointsFileXName, pointsFileYName,
460 zCol, zCols, spec, pages, out_point, &SDDS_out))
461 exit(EXIT_FAILURE);
462 writepage = 1;
463 } else {
464 for (k = 0; k < zCols; k++) {
465 if (spec->method == NN) {
466 do_nn_2d_interpolate(spec, &nin, &pin[k], &nout, &pout);
467 } else if (spec->method == CSA) {
468 do_csa_2d_interpolate(spec, nin, pin[k], &nout, &pout, std_all);
469 }
470 if (!spec->nointerp) {
471 if (!writepage) {
472 WriteOutputPage(&SDDS_out, pointsFileXName ? pointsFileXName : xCol,
473 pointsFileYName ? pointsFileYName : yCol,
474 zCol[k], spec, nout, pout, 0);
475 writepage = 1;
476 } else {
477 for (i = 0; i < nout; i++) {
479 zCol[k], pout[i].z, NULL))
481 }
482 }
483 }
484 }
487 }
488 } else {
489 for (i = 0; i < pages; i++) {
490 xmin = xmax = x[i][0];
491 ymin = ymax = y[i][0];
492 nin = rows[i];
493 for (j = 0; j < nin; j++) {
494 if (x[i][j] < xmin)
495 xmin = x[i][j];
496 else if (x[i][j] > xmax)
497 xmax = x[i][j];
498 if (y[i][j] < ymin)
499 ymin = y[i][j];
500 else if (y[i][j] > ymax)
501 ymax = y[i][j];
502 }
503 if (!spec->range) {
504 spec->xmin = xmin;
505 spec->ymin = ymin;
506 spec->xmax = xmax;
507 spec->ymax = ymax;
508 }
509 for (k = 0; k < zCols; k++) {
510 pin[k] = malloc(sizeof(**pin) * nin);
511 for (j = 0; j < rows[i]; j++) {
512 pin[k][j].x = x[i][j];
513 pin[k][j].y = y[i][j];
514 pin[k][j].z = z[k][i][j];
515 }
516 free(z[k][i]);
517 }
518 free(x[i]);
519 free(y[i]);
520 x[i] = y[i] = NULL;
521 if (std && std[i])
522 std_all = std[i];
523 else
524 std_all = NULL;
525 if (pointsFile) {
526 if (!interpolate_output_points(nin, pin, std_all, xCol, yCol, pointsFileXName, pointsFileYName,
527 zCol, zCols, spec, point_pages, out_point, &SDDS_out))
528 exit(EXIT_FAILURE);
529 writepage = 1;
530 } else {
531 for (k = 0; k < zCols; k++) {
532 if (spec->method == NN) {
533 do_nn_2d_interpolate(spec, &nin, &pin[k], &nout, &pout);
534 } else if (spec->method == CSA) {
535 do_csa_2d_interpolate(spec, nin, pin[k], &nout, &pout, std_all);
536 }
537 if (!spec->nointerp) {
538 if (!writepage) {
539 WriteOutputPage(&SDDS_out, pointsFileXName ? pointsFileXName : xCol,
540 pointsFileYName ? pointsFileYName : yCol,
541 zCol[k], spec, nout, pout, 0);
542 writepage = 1;
543 } else {
544 for (j = 0; j < nout; j++) {
546 zCol[k], pout[j].z, NULL))
548 }
549 }
550 }
551 }
552 if (std && std[i]) {
553 free(std[i]);
554 std[i] = NULL;
555 }
558 }
559 }
560 free(x);
561 free(y);
562 for (k = 0; k < zCols; k++)
563 free(z[k]);
564 free(z);
565 x = y = NULL;
566 }
567 if (std)
568 free(std);
569 for (k = 0; k < zCols; k++)
570 free(pin[k]);
571 free(pin);
574 if (point_pages && out_point) {
575 for (i = 0; i < point_pages; i++) {
576 free(out_point[i].pout);
577 }
578 free(out_point);
579 }
580 if (pout)
581 free(pout);
582 free(spec);
583 free(rows);
584 for (i = 0; i < zCols; i++)
585 free(zCol[i]);
586 free(zCol);
588 return EXIT_SUCCESS;
589}
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
int get_double(double *dptr, char *s)
Parses a double value from the given string.
int get_int(int *iptr, char *s)
Parses an integer value from the given string.
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.