182 {
184 char *inputFile, *outputFile, *xCol = "x", *yCol = "y", **zCol = NULL, *stdCol = "StdError", *pointsFile = NULL, **zColMatch = NULL;
185 char *pointsFileXName = NULL, *pointsFileYName = NULL;
186 long i, j, i_arg, k, scale, *rows, pages, merge = 0, point_pages = 0, writepage = 0, zColMatches = 0;
187 int32_t zCols = 1;
188 unsigned long dummyFlags = 0, pipeFlags = 0, majorOrderFlag;
189 SCANNED_ARG *s_arg;
190 double **x = NULL, **y = NULL, ***z = NULL, xmin = 0, xmax = 0, ymin = 0, ymax = 0, **std = NULL, *std_all = NULL;
191 specs *spec = specs_create();
192 int nin = 0;
193 point **pin = NULL;
194 int nout = 0;
195 point *pout = NULL;
197 short columnMajorOrder = -1;
198
199
200 spec->wmin = 0;
201 inputFile = outputFile = NULL;
203 argc =
scanargs(&s_arg, argc, argv);
204 if (argc < 2) {
205 fprintf(stderr, "%s", USAGE);
206 return EXIT_FAILURE;
207 }
208
209 for (i_arg = 1; i_arg < argc; i_arg++) {
210 if (s_arg[i_arg].arg_type == OPTION) {
212 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
213 case CLO_MAJOR_ORDER:
214 majorOrderFlag = 0;
215 s_arg[i_arg].n_items -= 1;
216 if (s_arg[i_arg].n_items > 0 &&
217 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
218 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
219 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
220 SDDS_Bomb(
"Invalid -majorOrder syntax/values");
221 }
222 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
223 columnMajorOrder = 1;
224 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
225 columnMajorOrder = 0;
226 break;
227 case CLO_FILE:
228 if (s_arg[i_arg].n_items != 2 && s_arg[i_arg].n_items != 4)
230 pointsFile = s_arg[i_arg].list[1];
231 if (s_arg[i_arg].n_items == 4) {
232 pointsFileXName = s_arg[i_arg].list[2];
233 pointsFileYName = s_arg[i_arg].list[3];
234 }
235 break;
236 case CLO_PIPE:
237 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
239 break;
240 case CLO_INDEPENDENT_COLUMN:
241 if (s_arg[i_arg].n_items < 3)
242 SDDS_Bomb(
"Invalid -independentColumn syntax.");
243 s_arg[i_arg].n_items--;
244 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
248 SDDS_Bomb(
"Invalid -independentColumn syntax");
249 s_arg[i_arg].n_items++;
250 break;
251 case CLO_DEPENDENT_COLUMN:
252 if (s_arg[i_arg].n_items < 2)
253 SDDS_Bomb(
"Invalid -dependentColumn syntax.");
254 zColMatches = s_arg[i_arg].n_items - 1;
255 zColMatch =
tmalloc(
sizeof(*zColMatch) * zColMatches);
256 for (i = 0; i < zColMatches; i++)
257 zColMatch[i] = s_arg[i_arg].list[i + 1];
258 break;
259 case CLO_SCALE:
260 if (s_arg[i_arg].n_items != 2)
262 if ((scale =
match_string(s_arg[i_arg].list[1], scale_option, SCALE_OPTIONS, 0)) == -1) {
263 fprintf(stderr, "Invalid scale option - %s provided.\n", s_arg[i_arg].list[1]);
264 exit(EXIT_FAILURE);
265 }
266 spec->square = !scale;
267 spec->invariant = scale;
268 break;
269 case CLO_OUT_DIMENSION:
270 if (s_arg[i_arg].n_items != 3)
271 SDDS_Bomb(
"Invalid -outDimension syntax.");
272 s_arg[i_arg].n_items--;
273 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
274 "xdimension",
SDDS_LONG, &spec->nx, 1, 0,
275 "ydimension",
SDDS_LONG, &spec->ny, 1, 0, NULL))
276 SDDS_Bomb(
"Invalid -outDimension syntax");
277 s_arg[i_arg].n_items++;
278 if (spec->nx <= 0 || spec->nx > NMAX || spec->ny <= 0 || spec->ny > NMAX)
279 SDDS_Bomb(
"Invalid size for output grid.");
280 spec->generate_points = 1;
281 break;
282 case CLO_RANGE:
283 if (s_arg[i_arg].n_items < 2)
285 s_arg[i_arg].n_items--;
286 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
292 s_arg[i_arg].n_items++;
293 if (spec->xmin > spec->xmax || spec->ymin > spec->ymax ||
294 isnan(spec->xmin) || isnan(spec->xmax) || isnan(spec->ymin) || isnan(spec->ymax))
296 spec->range = 1;
297 break;
298 case CLO_ZOOM:
299 if (s_arg[i_arg].n_items != 2)
301 if (!
get_double(&spec->zoom, s_arg[i_arg].list[1]))
302 SDDS_Bomb(
"Invalid -zoom value provided.");
303 break;
304 case CLO_DIMENSION_THIN:
305 if (s_arg[i_arg].n_items != 3)
306 SDDS_Bomb(
"Invalid -dimensionThin syntax.");
307 s_arg[i_arg].n_items--;
308 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
309 "xdimension",
SDDS_LONG, &spec->nxd, 1, 0,
310 "ydimension",
SDDS_LONG, &spec->nyd, 1, 0, NULL))
311 SDDS_Bomb(
"Invalid -dimensionThin syntax");
312 s_arg[i_arg].n_items++;
313 spec->thin = 1;
314 break;
315 case CLO_CLUSTER_THIN:
316 if (s_arg[i_arg].n_items != 2)
317 SDDS_Bomb(
"Invalid -clusterThin syntax.");
318 if (!
get_double(&spec->rmax, s_arg[i_arg].list[1]))
319 SDDS_Bomb(
"Invalid -clusterThin value provided.");
320 spec->thin = 2;
321 break;
322 case CLO_PREPROCESS:
323 spec->nointerp = 1;
324 break;
325 case CLO_ALGORITHM:
326 if (s_arg[i_arg].n_items < 2)
328 if ((spec->method =
match_string(s_arg[i_arg].list[1], algorithm_option, ALGORITHMS, 0)) == -1) {
329 fprintf(stderr, "Invalid algorithm - %s provided, has to be nn or csa.\n", s_arg[i_arg].list[1]);
330 exit(EXIT_FAILURE);
331 }
332 dummyFlags = 0;
333 s_arg[i_arg].n_items -= 2;
334 if (!
scanItemList(&dummyFlags, s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
335 "linear", -1, NULL, 0, LINEAR_NN,
336 "sibson", -1, NULL, 0, SIBSON_NN,
337 "nonSibson", -1, NULL, 0, NONSIBSON_NN,
341 spec->linear = 0;
342 if (!dummyFlags || dummyFlags & LINEAR_NN) {
343 spec->linear = 1;
344 } else if (dummyFlags & SIBSON_NN) {
345 nn_rule = SIBSON;
346 } else if (dummyFlags & NONSIBSON_NN) {
347 nn_rule = NON_SIBSONIAN;
348 }
349 s_arg[i_arg].n_items += 2;
350 break;
351 case CLO_WEIGHT:
352 if (s_arg[i_arg].n_items != 2)
354 if (
match_string(s_arg[i_arg].list[1], INFINITY_OPTION, 1, 0) == 0)
355 spec->wmin = -DBL_MAX;
356 else {
357 if (!
get_double(&spec->wmin, s_arg[i_arg].list[1]))
358 SDDS_Bomb(
"Invalid weight value provided.");
359 }
360 break;
361 case CLO_VERTEX:
362 if (s_arg[i_arg].n_items != 2)
364 if (!
get_int(&nn_test_vertice, s_arg[i_arg].list[1]))
365 SDDS_Bomb(
"Invalid vertex value provided.");
366 nn_verbose = 1;
367 break;
368 case CLO_NPOINTS:
369 if (s_arg[i_arg].n_items != 2)
371 if (!
get_int(&spec->npoints, s_arg[i_arg].list[1]))
372 SDDS_Bomb(
"Invalid npoints value provided.");
373 break;
374 case CLO_VERBOSE:
375 nn_verbose = 2;
376 break;
377 case CLO_MERGE:
378 merge = 1;
379 break;
380 default:
381 fprintf(stderr, "Unknown option - %s provided.\n", s_arg[i_arg].list[0]);
382 exit(EXIT_FAILURE);
383 break;
384 }
385 } else {
386 if (!inputFile)
387 inputFile = s_arg[i_arg].list[0];
388 else if (!outputFile)
389 outputFile = s_arg[i_arg].list[0];
390 else
392 }
393 }
394
395 processFilenames(
"sdds2dinterpolate", &inputFile, &outputFile, pipeFlags, 0, NULL);
396 if (!spec->generate_points && !spec->nointerp && !pointsFile) {
397 fprintf(stderr, "No output grid specified.\n");
398 exit(EXIT_FAILURE);
399 }
400 if (spec->thin) {
401 if (spec->nxd == -1)
402 spec->nxd = spec->nx;
403 if (spec->nyd == -1)
404 spec->nyd = spec->ny;
405 if (spec->nxd <= 0 || spec->nyd <= 0) {
406 fprintf(stderr, "Invalid grid size for thinning.\n");
407 exit(EXIT_FAILURE);
408 }
409 }
410 if (spec->npoints == 1) {
411 if (spec->nx <= 0)
412 spec->npoints = 0;
413 else
414 spec->npoints = spec->nx * spec->ny;
415 }
416 ReadInputFile(inputFile, xCol, yCol, zColMatch, zColMatches, &zCol, &zCols, stdCol, &pages, &rows, &x, &y, &z, &std, &SDDS_in);
417 if (!spec->nointerp)
418 SetupOutputFile(&SDDS_out, &SDDS_in, outputFile, xCol, yCol, pointsFileXName, pointsFileYName,
419 zCol, zCols, columnMajorOrder);
422 if (pointsFile)
423 ReadPointFile(pointsFile, pointsFileXName ? pointsFileXName : xCol, pointsFileYName ? pointsFileYName : yCol,
424 &point_pages, &out_point);
425 pin =
tmalloc(
sizeof(*pin) * zCols);
426 if (merge) {
427 for (i = 0; i < pages; i++) {
428 if (!i) {
429 xmin = xmax = x[0][0];
430 ymin = ymax = y[0][0];
431 }
432 for (k = 0; k < zCols; k++)
433 pin[k] =
SDDS_Realloc(pin[k],
sizeof(**pin) * (nin + rows[i]));
434 if (std)
435 std_all =
SDDS_Realloc(std_all,
sizeof(*std_all) * (nin + rows[i]));
436 for (j = 0; j < rows[i]; j++) {
437 if (x[i][j] < xmin)
438 xmin = x[i][j];
439 else if (x[i][j] > xmax)
440 xmax = x[i][j];
441 if (y[i][j] < ymin)
442 ymin = y[i][j];
443 else if (y[i][j] > ymax)
444 ymax = y[i][j];
445 for (k = 0; k < zCols; k++) {
446 pin[k][nin + j].x = x[i][j];
447 pin[k][nin + j].y = y[i][j];
448 pin[k][nin + j].z = z[k][i][j];
449 }
450 if (std)
451 std_all[nin + j] = std[i][j];
452 }
453 nin += rows[i];
454 free(x[i]);
455 free(y[i]);
456 for (k = 0; k < zCols; k++) {
457 free(z[k][i]);
458 z[k][i] = NULL;
459 }
460 if (std && std[i]) {
461 free(std[i]);
462 std[i] = NULL;
463 }
464 x[i] = y[i] = NULL;
465 }
466 free(x);
467 free(y);
468 x = y = NULL;
469 for (k = 0; k < zCols; k++) {
470 free(z[k]);
471 z[k] = NULL;
472 }
473 free(z);
474 z = NULL;
475 if (std)
476 free(std);
477 std = NULL;
478 if (!spec->range) {
479 spec->xmin = xmin;
480 spec->ymin = ymin;
481 spec->xmax = xmax;
482 spec->ymax = ymax;
483 }
484 if (pointsFile) {
485 if (!interpolate_output_points(nin, pin, std_all, xCol, yCol, pointsFileXName, pointsFileYName,
486 zCol, zCols, spec, pages, out_point, &SDDS_out))
487 exit(EXIT_FAILURE);
488 writepage = 1;
489 } else {
490 for (k = 0; k < zCols; k++) {
491 if (spec->method == NN) {
492 do_nn_2d_interpolate(spec, &nin, &pin[k], &nout, &pout);
493 } else if (spec->method == CSA) {
494 do_csa_2d_interpolate(spec, nin, pin[k], &nout, &pout, std_all);
495 }
496 if (!spec->nointerp) {
497 if (!writepage) {
498 WriteOutputPage(&SDDS_out, pointsFileXName ? pointsFileXName : xCol,
499 pointsFileYName ? pointsFileYName : yCol,
500 zCol[k], spec, nout, pout, 0);
501 writepage = 1;
502 } else {
503 for (i = 0; i < nout; i++) {
505 zCol[k], pout[i].z, NULL))
507 }
508 }
509 }
510 }
513 }
514 } else {
515 for (i = 0; i < pages; i++) {
516 xmin = xmax = x[i][0];
517 ymin = ymax = y[i][0];
518 nin = rows[i];
519 for (j = 0; j < nin; j++) {
520 if (x[i][j] < xmin)
521 xmin = x[i][j];
522 else if (x[i][j] > xmax)
523 xmax = x[i][j];
524 if (y[i][j] < ymin)
525 ymin = y[i][j];
526 else if (y[i][j] > ymax)
527 ymax = y[i][j];
528 }
529 if (!spec->range) {
530 spec->xmin = xmin;
531 spec->ymin = ymin;
532 spec->xmax = xmax;
533 spec->ymax = ymax;
534 }
535 for (k = 0; k < zCols; k++) {
536 pin[k] = malloc(sizeof(**pin) * nin);
537 for (j = 0; j < rows[i]; j++) {
538 pin[k][j].x = x[i][j];
539 pin[k][j].y = y[i][j];
540 pin[k][j].z = z[k][i][j];
541 }
542 free(z[k][i]);
543 }
544 free(x[i]);
545 free(y[i]);
546 x[i] = y[i] = NULL;
547 if (std && std[i])
548 std_all = std[i];
549 else
550 std_all = NULL;
551 if (pointsFile) {
552 if (!interpolate_output_points(nin, pin, std_all, xCol, yCol, pointsFileXName, pointsFileYName,
553 zCol, zCols, spec, point_pages, out_point, &SDDS_out))
554 exit(EXIT_FAILURE);
555 writepage = 1;
556 } else {
557 for (k = 0; k < zCols; k++) {
558 if (spec->method == NN) {
559 do_nn_2d_interpolate(spec, &nin, &pin[k], &nout, &pout);
560 } else if (spec->method == CSA) {
561 do_csa_2d_interpolate(spec, nin, pin[k], &nout, &pout, std_all);
562 }
563 if (!spec->nointerp) {
564 if (!writepage) {
565 WriteOutputPage(&SDDS_out, pointsFileXName ? pointsFileXName : xCol,
566 pointsFileYName ? pointsFileYName : yCol,
567 zCol[k], spec, nout, pout, 0);
568 writepage = 1;
569 } else {
570 for (j = 0; j < nout; j++) {
572 zCol[k], pout[j].z, NULL))
574 }
575 }
576 }
577 }
578 if (std && std[i]) {
579 free(std[i]);
580 std[i] = NULL;
581 }
584 }
585 }
586 free(x);
587 free(y);
588 for (k = 0; k < zCols; k++)
589 free(z[k]);
590 free(z);
591 x = y = NULL;
592 }
593 if (std)
594 free(std);
595 for (k = 0; k < zCols; k++)
596 free(pin[k]);
597 free(pin);
600 if (point_pages && out_point) {
601 for (i = 0; i < point_pages; i++) {
602 free(out_point[i].pout);
603 }
604 free(out_point);
605 }
606 if (pout)
607 free(pout);
608 free(spec);
609 free(rows);
610 for (i = 0; i < zCols; i++)
611 free(zCol[i]);
612 free(zCol);
614 return EXIT_SUCCESS;
615}
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.