SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsminterp.c
Go to the documentation of this file.
1/**
2 * @file sddsminterp.c
3 * @brief Multiplicative renormalized model interpolation utility for SDDS data sets.
4 *
5 * @details
6 * This program performs interpolation of data using another data set as a model function.
7 * It utilizes abscissa values from either a values file or the model function file to generate
8 * interpolated results. Multiple options allow for customization of interpolation parameters,
9 * output formats, and verbosity. The program supports SDDS files for both input and output.
10 *
11 * @section Usage
12 * ```
13 * sddsminterp <input-file> <output-file>
14 * [-pipe=[input],[output]]
15 * -columns=<independent-quantity>,<name>
16 * [-interpOrder=<order>]
17 * -model=<modelFile>,abscissa=<column>,ordinate=<column>[,interp=<order>]
18 * [-fileValues=<valuesFile>[,abscissa=<column>]]
19 * [-majorOrder=row|column]
20 * [-verbose]
21 * [-ascii]
22 * ```
23 *
24 * @section Options
25 * | Required | Description |
26 * |---------------------------------------|---------------------------------------------------------|
27 * | -columns | Specify the columns for interpolation. |
28 * | -model | Define the model dataset with required abscissa and ordinate columns. |
29 *
30 * | Optional | Description |
31 * |-------------------------------------|-----------------------------------------------------------------------------|
32 * | -pipe | Use pipes for input and output. |
33 * | -interpOrder | Set the interpolation order (default is 1). |
34 * | -fileValues | Provide abscissa values for interpolation from a file. |
35 * | -majorOrder | Set output data order as row or column. |
36 * | -verbose | Enable detailed output logging. |
37 * | -ascii | Produce ASCII-formatted output. |
38 *
39 * @subsection Incompatibilities
40 * - `-fileValues` is not operational yet
41 *
42 * @copyright
43 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
44 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
45 *
46 * @license
47 * This file is distributed under the terms of the Software License Agreement
48 * found in the file LICENSE included with this distribution.
49 *
50 * @author
51 * M. Borland, C. Saunders, R. Soliday, H. Shang
52 */
53
54#include "mdb.h"
55#include "scan.h"
56#include "match_string.h"
57#include "SDDS.h"
58
59/* Enumeration for option types */
60enum option_type {
61 CLO_COLUMNS,
62 CLO_ORDER,
63 CLO_MODEL,
64 CLO_VALUES,
65 CLO_VERBOSE,
66 CLO_ASCII,
67 CLO_PIPE,
68 CLO_MAJOR_ORDER,
69 N_OPTIONS
70};
71
72char *commandline_option[N_OPTIONS] = {
73 "columns",
74 "order",
75 "model",
76 "fileValues",
77 "verbose",
78 "ascii",
79 "pipe",
80 "majorOrder",
81};
82
83static char *USAGE =
84 "sddsminterp [<input-file>] [<output-file>]\n"
85 " [-pipe=[input],[output]]\n"
86 " -columns=<independent-quantity>,<name>\n"
87 " [-interpOrder=<order>]\n"
88 " -model=<modelFile>,abscissa=<column>,ordinate=<column>[,interp=<order>]\n"
89 " [-fileValues=<valuesFile>[,abscissa=<column>]]\n"
90 " [-majorOrder=row|column]\n"
91 " [-verbose]\n"
92 " [-ascii]\n"
93 "\nOptions:\n"
94 " -pipe=<input>,<output> Use pipes for input and output.\n"
95 " -columns=<independent-quantity>,<name> Specify the columns to interpolate.\n"
96 " -interpOrder=<order> Set the interpolation order (default: 1).\n"
97 " -model=<modelFile>,abscissa=<column>,\n"
98 " ordinate=<column>[,interp=<order>] Define the model data set.\n"
99 " -fileValues=<valuesFile>[,abscissa=<column>]\n"
100 " Specify abscissa values for interpolation.\n"
101 " -majorOrder=row|column Set output data order.\n"
102 " -verbose Enable verbose mode.\n"
103 " -ascii Output in ASCII format.\n"
104 "\nDescription:\n"
105 " Multiplicative renormalized model interpolation of a data set using another\n"
106 " data set as a model function.\n"
107 "\n"
108 "Program by Louis Emery, ANL (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
109
110#define MOD_ABSCISSA 0x0001U
111#define MOD_ORDINATE 0x0002U
112#define MOD_ORDER 0x0004U
113static char *modUsage =
114 "-model=<file>,abscissa=<column>,ordinate=<column>[,interp=<order>]\n";
115
116#define VAL_ABSCISSA 0x0001U
117static char *valUsage =
118 "-fileValues=<file>,abscissa=<column>\n";
119
120#define DEFAULT_ORDER 1
121
122int main(int argc, char **argv) {
123 SCANNED_ARG *s_arg;
124 SDDS_DATASET modDataSet, valDataSet, dataDataSet, outDataSet;
125 unsigned long modFlags, valFlags, majorOrderFlag;
126 char *modAbscissaName, *modOrdinateName;
127 char *valAbscissaName;
128 char *dataAbscissaName, *dataOrdinateName;
129 char *outAbscissaName, *outOrdinateName;
130 char *modFile, *dataFile, *valFile, *outFile;
131 long dataOrder;
132 int32_t modOrder;
133 double *modAbscissa, *modOrdinate;
134 double *valAbscissa;
135 double *dataAbscissa, *dataOrdinate, *dataScale, *dataOrdinateInterp;
136 double *outScale, *outAbscissa, *outOrdinate;
137 int64_t i, modRows, valRows, dataRows, outRows;
138
139 long i_arg;
140 /*long verbose; */
141 long warning;
142 long ascii;
143 long returnCode;
144 unsigned long pipeFlags;
145 long tmpfile_used, noWarnings;
146 short columnMajorOrder = -1;
147
149 argc = scanargs(&s_arg, argc, argv);
150 if (argc == 1)
151 bomb(NULL, USAGE);
152
153 /* Initialize variables */
154 /*verbose=0; */
155 dataFile = dataAbscissaName = dataOrdinateName = modFile = valFile = NULL;
156 modOrdinate = dataOrdinate = NULL;
157 outFile = NULL;
158 warning = 0;
159 modOrder = DEFAULT_ORDER;
160 dataOrder = DEFAULT_ORDER;
161 ascii = 0;
162 modFlags = 0x0UL;
163 valFlags = 0x0UL;
164 pipeFlags = 0;
165 tmpfile_used = 0;
166 noWarnings = 0;
167
168 for (i_arg = 1; i_arg < argc; i_arg++) {
169 if (s_arg[i_arg].arg_type == OPTION) {
170 switch (match_string(s_arg[i_arg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
171 case CLO_MAJOR_ORDER:
172 majorOrderFlag = 0;
173 s_arg[i_arg].n_items--;
174 if (s_arg[i_arg].n_items > 0 &&
175 !scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
176 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
177 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER,
178 NULL))
179 SDDS_Bomb("Invalid -majorOrder syntax or values");
180 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
181 columnMajorOrder = 1;
182 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
183 columnMajorOrder = 0;
184 break;
185 case CLO_VERBOSE:
186 /*verbose=1; */
187 break;
188 case CLO_ASCII:
189 ascii = 1;
190 break;
191 case CLO_PIPE:
192 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
193 SDDS_Bomb("Invalid -pipe syntax");
194 break;
195 case CLO_MODEL:
196 if ((s_arg[i_arg].n_items -= 2) < 0 ||
197 !scanItemList(&modFlags, s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
198 "abscissa", SDDS_STRING, &modAbscissaName, 1, MOD_ABSCISSA,
199 "ordinate", SDDS_STRING, &modOrdinateName, 1, MOD_ORDINATE,
200 "interp", SDDS_LONG, &modOrder, 1, MOD_ORDER,
201 NULL) ||
202 !(modFlags & MOD_ABSCISSA) || !(modFlags & MOD_ORDINATE))
203 bomb("Invalid -model syntax", modUsage);
204 if (!strlen(modFile = s_arg[i_arg].list[1]))
205 bomb("Invalid -model syntax", modUsage);
206 break;
207 case CLO_VALUES:
208 if ((s_arg[i_arg].n_items -= 2) < 0 ||
209 !scanItemList(&valFlags, s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
210 "abscissa", SDDS_STRING, &valAbscissaName, 1, VAL_ABSCISSA,
211 NULL) ||
212 !(valFlags & VAL_ABSCISSA))
213 bomb("Invalid -fileValues syntax", valUsage);
214 if (!strlen(valFile = s_arg[i_arg].list[1]))
215 bomb("Invalid -fileValues syntax", valUsage);
216 break;
217 case CLO_ORDER:
218 if (!get_long(&dataOrder, s_arg[i_arg].list[1]))
219 bomb("No value provided for option -order", USAGE);
220 break;
221 case CLO_COLUMNS:
222 /* The input file and the -order and -columns options could be combined more
223 compactly to resemble the syntax of the -model option.
224 However, we adopt the command line options of the
225 command sddsinterp since it allows an input pipe */
226 if (s_arg[i_arg].n_items != 3 ||
227 !strlen(dataAbscissaName = s_arg[i_arg].list[1]) ||
228 !strlen(dataOrdinateName = s_arg[i_arg].list[2]))
229 SDDS_Bomb("Invalid -columns syntax");
230 break;
231 default:
232 SDDS_Bomb("Unrecognized option provided");
233 }
234 } else {
235 if (!dataFile)
236 dataFile = s_arg[i_arg].list[0];
237 else if (!outFile)
238 outFile = s_arg[i_arg].list[0];
239 else
240 SDDS_Bomb("Too many filenames provided");
241 }
242 }
243
244 processFilenames("sddsminterp", &dataFile, &outFile, pipeFlags, noWarnings, &tmpfile_used);
245
246 if (valFlags) {
247 fprintf(stderr, "Warning: Option -fileValues is not operational yet. Using model abscissa values.\n");
248 }
249
250 if (!SDDS_InitializeInput(&modDataSet, modFile))
251 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
252 if (SDDS_ReadPage(&modDataSet) < 0)
253 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
254
255 if (valFlags) {
256 if (!SDDS_InitializeInput(&valDataSet, valFile))
257 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
258 if (SDDS_ReadPage(&valDataSet) < 0)
259 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
260 }
261
262 /* Check that the selected columns exist */
263 switch (SDDS_CheckColumn(&modDataSet, modAbscissaName, NULL, SDDS_DOUBLE, NULL)) {
264 case SDDS_CHECK_NONEXISTENT:
265 fprintf(stderr, "Error: Column '%s' does not exist in file '%s'.\n", modAbscissaName, modFile);
266 exit(EXIT_FAILURE);
267 }
268 switch (SDDS_CheckColumn(&modDataSet, modOrdinateName, NULL, SDDS_DOUBLE, NULL)) {
269 case SDDS_CHECK_NONEXISTENT:
270 fprintf(stderr, "Error: Column '%s' does not exist in file '%s'.\n", modOrdinateName, modFile);
271 exit(EXIT_FAILURE);
272 }
273
274 if (valFlags) {
275 switch (SDDS_CheckColumn(&valDataSet, valAbscissaName, NULL, SDDS_DOUBLE, NULL)) {
276 case SDDS_CHECK_NONEXISTENT:
277 fprintf(stderr, "Error: Column '%s' does not exist in file '%s'.\n", valAbscissaName, valFile);
278 exit(EXIT_FAILURE);
279 }
280 }
281
282 modRows = SDDS_CountRowsOfInterest(&modDataSet);
283 modAbscissa = (double *)SDDS_GetColumnInDoubles(&modDataSet, modAbscissaName);
284 modOrdinate = (double *)SDDS_GetColumnInDoubles(&modDataSet, modOrdinateName);
285 if (!modAbscissa || !modOrdinate)
286 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
287
288 if (valFlags) {
289 valRows = SDDS_CountRowsOfInterest(&valDataSet);
290 valAbscissa = (double *)SDDS_GetColumnInDoubles(&valDataSet, valAbscissaName);
291 if (!valAbscissa)
292 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
293 outAbscissa = valAbscissa;
294 outRows = valRows;
295 } else {
296 outAbscissa = modAbscissa;
297 outRows = modRows;
298 }
299
300 if (!SDDS_InitializeInput(&dataDataSet, dataFile))
301 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
302
303 switch (SDDS_CheckColumn(&dataDataSet, dataAbscissaName, NULL, SDDS_DOUBLE, NULL)) {
304 case SDDS_CHECK_NONEXISTENT:
305 fprintf(stderr, "Error: Column '%s' does not exist in file '%s'.\n", dataAbscissaName, dataFile);
306 exit(EXIT_FAILURE);
307 }
308 switch (SDDS_CheckColumn(&dataDataSet, dataOrdinateName, NULL, SDDS_DOUBLE, NULL)) {
309 case SDDS_CHECK_NONEXISTENT:
310 fprintf(stderr, "Error: Column '%s' does not exist in file '%s'.\n", dataOrdinateName, dataFile);
311 exit(EXIT_FAILURE);
312 }
313
314 if (!SDDS_InitializeOutput(&outDataSet, ascii ? SDDS_ASCII : SDDS_BINARY, 1,
315 "Interpolation data from model file", "Interpolated data", outFile) ||
316 !SDDS_InitializeCopy(&outDataSet, &dataDataSet, outFile, "w"))
317 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
318
319 if (columnMajorOrder != -1)
320 outDataSet.layout.data_mode.column_major = columnMajorOrder;
321 else
322 outDataSet.layout.data_mode.column_major = dataDataSet.layout.data_mode.column_major;
323
324 if (!SDDS_WriteLayout(&outDataSet))
325 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
326
327 if (valFlags) {
328 SDDS_CopyString(&outAbscissaName, valAbscissaName);
329 } else {
330 SDDS_CopyString(&outAbscissaName, modAbscissaName);
331 }
332 SDDS_CopyString(&outOrdinateName, dataOrdinateName);
333
334 while (SDDS_ReadPage(&dataDataSet) > 0) {
335 dataAbscissa = (double *)SDDS_GetColumnInDoubles(&dataDataSet, dataAbscissaName);
336 dataOrdinate = (double *)SDDS_GetColumnInDoubles(&dataDataSet, dataOrdinateName);
337 if (!dataAbscissa || !dataOrdinate)
338 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
339
340 dataRows = SDDS_CountRowsOfInterest(&dataDataSet);
341 dataOrdinateInterp = (double *)malloc(sizeof(double) * dataRows);
342 dataScale = (double *)malloc(sizeof(double) * dataRows);
343
344 outScale = (double *)malloc(sizeof(double) * outRows);
345 outOrdinate = (double *)malloc(sizeof(double) * outRows);
346
347 /* There are normally more rows in the model file or value file than in the data file. */
348 for (i = 0; i < dataRows; i++) {
349 dataOrdinateInterp[i] = interp(modOrdinate, modAbscissa, modRows, dataAbscissa[i], warning, modOrder, &returnCode);
350 dataScale[i] = dataOrdinate[i] / dataOrdinateInterp[i]; /* dataScale is a numerator */
351 }
352
353 for (i = 0; i < outRows; i++) {
354 outScale[i] = interp(dataScale, dataAbscissa, dataRows, outAbscissa[i], warning, dataOrder, &returnCode);
355 outOrdinate[i] = modOrdinate[i] * outScale[i];
356 }
357
358 if (SDDS_StartPage(&outDataSet, outRows) < 0)
359 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
360
361 if (!SDDS_CopyParameters(&outDataSet, &dataDataSet) ||
362 !SDDS_CopyArrays(&outDataSet, &dataDataSet) ||
363 !SDDS_SetColumn(&outDataSet, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, modAbscissa, outRows, outAbscissaName) ||
364 !SDDS_SetColumn(&outDataSet, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, outOrdinate, outRows, outOrdinateName) ||
365 SDDS_WritePage(&outDataSet) < 0)
366 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
367
368 free(dataAbscissa);
369 free(dataOrdinate);
370 free(dataOrdinateInterp);
371 free(dataScale);
372 free(outScale);
373 free(outOrdinate);
374 }
375
376 if (!SDDS_Terminate(&modDataSet) ||
377 !SDDS_Terminate(&outDataSet) ||
378 !SDDS_Terminate(&dataDataSet))
379 SDDS_PrintErrors(stdout, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
380
381 if (tmpfile_used && !replaceFileAndBackUp(dataFile, outFile))
382 exit(EXIT_FAILURE);
383
384 return EXIT_SUCCESS;
385}
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_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyArrays(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:334
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
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_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:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
#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 bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
int get_long(long *iptr, char *s)
Parses a long integer value from the given string.
Definition data_scan.c:255
double interp(double *f, double *x, long n, double xo, long warnings, long order, long *returnCode)
Performs simple linear interpolation of data.
Definition interp.c:34
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.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
Definition replacefile.c:75
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.