SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
sddsinterpset.c
Go to the documentation of this file.
1/**
2 * @file sddsinterpset.c
3 * @brief Perform multiple interpolations on SDDS data sets.
4 *
5 * @details
6 * This program reads an input SDDS file containing references to multiple data files.
7 * For each referenced data file, it performs interpolation based on specified parameters
8 * and writes the results to an output SDDS file. The interpolation behavior can be customized
9 * using various command-line options.
10 *
11 * @section Usage
12 * ```
13 * sddsinterpset [<input>] [<output>]
14 * [-pipe=[input][,output]]
15 * [-order=<number>]
16 * [-verbose]
17 * [-data=fileColumn=<colName>,interpolate=<colName>,functionof=<colName>,column=<colName> | atValue=<value>]
18 * [-majorOrder=row|column]
19 * [-belowRange={value=<value>|skip|saturate|extrapolate|wrap}[,{abort|warn}]]
20 * [-aboveRange={value=<value>|skip|saturate|extrapolate|wrap}[,{abort|warn}]]
21 * [-threads=<number>]
22 * ```
23 *
24 * @section Options
25 * | Option | Description |
26 * |---------------------|-----------------------------------------------------------------------------|
27 * | `-pipe` | Use standard SDDS Toolkit pipe options for input and output. |
28 * | `-order` | Specify the order of the polynomials used for interpolation. |
29 * | `-verbose` | Print detailed processing messages. |
30 * | `-data` | Define data interpolation parameters. |
31 * | `-majorOrder` | Specify data ordering for output: `row` or `column`. |
32 * | `-belowRange` | Define behavior for out-of-range points below data range. |
33 * | `-aboveRange` | Define behavior for out-of-range points above data range. |
34 * | `-threads` | Number of referenced data files to read concurrently. |
35 *
36 * @subsection Incompatibilities
37 * - The `column` and `atValue` options within `-data` are mutually exclusive; only one can be specified per invocation.
38 *
39 * @copyright
40 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
41 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
42 *
43 * @license
44 * This file is distributed under the terms of the Software License Agreement
45 * found in the file LICENSE included with this distribution.
46 *
47 * @authors
48 * H. Shang, R. Soliday, Xuesong Jiao, M. Borland
49 */
50
51#include "mdb.h"
52#include "SDDS.h"
53#include "scan.h"
54#include "SDDSutils.h"
55#include <ctype.h>
56
57/* Enumeration for option types */
58enum option_type {
59 CLO_ORDER,
60 CLO_PIPE,
61 CLO_BELOWRANGE,
62 CLO_ABOVERANGE,
63 CLO_DATA,
64 CLO_VERBOSE,
65 CLO_MAJOR_ORDER,
66 CLO_THREADS,
67 N_OPTIONS
68};
69
70char *option[N_OPTIONS] = {
71 "order",
72 "pipe",
73 "belowrange",
74 "aboverange",
75 "data",
76 "verbose",
77 "majorOrder",
78 "threads",
79};
80
81static const char *USAGE =
82 "Usage: sddsinterpset [<input>] [<output>] \n"
83 " [-pipe=[input][,output]] \n"
84 " [-order=<number>] \n"
85 " [-verbose] \n"
86 " [-data=fileColumn=<colName>,interpolate=<colName>,functionof=<colName>,\n"
87 " column=<colName> | atValue=<value>] \n"
88 " [-majorOrder=row|column] \n"
89 " [-belowRange={value=<value>|skip|saturate|extrapolate|wrap}[,{abort|warn}]] \n"
90 " [-aboveRange={value=<value>|skip|saturate|extrapolate|wrap}[,{abort|warn}]]\n"
91 " [-threads=<number>]\n\n"
92 "Options:\n"
93 " -verbose Print detailed processing messages.\n"
94 " -pipe Use standard SDDS Toolkit pipe options for input and output.\n"
95 " -order Specify the order of the polynomials used for interpolation.\n"
96 " Default is 1 (linear interpolation).\n"
97 " -data Define data interpolation parameters:\n"
98 " - fileColumn=<colName> : Column with data file names.\n"
99 " - interpolate=<colName> : Column to interpolate.\n"
100 " - functionof=<colName> : Independent variable column name.\n"
101 " - column=<colName> : Specify interpolation point as a column.\n"
102 " or\n"
103 " - atValue=<value> : Specify a fixed interpolation value.\n"
104 " -majorOrder Specify data ordering for output: 'row' or 'column'.\n"
105 " Default inherits from input file.\n"
106 " -belowRange Define behavior for interpolation points below data range:\n"
107 " Options: value=<value>, skip, saturate, extrapolate, wrap, abort, warn.\n"
108 " -aboveRange Define behavior for interpolation points above data range:\n"
109 " Options: value=<value>, skip, saturate, extrapolate, wrap, abort, warn.\n\n"
110 " -threads Number of referenced data files to read concurrently.\n"
111 " Default is 1.\n\n"
112 "Program by Hairong Shang. ("__DATE__
113 " "__TIME__
114 ", SVN revision: " SVN_VERSION ")\n";
115
116#define AT_COLUMN 0x00000001
117#define AT_VALUE 0x00000002
118
119typedef struct {
120 char *fileColumn;
121 char *interpCol;
122 char *funcOfCol;
123 char *atCol;
124 char **file;
125 int64_t files;
126 double atValue;
127 double *colValue;
128 unsigned long hasdata;
129 unsigned long flags;
131
132long checkMonotonicity(double *indepValue, int64_t rows);
133void freedatacontrol(DATA_CONTROL *data_control, long dataControls);
134static long interpolateDataFile(char *filename, DATA_CONTROL *control, double atValue,
135 OUTRANGE_CONTROL *belowRange, OUTRANGE_CONTROL *aboveRange,
136 long order, double *result, unsigned long *interpCode,
137 char *errorMessage, long errorMessageSize);
138
139int main(int argc, char **argv) {
140 int i_arg;
141 char *input = NULL, *output = NULL, **interpCol = NULL, **funcOf = NULL;
142 long order = 1, dataControls = 0, valid_option = 1;
143 //long verbose = 0;
144 SCANNED_ARG *s_arg;
145 OUTRANGE_CONTROL aboveRange, belowRange;
146 DATA_CONTROL *data_control = NULL;
147 unsigned long pipeFlags = 0, majorOrderFlag;
148 SDDS_DATASET SDDSdata, SDDSout, SDDSin;
149 double ***out_depenValue = NULL, atValue = 0;
150 int32_t **rowFlag = NULL;
151 long valid_data = 0, index, pages = 0;
152 int64_t *rows = NULL;
153 int64_t i, j, row;
154 short columnMajorOrder = -1;
155 int threads = 1;
156
158 argc = scanargs(&s_arg, argc, argv);
159 if (argc < 3) {
160 fprintf(stderr, "%s", USAGE);
161 exit(EXIT_FAILURE);
162 }
163
164 aboveRange.flags = belowRange.flags = OUTRANGE_SATURATE;
165
166 for (i_arg = 1; i_arg < argc; i_arg++) {
167 if (s_arg[i_arg].arg_type == OPTION) {
168 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
169 case CLO_MAJOR_ORDER:
170 majorOrderFlag = 0;
171 s_arg[i_arg].n_items--;
172 if (s_arg[i_arg].n_items > 0 &&
173 !scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
174 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
175 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)) {
176 SDDS_Bomb("invalid -majorOrder syntax/values");
177 }
178 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
179 columnMajorOrder = 1;
180 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
181 columnMajorOrder = 0;
182 break;
183 case CLO_THREADS:
184 if (s_arg[i_arg].n_items != 2 ||
185 sscanf(s_arg[i_arg].list[1], "%d", &threads) != 1 ||
186 threads < 1) {
187 SDDS_Bomb("invalid -threads syntax/value");
188 }
189 break;
190
191 case CLO_ORDER:
192 if (s_arg[i_arg].n_items != 2 ||
193 sscanf(s_arg[i_arg].list[1], "%ld", &order) != 1 ||
194 order < 1) {
195 SDDS_Bomb("invalid -order syntax/value");
196 }
197 break;
198
199 case CLO_PIPE:
200 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
201 SDDS_Bomb("invalid -pipe syntax");
202 }
203 break;
204
205 case CLO_ABOVERANGE:
206 s_arg[i_arg].n_items -= 1;
207 if (s_arg[i_arg].n_items < 1 ||
208 !scanItemList(&aboveRange.flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
209 "value", SDDS_DOUBLE, &aboveRange.value, 1, OUTRANGE_VALUE,
210 "skip", -1, NULL, 0, OUTRANGE_SKIP,
211 "saturate", -1, NULL, 0, OUTRANGE_SATURATE,
212 "extrapolate", -1, NULL, 0, OUTRANGE_EXTRAPOLATE,
213 "wrap", -1, NULL, 0, OUTRANGE_WRAP,
214 "abort", -1, NULL, 0, OUTRANGE_ABORT,
215 "warn", -1, NULL, 0, OUTRANGE_WARN, NULL)) {
216 SDDS_Bomb("invalid -aboveRange syntax/value");
217 }
218 if ((i = bitsSet(aboveRange.flags & (OUTRANGE_VALUE | OUTRANGE_SKIP | OUTRANGE_SATURATE |
219 OUTRANGE_EXTRAPOLATE | OUTRANGE_WRAP | OUTRANGE_ABORT))) > 1) {
220 SDDS_Bomb("incompatible keywords given for -aboveRange");
221 }
222 if (i != 1)
223 aboveRange.flags |= OUTRANGE_SATURATE;
224 break;
225
226 case CLO_VERBOSE:
227 //verbose = 1;
228 break;
229
230 case CLO_BELOWRANGE:
231 s_arg[i_arg].n_items -= 1;
232 if (s_arg[i_arg].n_items < 1 ||
233 !scanItemList(&belowRange.flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
234 "value", SDDS_DOUBLE, &belowRange.value, 1, OUTRANGE_VALUE,
235 "skip", -1, NULL, 0, OUTRANGE_SKIP,
236 "saturate", -1, NULL, 0, OUTRANGE_SATURATE,
237 "extrapolate", -1, NULL, 0, OUTRANGE_EXTRAPOLATE,
238 "wrap", -1, NULL, 0, OUTRANGE_WRAP,
239 "abort", -1, NULL, 0, OUTRANGE_ABORT,
240 "warn", -1, NULL, 0, OUTRANGE_WARN, NULL)) {
241 SDDS_Bomb("invalid -belowRange syntax/value");
242 }
243 if ((i = bitsSet(belowRange.flags & (OUTRANGE_VALUE | OUTRANGE_SKIP | OUTRANGE_SATURATE |
244 OUTRANGE_EXTRAPOLATE | OUTRANGE_WRAP | OUTRANGE_ABORT))) > 1) {
245 SDDS_Bomb("incompatible keywords given for -belowRange");
246 }
247 if (i != 1)
248 belowRange.flags |= OUTRANGE_SATURATE;
249 break;
250
251 case CLO_DATA:
252 s_arg[i_arg].n_items -= 1;
253 if (s_arg[i_arg].n_items < 4) {
254 SDDS_Bomb("invalid -data syntax");
255 }
256 data_control = SDDS_Realloc(data_control, sizeof(*data_control) * (dataControls + 1));
257 data_control[dataControls].fileColumn = data_control[dataControls].interpCol =
258 data_control[dataControls].funcOfCol = data_control[dataControls].atCol = NULL;
259 data_control[dataControls].file = NULL;
260 data_control[dataControls].files = 0;
261 data_control[dataControls].hasdata = 0;
262 data_control[dataControls].colValue = NULL;
263 data_control[dataControls].flags = 0;
264
265 if (!scanItemList(&data_control[dataControls].flags, s_arg[i_arg].list + 1,
266 &s_arg[i_arg].n_items, 0,
267 "fileColumn", SDDS_STRING, &(data_control[dataControls].fileColumn), 1, 0,
268 "interpolate", SDDS_STRING, &(data_control[dataControls].interpCol), 1, 0,
269 "functionof", SDDS_STRING, &(data_control[dataControls].funcOfCol), 1, 0,
270 "column", SDDS_STRING, &(data_control[dataControls].atCol), 1, AT_COLUMN,
271 "atValue", SDDS_DOUBLE, &(data_control[dataControls].atValue), 1, AT_VALUE, NULL) ||
272 !data_control[dataControls].fileColumn ||
273 !data_control[dataControls].interpCol ||
274 !data_control[dataControls].funcOfCol) {
275 SDDS_Bomb("Invalid -data syntax");
276 }
277
278 if (!(data_control[dataControls].flags & AT_COLUMN) &&
279 !(data_control[dataControls].flags & AT_VALUE)) {
280 SDDS_Bomb("Invalid -data syntax: either column or atValue option should be given.");
281 }
282
283 if ((data_control[dataControls].flags & AT_COLUMN) &&
284 (data_control[dataControls].flags & AT_VALUE)) {
285 SDDS_Bomb("Invalid -data syntax: column and atValue options are not compatible.");
286 }
287
288 valid_option = 1;
289 if (dataControls) {
290 if (match_string(data_control[dataControls].funcOfCol, funcOf, dataControls, EXACT_MATCH) > 0) {
291 fprintf(stderr, "Multiple independent columns provided!\n");
292 exit(EXIT_FAILURE);
293 }
294 if (match_string(data_control[dataControls].interpCol, interpCol, dataControls, EXACT_MATCH) > 0) {
295 fprintf(stderr, "Warning: Interpolate column '%s' has been used.\n", data_control[dataControls].interpCol);
296 valid_option = 0;
297 }
298 }
299
300 if (valid_option) {
301 interpCol = SDDS_Realloc(interpCol, sizeof(*interpCol) * (dataControls + 1));
302 funcOf = SDDS_Realloc(funcOf, sizeof(*funcOf) * (dataControls + 1));
303 interpCol[dataControls] = data_control[dataControls].interpCol;
304 funcOf[dataControls] = data_control[dataControls].funcOfCol;
305 dataControls++;
306 }
307 break;
308
309 default:
310 fprintf(stderr, "Error: Unknown or ambiguous option '%s'\n", s_arg[i_arg].list[0]);
311 exit(EXIT_FAILURE);
312 break;
313 }
314 } else {
315 if (!input)
316 input = s_arg[i_arg].list[0];
317 else if (!output)
318 output = s_arg[i_arg].list[0];
319 else
320 SDDS_Bomb("Too many filenames provided.");
321 }
322 }
323
324 processFilenames("sddsinterpset", &input, &output, pipeFlags, 0, NULL);
325
326 if (!SDDS_InitializeInput(&SDDSin, input))
327 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
328
329 for (i = 0; i < dataControls; i++) {
330 if ((index = SDDS_GetColumnIndex(&SDDSin, data_control[i].fileColumn)) < 0) {
331 fprintf(stderr, "Warning: Column '%s' does not exist in input file '%s'.\n",
332 data_control[i].fileColumn, input);
333 continue;
334 }
335 if (SDDS_GetColumnType(&SDDSin, index) != SDDS_STRING) {
336 fprintf(stderr, "Error: Column '%s' in input file '%s' is not a string column.\n",
337 data_control[i].fileColumn, input);
338 continue;
339 }
340 if (data_control[i].atCol) {
341 if ((index = SDDS_GetColumnIndex(&SDDSin, data_control[i].atCol)) < 0) {
342 fprintf(stderr, "Warning: Column '%s' does not exist in input file '%s'.\n",
343 data_control[i].atCol, input);
344 continue;
345 }
346 if (!SDDS_NUMERIC_TYPE(SDDS_GetColumnType(&SDDSin, index))) {
347 fprintf(stderr, "Error: Column '%s' in input file '%s' is not a numeric column.\n",
348 data_control[i].atCol, input);
349 continue;
350 }
351 }
352 data_control[i].hasdata = 1;
353 valid_data++;
354 }
355
356 if (!valid_data) {
357 fprintf(stderr, "Error: No valid -data options provided for processing.\n");
358 exit(EXIT_FAILURE);
359 }
360
361 if (!SDDS_InitializeCopy(&SDDSout, &SDDSin, output, "w"))
362 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
363
364 if (columnMajorOrder != -1)
365 SDDSout.layout.data_mode.column_major = columnMajorOrder;
366 else
367 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
368
369 while (SDDS_ReadPage(&SDDSin) > 0) {
370 rows = SDDS_Realloc(rows, sizeof(*rows) * (pages + 1));
371 out_depenValue = SDDS_Realloc(out_depenValue, sizeof(*out_depenValue) * (pages + 1));
372 rowFlag = SDDS_Realloc(rowFlag, sizeof(*rowFlag) * (pages + 1));
373
374 if (!(rows[pages] = SDDS_CountRowsOfInterest(&SDDSin))) {
375 fprintf(stderr, "Error: No data found in input file '%s'.\n", input);
376 exit(EXIT_FAILURE);
377 }
378
379 rowFlag[pages] = (int32_t *)malloc(sizeof(**rowFlag) * rows[pages]);
380 out_depenValue[pages] = calloc(dataControls, sizeof(*out_depenValue[pages]));
381 if (!out_depenValue[pages])
382 SDDS_Bomb("memory allocation failure");
383
384 for (i = 0; i < rows[pages]; i++)
385 rowFlag[pages][i] = 1;
386
387 for (i = 0; i < dataControls; i++) {
388 if (data_control[i].hasdata) {
389 unsigned long *interpCodeRow = NULL;
390 char errorMessage[1024];
391 int failed = 0;
392
393 out_depenValue[pages][i] = malloc(sizeof(*out_depenValue[pages][i]) * rows[pages]);
394 if (!out_depenValue[pages][i])
395 SDDS_Bomb("memory allocation failure");
396
397 data_control[i].files = rows[pages];
398 if (!(data_control[i].file = (char **)SDDS_GetColumn(&SDDSin, data_control[i].fileColumn))) {
399 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
400 }
401
402 if (data_control[i].atCol) {
403 if (!(data_control[i].colValue = SDDS_GetColumnInDoubles(&SDDSin, data_control[i].atCol))) {
404 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
405 }
406 }
407
408 if (!data_control[i].atCol)
409 atValue = data_control[i].atValue;
410
411 if (!pages) {
412 j = rows[pages] - 1;
413 if (!SDDS_InitializeInput(&SDDSdata, data_control[i].file[j]))
414 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
415
416 switch (SDDS_CheckColumn(&SDDSdata, data_control[i].interpCol, NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) {
417 case SDDS_CHECK_OKAY:
418 if (!SDDS_TransferColumnDefinition(&SDDSout, &SDDSdata, data_control[i].interpCol, data_control[i].interpCol))
419 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
420 break;
421 default:
422 fprintf(stderr, "Error: Column '%s' missing or invalid in file '%s'.\n",
423 data_control[i].interpCol, data_control[i].file[j]);
424 exit(EXIT_FAILURE);
425 break;
426 }
427
428 switch (SDDS_CheckColumn(&SDDSdata, data_control[i].funcOfCol, NULL, SDDS_ANY_NUMERIC_TYPE, NULL)) {
429 case SDDS_CHECK_OKAY:
430 if (!(data_control[i].atCol) &&
431 !SDDS_TransferColumnDefinition(&SDDSout, &SDDSdata, data_control[i].funcOfCol, data_control[i].funcOfCol))
432 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
433 break;
434 default:
435 fprintf(stderr, "Error: Column '%s' missing or invalid in file '%s'.\n",
436 data_control[i].funcOfCol, data_control[i].file[j]);
437 exit(EXIT_FAILURE);
438 break;
439 }
440
441 if (!SDDS_Terminate(&SDDSdata))
442 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
443 }
444
445 interpCodeRow = calloc(rows[pages], sizeof(*interpCodeRow));
446 if (!interpCodeRow)
447 SDDS_Bomb("memory allocation failure");
448 errorMessage[0] = 0;
449
450#pragma omp parallel for if (threads > 1 && rows[pages] > 1) num_threads(threads) schedule(dynamic)
451 for (j = 0; j < rows[pages]; j++) {
452 double localAtValue, localResult;
453 unsigned long localInterpCode;
454 char localError[1024];
455 localAtValue = data_control[i].atCol ? data_control[i].colValue[j] : atValue;
456 localResult = 0;
457 localInterpCode = 0;
458 localError[0] = 0;
459
460 if (!interpolateDataFile(data_control[i].file[j], &data_control[i], localAtValue,
461 &belowRange, &aboveRange, order, &localResult, &localInterpCode,
462 localError, sizeof(localError))) {
463#pragma omp critical
464 {
465 if (!failed) {
466 failed = 1;
467 snprintf(errorMessage, sizeof(errorMessage), "%s", localError);
468 }
469 }
470 } else {
471 out_depenValue[pages][i][j] = localResult;
472 interpCodeRow[j] = localInterpCode;
473 if (localInterpCode & OUTRANGE_SKIP)
474 rowFlag[pages][j] = 0;
475 }
476 }
477
478 if (failed) {
479 fprintf(stderr, "%s\n", errorMessage);
480 exit(EXIT_FAILURE);
481 }
482
483 for (j = 0; j < rows[pages]; j++) {
484 if (interpCodeRow[j] & OUTRANGE_ABORT) {
485 fprintf(stderr, "Error: Value %e out of range for column '%s'.\n",
486 data_control[i].atCol ? data_control[i].colValue[j] : atValue, data_control[i].interpCol);
487 exit(EXIT_FAILURE);
488 }
489 if (interpCodeRow[j] & OUTRANGE_WARN)
490 fprintf(stderr, "Warning: Value %e out of range for column '%s'.\n",
491 data_control[i].atCol ? data_control[i].colValue[j] : atValue, data_control[i].interpCol);
492 }
493 free(interpCodeRow);
494 }
495
496 for (j = 0; j < data_control[i].files; j++)
497 free(data_control[i].file[j]);
498 free(data_control[i].file);
499 data_control[i].file = NULL;
500
501 if (data_control[i].colValue) {
502 free(data_control[i].colValue);
503 data_control[i].colValue = NULL;
504 }
505 }
506
507 if (!pages) {
508 if (!SDDS_WriteLayout(&SDDSout))
509 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
510 }
511
512 if (!SDDS_StartTable(&SDDSout, rows[pages]))
513 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
514
515 if (!SDDS_CopyColumns(&SDDSout, &SDDSin))
516 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
517
518 if (!SDDS_CopyParameters(&SDDSout, &SDDSin))
519 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
520
521 for (i = 0; i < dataControls; i++) {
522 if (data_control[i].hasdata) {
523 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, out_depenValue[pages][i],
524 rows[pages], data_control[i].interpCol)) {
525 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
526 }
527 if (!(data_control[i].atCol)) {
528 for (row = 0; row < rows[pages]; row++) {
529 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, row,
530 data_control[i].funcOfCol, data_control[i].atValue, NULL)) {
531 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
532 }
533 }
534 }
535 }
536 }
537
538 if (!SDDS_AssertRowFlags(&SDDSout, SDDS_FLAG_ARRAY, rowFlag[pages], rows[pages]))
539 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
540
541 if (!SDDS_WritePage(&SDDSout))
542 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
543
544 pages++;
545 }
546
547 if (!SDDS_Terminate(&SDDSin))
548 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
549
550 if (!SDDS_Terminate(&SDDSout)) {
551 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
552 exit(EXIT_FAILURE);
553 }
554
555 freedatacontrol(data_control, dataControls);
556
557 if (out_depenValue) {
558 for (i = 0; i < pages; i++) {
559 for (j = 0; j < dataControls; j++)
560 free(out_depenValue[i][j]);
561 free(out_depenValue[i]);
562 free(rowFlag[i]);
563 }
564 free(out_depenValue);
565 free(rowFlag);
566 }
567
568 if (interpCol)
569 free(interpCol);
570 if (funcOf)
571 free(funcOf);
572 if (rows)
573 free(rows);
574
575 free_scanargs(&s_arg, argc);
576 return EXIT_SUCCESS;
577}
578
579static long interpolateDataFile(char *filename, DATA_CONTROL *control, double atValue,
580 OUTRANGE_CONTROL *belowRange, OUTRANGE_CONTROL *aboveRange,
581 long order, double *result, unsigned long *interpCode,
582 char *errorMessage, long errorMessageSize) {
583 SDDS_DATASET SDDSdata;
584 double *indepValue = NULL, *depenValue = NULL;
585 int64_t datarows;
586 long monotonicity;
587 int initialized = 0;
588
589 if (!SDDS_InitializeInput(&SDDSdata, filename)) {
590 snprintf(errorMessage, errorMessageSize, "Error: unable to open input data file '%s'.", filename);
591 return 0;
592 }
593 initialized = 1;
594
595 if (SDDS_CheckColumn(&SDDSdata, control->interpCol, NULL, SDDS_ANY_NUMERIC_TYPE, NULL) != SDDS_CHECK_OKAY) {
596 snprintf(errorMessage, errorMessageSize, "Error: Column '%s' missing or invalid in file '%s'.",
597 control->interpCol, filename);
598 SDDS_Terminate(&SDDSdata);
599 return 0;
600 }
601 if (SDDS_CheckColumn(&SDDSdata, control->funcOfCol, NULL, SDDS_ANY_NUMERIC_TYPE, NULL) != SDDS_CHECK_OKAY) {
602 snprintf(errorMessage, errorMessageSize, "Error: Column '%s' missing or invalid in file '%s'.",
603 control->funcOfCol, filename);
604 SDDS_Terminate(&SDDSdata);
605 return 0;
606 }
607 if (SDDS_ReadPage(&SDDSdata) <= 0) {
608 snprintf(errorMessage, errorMessageSize, "Error: unable to read data page from file '%s'.", filename);
609 SDDS_Terminate(&SDDSdata);
610 return 0;
611 }
612 datarows = SDDS_CountRowsOfInterest(&SDDSdata);
613 if (datarows <= 0) {
614 snprintf(errorMessage, errorMessageSize, "Error: No data found in file '%s'.", filename);
615 SDDS_Terminate(&SDDSdata);
616 return 0;
617 }
618 if (!(indepValue = SDDS_GetColumnInDoubles(&SDDSdata, control->funcOfCol))) {
619 snprintf(errorMessage, errorMessageSize, "Error: problem getting column '%s' from file '%s'.",
620 control->funcOfCol, filename);
621 SDDS_Terminate(&SDDSdata);
622 return 0;
623 }
624 if (!(depenValue = SDDS_GetColumnInDoubles(&SDDSdata, control->interpCol))) {
625 snprintf(errorMessage, errorMessageSize, "Error: problem getting column '%s' from file '%s'.",
626 control->interpCol, filename);
627 free(indepValue);
628 SDDS_Terminate(&SDDSdata);
629 return 0;
630 }
631 if (initialized && !SDDS_Terminate(&SDDSdata)) {
632 snprintf(errorMessage, errorMessageSize, "Error: problem closing data file '%s'.", filename);
633 free(indepValue);
634 free(depenValue);
635 return 0;
636 }
637 initialized = 0;
638
639 if (!(monotonicity = checkMonotonicity(indepValue, datarows))) {
640 snprintf(errorMessage, errorMessageSize, "Error: Independent (%s) data in file '%s' is not monotonic.",
641 control->funcOfCol, filename);
642 free(indepValue);
643 free(depenValue);
644 return 0;
645 }
646
647 *result = interpolate(depenValue, indepValue, datarows, atValue,
648 belowRange, aboveRange, order, interpCode, monotonicity);
649 free(depenValue);
650 free(indepValue);
651 return 1;
652}
653
654long checkMonotonicity(double *indepValue, int64_t rows) {
655 if (rows == 1)
656 return 1;
657
658 if (indepValue[rows - 1] > indepValue[0]) {
659 while (--rows > 0)
660 if (indepValue[rows] < indepValue[rows - 1])
661 return 0;
662 return 1;
663 } else {
664 while (--rows > 0)
665 if (indepValue[rows] > indepValue[rows - 1])
666 return 0;
667 return -1;
668 }
669}
670
671void freedatacontrol(DATA_CONTROL *data_control, long dataControls) {
672 long i;
673 for (i = 0; i < dataControls; i++) {
674 free(data_control[i].interpCol);
675 free(data_control[i].funcOfCol);
676 free(data_control[i].fileColumn);
677 if (data_control[i].atCol)
678 free(data_control[i].atCol);
679 }
680 free(data_control);
681}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyColumns(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:387
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
int32_t SDDS_AssertRowFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode,...)
Sets acceptance flags for rows based on specified criteria.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:50
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:474
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:743
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
Definition SDDStypes.h:157
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
Utility functions for SDDS dataset manipulation and string array operations.
long bitsSet(unsigned long data)
Counts the number of set bits (1s) in the given data.
Definition binary.c:52
double interpolate(double *f, double *x, int64_t n, double xo, OUTRANGE_CONTROL *belowRange, OUTRANGE_CONTROL *aboveRange, long order, unsigned long *returnCode, long M)
Performs interpolation with range control options.
Definition interp.c:160
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)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:357
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:391
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:588
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.