SDDSlib
Loading...
Searching...
No Matches
sddsinterp.c
Go to the documentation of this file.
1/**
2 * @file sddsinterp.c
3 * @brief SDDS-format interpolation program
4 *
5 * This program performs interpolation on SDDS (Self Describing Data Set) formatted data.
6 * It supports various interpolation methods, handles range conditions, and allows
7 * customization of output through multiple command-line options.
8 *
9 * @section Usage
10 *
11 * The `sddsinterp` program interpolates data from an input SDDS file and writes the
12 * interpolated data to an output SDDS file. It offers several methods for specifying
13 * interpolation points and provides options to control the interpolation behavior.
14 *
15 * **Basic Syntax:**
16 * ```
17 * sddsinterp [<inputfile>] [<outputfile>] [options]
18 * ```
19 *
20 * @section Options
21 *
22 * The following options are available to customize the interpolation process:
23 *
24 * -pipe=[input][,output]
25 * -columns=<independent>,<dependent1>[,...]
26 * -exclude=<name>[,...]
27 * -atValues=<values-list>
28 * -sequence=<points>[,<start>,<end>]
29 * -equispaced=<spacing>[,<start>,<end>]
30 * -fillIn
31 * -fileValues=<valuesfile>[,column=<name>][,parallelPages]
32 * -interpShort=-1|-2
33 * -order=<number>
34 * -printout[=bare][,stdout]
35 * -forceMonotonic[={increasing|decreasing}]
36 * -belowRange={value=<v>|skip|saturate|extrapolate|wrap}[,{abort|warn}]
37 * -aboveRange={value=<v>|skip|saturate|extrapolate|wrap}[,{abort|warn}]
38 * -majorOrder=row|column
39 *
40 * @copyright
41 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
42 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
43 *
44 * @license
45 * This file is distributed under the terms of the Software License Agreement
46 * found in the file LICENSE included with this distribution.
47 *
48 * @author M. Borland, C. Saunders, R. Soliday, H. Shang
49 */
50
51#include "mdb.h"
52#include "SDDS.h"
53#include "scan.h"
54#include "SDDSutils.h"
55
56/* Enumeration for option types */
57enum option_type {
58 CLO_ORDER,
59 CLO_ATVALUES,
60 CLO_SEQUENCE,
61 CLO_COLUMNS,
62 CLO_PRINTOUT,
63 CLO_FILEVALUES,
64 CLO_COMBINEDUPLICATES,
65 CLO_BRANCH,
66 CLO_BELOWRANGE,
67 CLO_ABOVERANGE,
68 CLO_PIPE,
69 CLO_EXCLUDE,
70 CLO_FORCEMONOTONIC,
71 CLO_FILLIN,
72 CLO_EQUISPACED,
73 CLO_INTERP_SHORT,
74 CLO_MAJOR_ORDER,
75 N_OPTIONS
76};
77
78char *option[N_OPTIONS] = {
79 "order",
80 "atvalues",
81 "sequence",
82 "columns",
83 "printout",
84 "filevalues",
85 "combineduplicates",
86 "branch",
87 "belowrange",
88 "aboverange",
89 "pipe",
90 "exclude",
91 "forcemonotonic",
92 "fillin",
93 "equispaced",
94 "interpShort",
95 "majorOrder",
96};
97
98static char *USAGE =
99 "Usage: sddsinterp [<inputfile>] [<outputfile>]\n"
100 " Options:\n"
101 " -pipe=[input][,output] Use pipe for input and/or output.\n"
102 " -columns=<independent>,<dependent1>[,...] Specify the independent and dependent columns.\n"
103 " -exclude=<name>[,...] Exclude specified columns from processing.\n"
104 " -atValues=<values-list> Interpolate at the specified list of values.\n"
105 " -sequence=<points>[,<start>,<end>] Generate a sequence of interpolation points.\n"
106 " -equispaced=<spacing>[,<start>,<end>] Generate equispaced interpolation points.\n"
107 " -fillIn Automatically fill in interpolation points based on data.\n"
108 " -fileValues=<valuesfile>[,column=<name>][,parallelPages]\n"
109 " Use values from a file for interpolation.\n"
110 " -interpShort=-1|-2 Interpolate short columns with order -1 or -2.\n"
111 " Order -1 inherits value from the previous point;\n"
112 " Order -2 inherits value from the next point.\n"
113 " -order=<number> Set the interpolation order (default is 1).\n"
114 " -printout[=bare][,stdout] Output interpolated data in bare format and/or to stdout.\n"
115 " -forceMonotonic[={increasing|decreasing}] Enforce monotonicity in the data.\n"
116 " -belowRange={value=<v>|skip|saturate|extrapolate|wrap}[,{abort|warn}]\n"
117 " Handle values below the interpolation range.\n"
118 " -aboveRange={value=<v>|skip|saturate|extrapolate|wrap}[,{abort|warn}]\n"
119 " Handle values above the interpolation range.\n"
120 " -majorOrder=row|column Set the major order of data storage.\n\n"
121 " Example:\n"
122 " sddsinterp input.sdds output.sdds -columns=energy,flux -atValues=1.0,2.0,3.0\n\n"
123 " Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
124
125double *makeSequence(int64_t *points, double start, double end, double spacing, double *data, int64_t dataRows);
126double *makeFillInSequence(double *x, int64_t dataRows, int64_t *nPointsReturn);
127long checkMonotonicity(double *indepValue, int64_t rows);
128int64_t forceMonotonicity(double *indepValue, double **y, long columns, int64_t rows, unsigned long direction);
129int64_t combineDuplicatePoints(double *x, double **y, long columns, int64_t rows, double tolerance);
130
131#define FILEVALUES_PARALLEL_PAGES 0x0001U
132
133#define NORMAL_PRINTOUT 1
134#define BARE_PRINTOUT 2
135#define STDOUT_PRINTOUT 4
136
137#define FORCE_MONOTONIC 0x0001U
138#define FORCE_INCREASING 0x0002U
139#define FORCE_DECREASING 0x0004U
140
141int main(int argc, char **argv) {
142 int iArg;
143 char *indepQuantity, **depenQuantity, *fileValuesQuantity, *fileValuesFile, **exclude;
144 long depenQuantities, monotonicity, excludes;
145 char *input, *output;
146 long i, readCode, order, valuesReadCode, fillIn;
147 int64_t rows, row, interpPoints, j;
148 long sequencePoints, combineDuplicates, branch;
149 int32_t *rowFlag;
150 double sequenceStart, sequenceEnd;
151 double sequenceSpacing;
152 unsigned long flags, interpCode, printFlags, forceMonotonic;
153 SCANNED_ARG *scanned;
154 SDDS_DATASET SDDSin, SDDSout, SDDSvalues;
155 OUTRANGE_CONTROL aboveRange, belowRange;
156 double *atValue;
157 long atValues, doNotRead, parallelPages;
158 double *indepValue, **depenValue, *interpPoint, **outputData;
159 unsigned long pipeFlags, majorOrderFlag;
160 FILE *fpPrint;
161 short interpShort = 0, interpShortOrder = -1, *shortValue = NULL, columnMajorOrder = -1;
162 long nextPos;
163
165 argc = scanargs(&scanned, argc, argv);
166 if (argc < 3 || argc > (3 + N_OPTIONS))
167 bomb(NULL, USAGE);
168
169 atValue = NULL;
170 atValues = fillIn = 0;
171 output = input = NULL;
172 combineDuplicates = branch = sequencePoints = parallelPages = 0;
173 indepQuantity = NULL;
174 depenQuantity = exclude = NULL;
175 depenQuantities = excludes = 0;
176 aboveRange.flags = belowRange.flags = OUTRANGE_SATURATE;
177 order = 1;
178 readCode = interpPoints = 0;
179 fileValuesFile = fileValuesQuantity = NULL;
180 sequenceStart = sequenceEnd = sequenceSpacing = 0;
181 printFlags = pipeFlags = 0;
182 forceMonotonic = 0;
183 indepValue = interpPoint = NULL;
184 depenValue = outputData = NULL;
185
186 for (iArg = 1; iArg < argc; iArg++) {
187 if (scanned[iArg].arg_type == OPTION) {
188 /* process options here */
189 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
190 case CLO_MAJOR_ORDER:
191 majorOrderFlag = 0;
192 scanned[iArg].n_items--;
193 if (scanned[iArg].n_items > 0 &&
194 (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
195 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
196 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
197 SDDS_Bomb("invalid -majorOrder syntax/values");
198 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
199 columnMajorOrder = 1;
200 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
201 columnMajorOrder = 0;
202 break;
203 case CLO_ORDER:
204 if (scanned[iArg].n_items != 2 ||
205 sscanf(scanned[iArg].list[1], "%ld", &order) != 1 || order < 0)
206 SDDS_Bomb("invalid -order syntax/value");
207 break;
208 case CLO_ATVALUES:
209 if (scanned[iArg].n_items < 2)
210 SDDS_Bomb("invalid -atValues syntax");
211 if (atValue)
212 SDDS_Bomb("give -atValues only once");
213 atValue = tmalloc(sizeof(*atValue) * (atValues = scanned[iArg].n_items - 1));
214 for (i = 0; i < atValues; i++)
215 if (sscanf(scanned[iArg].list[i + 1], "%lf", &atValue[i]) != 1)
216 SDDS_Bomb("invalid -atValues value");
217 break;
218 case CLO_INTERP_SHORT:
219 if (scanned[iArg].n_items == 2) {
220 if (sscanf(scanned[iArg].list[1], "%hd", &interpShortOrder) != 1 ||
221 (interpShortOrder != -1 && interpShortOrder != -2))
222 SDDS_Bomb("invalid -interpShort value; must be -1 or -2");
223 }
224 interpShort = 1;
225 break;
226 case CLO_SEQUENCE:
227 if ((scanned[iArg].n_items != 2 && scanned[iArg].n_items != 4) ||
228 sscanf(scanned[iArg].list[1], "%ld", &sequencePoints) != 1 ||
229 sequencePoints < 2)
230 SDDS_Bomb("invalid -sequence syntax/value");
231 if (scanned[iArg].n_items == 4 &&
232 (sscanf(scanned[iArg].list[2], "%lf", &sequenceStart) != 1 ||
233 sscanf(scanned[iArg].list[3], "%lf", &sequenceEnd) != 1))
234 SDDS_Bomb("invalid -sequence syntax/value");
235 if (sequenceSpacing)
236 SDDS_Bomb("give only one of -sequence and -equispaced");
237 break;
238 case CLO_EQUISPACED:
239 if ((scanned[iArg].n_items != 2 && scanned[iArg].n_items != 4) ||
240 sscanf(scanned[iArg].list[1], "%lf", &sequenceSpacing) != 1 ||
241 sequenceSpacing <= 0)
242 SDDS_Bomb("invalid -equispaced syntax/value");
243 if (scanned[iArg].n_items == 4 &&
244 (sscanf(scanned[iArg].list[2], "%lf", &sequenceStart) != 1 ||
245 sscanf(scanned[iArg].list[3], "%lf", &sequenceEnd) != 1))
246 SDDS_Bomb("invalid -equispaced syntax/values");
247 if (sequencePoints)
248 SDDS_Bomb("give only one of -sequence and -equispaced");
249 break;
250 case CLO_COLUMNS:
251 if (indepQuantity)
252 SDDS_Bomb("only one -columns option may be given");
253 if (scanned[iArg].n_items < 2)
254 SDDS_Bomb("invalid -columns syntax");
255 indepQuantity = scanned[iArg].list[1];
256 if (scanned[iArg].n_items >= 2) {
257 depenQuantity = tmalloc(sizeof(*depenQuantity) * (depenQuantities = scanned[iArg].n_items - 2));
258 for (i = 0; i < depenQuantities; i++)
259 depenQuantity[i] = scanned[iArg].list[i + 2];
260 }
261 break;
262 case CLO_PRINTOUT:
263 if ((scanned[iArg].n_items -= 1) >= 1) {
264 if (!scanItemList(&printFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
265 "bare", -1, NULL, 0, BARE_PRINTOUT,
266 "stdout", -1, NULL, 0, STDOUT_PRINTOUT, NULL))
267 SDDS_Bomb("invalid -printout syntax");
268 }
269 if (!(printFlags & BARE_PRINTOUT))
270 printFlags |= NORMAL_PRINTOUT;
271 break;
272 case CLO_FILEVALUES:
273 if (scanned[iArg].n_items < 2)
274 SDDS_Bomb("invalid -fileValues syntax");
275 fileValuesFile = scanned[iArg].list[1];
276 scanned[iArg].n_items -= 2;
277 if (!scanItemList(&flags, scanned[iArg].list + 2, &scanned[iArg].n_items, 0,
278 "column", SDDS_STRING, &fileValuesQuantity, 1, 0,
279 "parallelpages", -1, NULL, 0, FILEVALUES_PARALLEL_PAGES, NULL))
280 SDDS_Bomb("invalid -fileValues syntax");
281 if (flags & FILEVALUES_PARALLEL_PAGES)
282 parallelPages = 1;
283 break;
284 case CLO_COMBINEDUPLICATES:
285 SDDS_Bomb("-combineDuplicates option not implemented yet--send email to borland@aps.anl.gov");
286 combineDuplicates = 1;
287 break;
288 case CLO_BRANCH:
289 SDDS_Bomb("-branch option not implemented yet--send email to borland@aps.anl.gov");
290 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%ld", &branch) != 1 || branch < 1)
291 SDDS_Bomb("invalid -branch syntax/value");
292 break;
293 case CLO_BELOWRANGE:
294 if ((scanned[iArg].n_items -= 1) < 1 ||
295 !scanItemList(&belowRange.flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
296 "value", SDDS_DOUBLE, &belowRange.value, 1, OUTRANGE_VALUE,
297 "skip", -1, NULL, 0, OUTRANGE_SKIP,
298 "saturate", -1, NULL, 0, OUTRANGE_SATURATE,
299 "extrapolate", -1, NULL, 0, OUTRANGE_EXTRAPOLATE,
300 "wrap", -1, NULL, 0, OUTRANGE_WRAP,
301 "abort", -1, NULL, 0, OUTRANGE_ABORT,
302 "warn", -1, NULL, 0, OUTRANGE_WARN, NULL))
303 SDDS_Bomb("invalid -belowRange syntax/value");
304 if ((i = bitsSet(belowRange.flags & (OUTRANGE_VALUE | OUTRANGE_SKIP | OUTRANGE_SATURATE | OUTRANGE_EXTRAPOLATE | OUTRANGE_WRAP | OUTRANGE_ABORT))) > 1)
305 SDDS_Bomb("incompatible keywords given for -belowRange");
306 if (i != 1)
307 belowRange.flags |= OUTRANGE_SATURATE;
308 break;
309 case CLO_ABOVERANGE:
310 if ((scanned[iArg].n_items -= 1) < 1 ||
311 !scanItemList(&aboveRange.flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
312 "value", SDDS_DOUBLE, &aboveRange.value, 1, OUTRANGE_VALUE,
313 "skip", -1, NULL, 0, OUTRANGE_SKIP,
314 "saturate", -1, NULL, 0, OUTRANGE_SATURATE,
315 "extrapolate", -1, NULL, 0, OUTRANGE_EXTRAPOLATE,
316 "wrap", -1, NULL, 0, OUTRANGE_WRAP,
317 "abort", -1, NULL, 0, OUTRANGE_ABORT,
318 "warn", -1, NULL, 0, OUTRANGE_WARN, NULL))
319 SDDS_Bomb("invalid -aboveRange syntax/value");
320 if ((i = bitsSet(aboveRange.flags & (OUTRANGE_VALUE | OUTRANGE_SKIP | OUTRANGE_SATURATE | OUTRANGE_EXTRAPOLATE | OUTRANGE_WRAP | OUTRANGE_ABORT))) > 1)
321 SDDS_Bomb("incompatible keywords given for -aboveRange");
322 if (i != 1)
323 aboveRange.flags |= OUTRANGE_SATURATE;
324 break;
325 case CLO_PIPE:
326 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
327 SDDS_Bomb("invalid -pipe syntax");
328 break;
329 case CLO_EXCLUDE:
330 if (scanned[iArg].n_items < 2)
331 SDDS_Bomb("invalid -exclude syntax");
332 moveToStringArray(&exclude, &excludes, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
333 break;
334 case CLO_FORCEMONOTONIC:
335 if ((scanned[iArg].n_items -= 1) > 0) {
336 if (!scanItemList(&forceMonotonic, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
337 "increasing", -1, NULL, 0, FORCE_INCREASING,
338 "decreasing", -1, NULL, 0, FORCE_DECREASING, NULL) ||
339 bitsSet(forceMonotonic) != 1)
340 SDDS_Bomb("invalid -forceMonotonic syntax/value");
341 } else
342 forceMonotonic = FORCE_MONOTONIC;
343 break;
344 case CLO_FILLIN:
345 fillIn = 1;
346 break;
347 default:
348 fprintf(stderr, "error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
349 exit(EXIT_FAILURE);
350 break;
351 }
352 } else {
353 if (!input)
354 input = scanned[iArg].list[0];
355 else if (!output)
356 output = scanned[iArg].list[0];
357 else
358 SDDS_Bomb("too many filenames seen");
359 }
360 }
361
362 processFilenames("sddsinterp", &input, &output, pipeFlags, 0, NULL);
363
364 fpPrint = stderr;
365 if (printFlags & STDOUT_PRINTOUT)
366 fpPrint = stdout;
367
368 if (!indepQuantity)
369 SDDS_Bomb("supply the independent quantity name with the -columns option");
370
371 if ((atValues ? 1 : 0) + (fileValuesFile ? 1 : 0) + (sequencePoints ? 1 : 0) + fillIn + (sequenceSpacing > 0 ? 1 : 0) != 1)
372 SDDS_Bomb("you must give one and only one of -atValues, -fileValues, -sequence, -equispaced, and -fillIn");
373
374 if (!SDDS_InitializeInput(&SDDSin, input))
375 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
376
377 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
378 if (!depenQuantities)
379 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities, "*");
380
381 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
382 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
383 SDDS_Bomb("no dependent quantities selected for interpolation");
384 }
385
386 if (!SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 0, NULL, "sddsinterp output", output))
387 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
388 if (!SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, indepQuantity, NULL))
389 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
390 if (columnMajorOrder != -1)
391 SDDSout.layout.data_mode.column_major = columnMajorOrder;
392 else
393 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
394 if (fileValuesFile && !SDDS_InitializeInput(&SDDSvalues, fileValuesFile))
395 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
396
397 if (SDDS_DefineParameter(&SDDSout, "InterpDataPage", NULL, NULL,
398 "Page of interpolation data file used to create this page", NULL, SDDS_LONG, NULL) < 0 ||
399 SDDS_DefineParameter(&SDDSout, "InterpPointsPage", NULL, NULL, "Page of interpolation points file used to create this page", NULL, SDDS_LONG, NULL) < 0)
400 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
401 for (i = 0; i < depenQuantities; i++)
402 if (!SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, depenQuantity[i], NULL)) {
403 fprintf(stderr, "problem creating interpolated-output column %s\n", depenQuantity[i]);
404 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
405 }
406 if (!SDDS_TransferAllParameterDefinitions(&SDDSout, &SDDSin, SDDS_TRANSFER_KEEPOLD) ||
407 !SDDS_WriteLayout(&SDDSout))
408 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
409
410 doNotRead = 0;
411 interpPoint = NULL;
412 outputData = tmalloc(sizeof(*outputData) * (depenQuantities));
413 depenValue = tmalloc(sizeof(*depenValue) * (depenQuantities));
414 rowFlag = NULL;
415 valuesReadCode = 0;
416
417 while (doNotRead || (readCode = SDDS_ReadPage(&SDDSin)) > 0) {
418 rows = SDDS_CountRowsOfInterest(&SDDSin);
419 if (!(indepValue = SDDS_GetColumnInDoubles(&SDDSin, indepQuantity)))
420 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
421 if (atValues) {
422 interpPoint = atValue;
423 interpPoints = atValues;
424 } else if (fileValuesFile) {
425 if (interpPoint)
426 free(interpPoint);
427 if ((valuesReadCode = SDDS_ReadPage(&SDDSvalues)) == 0)
428 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
429 else if (valuesReadCode == -1) {
430 if (parallelPages) {
431 fprintf(stderr, "warning: file %s ends before file %s\n", fileValuesFile, input);
432 break;
433 } else {
434 /* "rewind" the values file */
435 if (!SDDS_Terminate(&SDDSvalues) ||
436 !SDDS_InitializeInput(&SDDSvalues, fileValuesFile))
437 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
438 if ((valuesReadCode = SDDS_ReadPage(&SDDSvalues)) < 1) {
439 fprintf(stderr, "error: unable to (re)read file %s\n", fileValuesFile);
440 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
441 exit(EXIT_FAILURE);
442 }
443 /* read the next page of the interpolation data file */
444 if ((readCode = SDDS_ReadPage(&SDDSin)) < 1) {
445 if (readCode == -1)
446 break;
447 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
448 }
449 rows = SDDS_CountRowsOfInterest(&SDDSin);
450 if (indepValue)
451 free(indepValue);
452 if (!(indepValue = SDDS_GetColumnInDoubles(&SDDSin, indepQuantity)))
453 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
454 }
455 }
456
457 if (!parallelPages)
458 doNotRead = 1;
459 interpPoints = SDDS_CountRowsOfInterest(&SDDSvalues);
460 interpPoint = SDDS_GetColumnInDoubles(&SDDSvalues, fileValuesQuantity);
462 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
463 } else if (sequencePoints || sequenceSpacing) {
464 if (interpPoint)
465 free(interpPoint);
466 interpPoints = sequencePoints;
467 if (!(interpPoint = makeSequence(&interpPoints, sequenceStart, sequenceEnd, sequenceSpacing, indepValue, rows)))
468 exit(EXIT_FAILURE);
469 } else {
470 /* fillIn interpolation */
471 if (interpPoint)
472 free(interpPoint);
473 if (!(interpPoint = makeFillInSequence(indepValue, rows, &interpPoints)))
474 exit(EXIT_FAILURE);
475 }
476
477 for (i = 0; i < depenQuantities; i++)
478 outputData[i] = tmalloc(sizeof(*outputData[i]) * interpPoints);
479 rowFlag = trealloc(rowFlag, sizeof(*rowFlag) * interpPoints);
480 for (j = 0; j < interpPoints; j++)
481 rowFlag[j] = 1;
482 for (i = 0; i < depenQuantities; i++) {
483 if (!(depenValue[i] = SDDS_GetColumnInDoubles(&SDDSin, depenQuantity[i])))
484 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
485 }
486 if (forceMonotonic)
487 rows = forceMonotonicity(indepValue, depenValue, depenQuantities, rows, forceMonotonic);
488 else if (combineDuplicates)
489 rows = combineDuplicatePoints(indepValue, depenValue, depenQuantities, rows, 0.0);
490 if ((monotonicity = checkMonotonicity(indepValue, rows)) == 0)
491 SDDS_Bomb("independent data values do not change monotonically or repeated independent values exist");
492 if (interpShort)
493 shortValue = tmalloc(sizeof(*shortValue) * rows);
494
495 for (i = 0; i < depenQuantities; i++) {
496 if (interpShort) {
497 for (row = 0; row < rows; row++) {
498 shortValue[row] = (short)depenValue[i][row];
499 }
500 }
501 for (j = 0; j < interpPoints; j++) {
502 if (!interpShort) {
503 outputData[i][j] = interpolate(depenValue[i], indepValue, rows, interpPoint[j], &belowRange, &aboveRange, order, &interpCode, monotonicity);
504 } else {
505 outputData[i][j] = (double)interp_short(shortValue, indepValue, rows, interpPoint[j], 0, interpShortOrder, &interpCode, &nextPos);
506 }
507 if (interpCode) {
508 if (interpCode & OUTRANGE_ABORT) {
509 fprintf(stderr, "error: value %e is out of range for column %s\n", interpPoint[j], depenQuantity[i]);
510 exit(EXIT_FAILURE);
511 }
512 if (interpCode & OUTRANGE_WARN)
513 fprintf(stderr, "warning: value %e is out of range for column %s\n", interpPoint[j], depenQuantity[i]);
514 if (interpCode & OUTRANGE_SKIP)
515 rowFlag[j] = 0;
516 }
517 }
518 }
519 if (interpShort)
520 free(shortValue);
521 if (!SDDS_StartPage(&SDDSout, interpPoints) ||
522 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, interpPoint, interpPoints, indepQuantity))
523 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
524 if (!SDDS_SetParameters(&SDDSout, SDDS_BY_NAME | SDDS_PASS_BY_VALUE, "InterpDataPage", readCode, "InterpPointsPage", valuesReadCode, NULL) ||
525 !SDDS_CopyParameters(&SDDSout, &SDDSin))
526 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
527 for (i = 0; i < depenQuantities; i++)
528 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, outputData[i], interpPoints, depenQuantity[i]))
529 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
530 if (!SDDS_AssertRowFlags(&SDDSout, SDDS_FLAG_ARRAY, rowFlag, rows) || !SDDS_WritePage(&SDDSout))
531 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
532 if (printFlags & BARE_PRINTOUT) {
533 for (j = 0; j < interpPoints; j++)
534 if (rowFlag[j]) {
535 fprintf(fpPrint, "%21.15e ", interpPoint[j]);
536 for (i = 0; i < depenQuantities; i++)
537 fprintf(fpPrint, "%21.15e ", outputData[i][j]);
538 fputc('\n', fpPrint);
539 }
540 } else if (printFlags & NORMAL_PRINTOUT) {
541 for (j = 0; j < interpPoints; j++)
542 if (rowFlag[j]) {
543 fprintf(fpPrint, "%s=%21.15e ", indepQuantity, interpPoint[j]);
544 for (i = 0; i < depenQuantities; i++)
545 fprintf(fpPrint, "%s=%21.15e ", depenQuantity[i], outputData[i][j]);
546 fputc('\n', fpPrint);
547 }
548 }
549 if (indepValue)
550 free(indepValue);
551 indepValue = NULL;
552 for (i = 0; i < depenQuantities; i++) {
553 if (outputData[i])
554 free(outputData[i]);
555 outputData[i] = NULL;
556 if (depenValue[i])
557 free(depenValue[i]);
558 depenValue[i] = NULL;
559 }
560 if (fileValuesFile) {
561 if (interpPoint)
562 free(interpPoint);
563 interpPoint = NULL;
564 }
565 if (rowFlag)
566 free(rowFlag);
567 rowFlag = NULL;
568 }
569
570 if (!SDDS_Terminate(&SDDSin)) {
571 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
572 exit(EXIT_FAILURE);
573 }
574 if (!SDDS_Terminate(&SDDSout)) {
575 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
576 exit(EXIT_FAILURE);
577 }
578 if (fileValuesFile) {
579 if (!SDDS_Terminate(&SDDSvalues)) {
580 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
581 exit(EXIT_FAILURE);
582 }
583 }
584
585 return EXIT_SUCCESS;
586}
587
588double *makeFillInSequence(double *x, int64_t dataRows, int64_t *nPointsReturn) {
589 int64_t i;
590 double dxMin, dx, xMin, xMax;
591
592 dxMin = DBL_MAX;
593 xMin = xMax = x[0];
594 for (i = 1; i < dataRows; i++) {
595 if ((dx = fabs(x[i] - x[i - 1])) < dxMin && dx > 0)
596 dxMin = dx;
597 if (x[i] < xMin)
598 xMin = x[i];
599 if (x[i] > xMax)
600 xMax = x[i];
601 }
602 *nPointsReturn = (int64_t)((xMax - xMin) / dxMin + 1);
603 return makeSequence(nPointsReturn, xMin, xMax, 0.0, x, dataRows);
604}
605
606double *makeSequence(int64_t *points, double start, double end, double spacing, double *data, int64_t dataRows) {
607 int64_t i;
608 double delta, *sequence;
609 if (start == end) {
610 if (!find_min_max(&start, &end, data, dataRows))
611 return NULL;
612 }
613 if (*points > 1) {
614 delta = (end - start) / (*points - 1);
615 } else if (spacing >= 0) {
616 delta = spacing;
617 *points = (int64_t)((end - start) / delta + 1.5);
618 } else {
619 *points = 1;
620 delta = 0;
621 }
622 sequence = tmalloc(sizeof(*sequence) * (*points));
623 for (i = 0; i < *points; i++)
624 sequence[i] = start + delta * i;
625 return sequence;
626}
627
628long checkMonotonicity(double *indepValue, int64_t rows) {
629 if (rows == 1)
630 return 1;
631 if (indepValue[rows - 1] > indepValue[0]) {
632 while (--rows > 0)
633 if (indepValue[rows] <= indepValue[rows - 1])
634 return 0;
635 return 1;
636 } else {
637 while (--rows > 0)
638 if (indepValue[rows] >= indepValue[rows - 1])
639 return 0;
640 return -1;
641 }
642}
643
644int64_t combineDuplicatePoints(double *x, double **y, long columns, int64_t rows, double tolerance) {
645 double xmin, xmax;
646 long column;
647 int64_t i, j;
648
649 find_min_max(&xmin, &xmax, x, rows);
650 if (xmin == xmax)
651 SDDS_Bomb("interpolation data is invalid--no range in independent variable");
652 tolerance *= xmax - xmin;
653 for (i = 1; i < rows; i++) {
654 if (fabs(x[i] - x[i - 1]) <= tolerance) {
655 x[i - 1] = (x[i] + x[i - 1]) / 2;
656 for (column = 0; column < columns; column++)
657 y[column][i - 1] = (y[column][i] + y[column][i - 1]) / 2;
658 for (j = i + 1; j < rows; j++) {
659 x[j - 1] = x[j];
660 for (column = 0; column < columns; column++)
661 y[column][j - 1] = y[column][j];
662 }
663 rows--;
664 i--;
665 }
666 }
667 return rows;
668}
669
670int64_t forceMonotonicity(double *x, double **y, long columns, int64_t rows, unsigned long mode) {
671 int64_t i, j;
672 long column, direction;
673 char *keep;
674 double reference;
675
676 if (rows < 2)
677 return rows;
678
679 if (mode & FORCE_INCREASING)
680 direction = 1;
681 else if (mode & FORCE_DECREASING)
682 direction = -1;
683 else
684 direction = x[1] > x[0] ? 1 : -1;
685
686 keep = tmalloc(sizeof(*keep) * rows);
687 reference = x[0];
688 keep[0] = 1; // Always keep the first point
689 for (i = 1; i < rows; i++) {
690 if (direction * (x[i] - reference) > 0) {
691 reference = x[i];
692 keep[i] = 1;
693 } else {
694 keep[i] = 0;
695 }
696 }
697 for (i = j = 1; i < rows; i++) {
698 if (keep[i]) {
699 if (i != j) {
700 for (column = 0; column < columns; column++)
701 y[column][j] = y[column][i];
702 x[j] = x[i];
703 }
704 j++;
705 }
706 }
707 rows = j;
708 free(keep);
709 return rows;
710}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
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.
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:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output 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_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
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_TransferAllParameterDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all parameter definitions from a source dataset to a target dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_NumberOfErrors()
Retrieves the number of errors recorded by SDDS library routines.
Definition SDDS_utils.c:304
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
long bitsSet(unsigned long data)
Counts the number of set bits (1s) in the given data.
Definition binary.c:52
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
Definition findMinMax.c:33
short interp_short(short *f, double *x, int64_t n, double xo, long warnings, short order, unsigned long *returnCode, long *next_start_pos)
Performs interpolation for short integer data types.
Definition interp.c:281
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:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
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.