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