SDDSlib
Loading...
Searching...
No Matches
sddsderiv.c
Go to the documentation of this file.
1/**
2 * @file sddsderiv.c
3 * @brief Differentiates a data set in SDDS format.
4 *
5 * This program calculates the derivative of specified columns in an SDDS data set.
6 * It supports various options including handling error columns, Savitzky-Golay filtering,
7 * and customizable output templates.
8 *
9 * Usage:
10 * sddsderiv [<input>] [<output>]
11 * [-pipe=[input][,output]]
12 * -differentiate=<column-name>[,<sigma-name>]...
13 * [-exclude=<column-name>[,...]]
14 * -versus=<column-name>
15 * [-interval=<integer>]
16 * [-SavitzkyGolay=<left>,<right>,<fitOrder>[,<derivOrder>]]
17 * [-mainTemplates=<item>=<string>[,...]]
18 * [-errorTemplates=<item>=<string>[,...]]
19 * [-majorOrder=row|column]
20 *
21 * Options:
22 * -pipe=[input][,output] Use standard input/output.
23 * -differentiate=<col>[,<sigma-col>]... Columns to differentiate, optionally specifying sigma columns.
24 * -exclude=<col>[,...] Columns to exclude from differentiation.
25 * -versus=<col> Column to differentiate with respect to.
26 * -interval=<integer> Interval for finite difference.
27 * -SavitzkyGolay=<left>,<right>,<fitOrder>[,<derivOrder>]
28 * Apply Savitzky-Golay filter with specified parameters.
29 * -mainTemplates=<item>=<string>[,...] Templates for main output columns. Items: name, symbol, description.
30 * -errorTemplates=<item>=<string>[,...] Templates for error output columns. Items: name, symbol, description.
31 * -majorOrder=row|column Set major order of data.
32 *
33 * The -templates <item> may be "name", "symbol" or "description".
34 * The default main name, description, and symbol templates are "%yNameDeriv",
35 * "Derivative w.r.t %xSymbol of %ySymbol", and "d[%ySymbol]/d[%xSymbol]", respectively.
36 * The default error name, description, and symbol templates are "%yNameDerivSigma",
37 * "Sigma of derivative w.r.t %xSymbol of %ySymbol", and "Sigma[d[%ySymbol]/d[%xSymbol]]", respectively.
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 * @author M. Borland, C. Saunders, R. Soliday, H. Shang
48 */
49
50#include "mdb.h"
51#include "SDDS.h"
52#include "SDDSutils.h"
53#include "scan.h"
54#include <ctype.h>
55
56static char *USAGE =
57 "Usage: sddsderiv [<input>] [<output>]\n"
58 " [-pipe=[input][,output]]\n"
59 " -differentiate=<column-name>[,<sigma-name>]...\n"
60 " [-exclude=<column-name>[,...]]\n"
61 " -versus=<column-name>\n"
62 " [-interval=<integer>]\n"
63 " [-SavitzkyGolay=<left>,<right>,<fitOrder>[,<derivOrder>]]\n"
64 " [-mainTemplates=<item>=<string>[,...]]\n"
65 " [-errorTemplates=<item>=<string>[,...]]\n"
66 " [-majorOrder=row|column]\n\n"
67 "Options:\n"
68 " -pipe=[input][,output] Use standard input/output.\n"
69 " -differentiate=<col>[,<sigma-col>]... Columns to differentiate, optionally specifying sigma columns.\n"
70 " -exclude=<col>[,...] Columns to exclude from differentiation.\n"
71 " -versus=<col> Column to differentiate with respect to.\n"
72 " -interval=<integer> Interval for finite difference.\n"
73 " -SavitzkyGolay=<left>,<right>,<fitOrder>[,<derivOrder>]\n"
74 " Apply Savitzky-Golay filter with specified parameters.\n"
75 " -mainTemplates=<item>=<string>[,...] Templates for main output columns. Items: name, symbol, description.\n"
76 " -errorTemplates=<item>=<string>[,...] Templates for error output columns. Items: name, symbol, description.\n"
77 " -majorOrder=row|column Set major order of data.\n\n"
78 "The -templates <item> may be \"name\", \"symbol\" or \"description\".\n"
79 "The default main name, description, and symbol templates are \"%yNameDeriv\",\n"
80 " \"Derivative w.r.t %xSymbol of %ySymbol\", and \"d[%ySymbol]/d[%xSymbol]\", respectively.\n"
81 "The default error name, description, and symbol templates are \"%yNameDerivSigma\",\n"
82 " \"Sigma of derivative w.r.t %xSymbol of %ySymbol\", and \"Sigma[d[%ySymbol]/d[%xSymbol]]\", respectively.\n"
83 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")";
84
85/* Enumeration for option types */
86enum option_type {
87 CLO_DIFFERENTIATE,
88 CLO_VERSUS,
89 CLO_INTERVAL,
90 CLO_MAINTEMPLATE,
91 CLO_ERRORTEMPLATE,
92 CLO_PIPE,
93 CLO_EXCLUDE,
94 CLO_SAVITZKYGOLAY,
95 CLO_MAJOR_ORDER,
96 N_OPTIONS
97};
98
99static char *option[N_OPTIONS] = {
100 "differentiate",
101 "versus",
102 "interval",
103 "maintemplate",
104 "errortemplate",
105 "pipe",
106 "exclude",
107 "savitzkygolay",
108 "majorOrder",
109};
110
111long checkErrorNames(char **yErrorName, long nDerivatives);
112void makeSubstitutions(char *buffer1, char *buffer2, char *template, char *nameRoot, char *symbolRoot, char *xName, char *xSymbol);
113char *changeInformation(SDDS_DATASET *SDDSout, char *name, char *nameRoot, char *symbolRoot, char *xName, char *xSymbol, char **template, char *newUnits);
114long setupOutputFile(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *output,
115 char ***yOutputName, char ***yOutputErrorName, char ***yOutputUnits, char *xName, char *xErrorName, char **yName, char **yErrorName, long yNames, char **mainTemplate, char **errorTemplate, int32_t interval, long order, short columnMajorOrder);
116long findDerivIndices(int64_t *i1, int64_t *i2, long interval, int64_t i, int64_t rows);
117void takeDerivative(double *x, double *y, double *sy, int64_t rows, double *deriv, double *derivSigma, double *derivPosition, long interval);
118void takeSGDerivative(double *x, double *y, int64_t rows, double *deriv, double *derivPosition, long left, long right, long sgOrder, long derivOrder);
119
120int main(int argc, char **argv) {
121 double *xData, *yData, *xError, *yError, *derivative, *derivativeError, *derivativePosition;
122 char *input, *output, *xName, *xErrorName, **yName, **yErrorName, **yOutputName, **yOutputErrorName, *ptr;
123 char **yOutputUnits, **yExcludeName;
124 char *mainTemplate[3] = {NULL, NULL, NULL};
125 char *errorTemplate[3] = {NULL, NULL, NULL};
126 long i, iArg, yNames, yExcludeNames;
127 int64_t rows;
128 int32_t interval;
129 SDDS_DATASET SDDSin, SDDSout;
130 SCANNED_ARG *scanned;
131 unsigned long flags, pipeFlags, majorOrderFlag;
132 long SGLeft, SGRight, SGOrder, SGDerivOrder, intervalGiven, yErrorsSeen;
133 short columnMajorOrder = -1;
134
136
137 argc = scanargs(&scanned, argc, argv);
138 if (argc == 1)
139 bomb(NULL, USAGE);
140
141 input = output = xName = xErrorName = NULL;
142 yName = yErrorName = yExcludeName = NULL;
143 derivative = derivativeError = derivativePosition = yError = yData = xData = xError = NULL;
144 yNames = yExcludeNames = 0;
145 pipeFlags = 0;
146 interval = 2;
147 SGOrder = -1;
148 SGDerivOrder = 1;
149 intervalGiven = 0;
150 yErrorsSeen = 0;
151
152 for (iArg = 1; iArg < argc; iArg++) {
153 if (scanned[iArg].arg_type == OPTION) {
154 /* process options here */
155 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
156 case CLO_MAJOR_ORDER:
157 majorOrderFlag = 0;
158 scanned[iArg].n_items--;
159 if (scanned[iArg].n_items > 0 && (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
160 SDDS_Bomb("invalid -majorOrder syntax/values");
161 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
162 columnMajorOrder = 1;
163 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
164 columnMajorOrder = 0;
165 break;
166 case CLO_DIFFERENTIATE:
167 if (scanned[iArg].n_items != 2 && scanned[iArg].n_items != 3)
168 SDDS_Bomb("invalid -differentiate syntax");
169 yName = SDDS_Realloc(yName, sizeof(*yName) * (yNames + 1));
170 yErrorName = SDDS_Realloc(yErrorName, sizeof(*yErrorName) * (yNames + 1));
171 yName[yNames] = scanned[iArg].list[1];
172 if (scanned[iArg].n_items == 3) {
173 yErrorsSeen = 1;
174 yErrorName[yNames] = scanned[iArg].list[2];
175 } else
176 yErrorName[yNames] = NULL;
177 yNames++;
178 break;
179 case CLO_EXCLUDE:
180 if (scanned[iArg].n_items < 2)
181 SDDS_Bomb("invalid -exclude syntax");
182 moveToStringArray(&yExcludeName, &yExcludeNames, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
183 break;
184 case CLO_VERSUS:
185 if (xName)
186 SDDS_Bomb("give -versus only once");
187 if (scanned[iArg].n_items != 2)
188 SDDS_Bomb("invalid -versus syntax");
189 xName = scanned[iArg].list[1];
190 xErrorName = NULL;
191 break;
192 case CLO_MAINTEMPLATE:
193 if (scanned[iArg].n_items < 2)
194 SDDS_Bomb("invalid -mainTemplate syntax");
195 scanned[iArg].n_items--;
196 if (!scanItemList(&flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "name", SDDS_STRING, mainTemplate + 0, 1, 0, "description", SDDS_STRING, mainTemplate + 1, 1, 0, "symbol", SDDS_STRING, mainTemplate + 2, 1, 0, NULL))
197 SDDS_Bomb("invalid -mainTemplate syntax");
198 break;
199 case CLO_ERRORTEMPLATE:
200 if (scanned[iArg].n_items < 2)
201 SDDS_Bomb("invalid -errorTemplate syntax");
202 scanned[iArg].n_items--;
203 if (!scanItemList(&flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "name", SDDS_STRING, errorTemplate + 0, 1, 0, "description", SDDS_STRING, errorTemplate + 1, 1, 0, "symbol", SDDS_STRING, errorTemplate + 2, 1, 0, NULL))
204 SDDS_Bomb("invalid -errorTemplate syntax");
205 break;
206 case CLO_PIPE:
207 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
208 SDDS_Bomb("invalid -pipe syntax");
209 break;
210 case CLO_INTERVAL:
211 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%" SCNd32, &interval) != 1 || interval <= 0)
212 SDDS_Bomb("invalid -interval syntax/value");
213 intervalGiven = 1;
214 break;
215 case CLO_SAVITZKYGOLAY:
216 if ((scanned[iArg].n_items != 4 && scanned[iArg].n_items != 5) ||
217 sscanf(scanned[iArg].list[1], "%ld", &SGLeft) != 1 ||
218 sscanf(scanned[iArg].list[2], "%ld", &SGRight) != 1 ||
219 sscanf(scanned[iArg].list[3], "%ld", &SGOrder) != 1 ||
220 (scanned[iArg].n_items == 5 && sscanf(scanned[iArg].list[4], "%ld", &SGDerivOrder) != 1) ||
221 SGLeft < 0 ||
222 SGRight < 0 ||
223 (SGLeft + SGRight) < SGOrder ||
224 SGOrder < 0 ||
225 SGDerivOrder < 0)
226 SDDS_Bomb("invalid -SavitzkyGolay syntax/values");
227 break;
228 default:
229 fprintf(stderr, "invalid option seen: %s\n", scanned[iArg].list[0]);
230 exit(EXIT_FAILURE);
231 break;
232 }
233 } else {
234 if (!input)
235 input = scanned[iArg].list[0];
236 else if (!output)
237 output = scanned[iArg].list[0];
238 else
239 SDDS_Bomb("too many filenames");
240 }
241 }
242
243 if (intervalGiven && SGOrder >= 0)
244 SDDS_Bomb("-interval and -SavitzkyGolay options are incompatible");
245 if (SGOrder >= 0 && (xErrorName || yErrorsSeen))
246 SDDS_Bomb("Savitzky-Golay method does not support errors in data");
247
248 processFilenames("sddsderiv", &input, &output, pipeFlags, 0, NULL);
249
250 if (!yNames)
251 SDDS_Bomb("-differentiate option must be given at least once");
252 if (!checkErrorNames(yErrorName, yNames))
253 SDDS_Bomb("either all -differentiate quantities must have errors, or none");
254
255 if (!SDDS_InitializeInput(&SDDSin, input))
256 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
257 if (!(ptr = SDDS_FindColumn(&SDDSin, FIND_NUMERIC_TYPE, xName, NULL))) {
258 fprintf(stderr, "error: column %s doesn't exist\n", xName);
259 exit(EXIT_FAILURE);
260 }
261 free(xName);
262 xName = ptr;
263 if (xErrorName) {
264 if (!(ptr = SDDS_FindColumn(&SDDSin, FIND_NUMERIC_TYPE, xErrorName, NULL))) {
265 fprintf(stderr, "error: column %s doesn't exist\n", xErrorName);
266 exit(EXIT_FAILURE);
267 } else {
268 free(xErrorName);
269 xErrorName = ptr;
270 }
271 }
272
273 if (!(yNames = expandColumnPairNames(&SDDSin, &yName, &yErrorName, yNames, yExcludeName, yExcludeNames, FIND_NUMERIC_TYPE, 0))) {
274 fprintf(stderr, "error: no quantities to differentiate found in file\n");
275 exit(EXIT_FAILURE);
276 }
277
278 setupOutputFile(&SDDSout, &SDDSin, output, &yOutputName, &yOutputErrorName, &yOutputUnits, xName, xErrorName, yName, yErrorName, yNames, mainTemplate, errorTemplate, interval, SGOrder >= 0 ? SGDerivOrder : 1, columnMajorOrder);
279
280 while (SDDS_ReadPage(&SDDSin) > 0) {
281 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) < 2)
282 SDDS_Bomb("Can't compute derivatives: too little data.");
283 derivative = SDDS_Realloc(derivative, sizeof(*derivative) * rows);
284 derivativeError = SDDS_Realloc(derivativeError, sizeof(*derivativeError) * rows);
285 derivativePosition = SDDS_Realloc(derivativePosition, sizeof(*derivativePosition) * rows);
286 if (!SDDS_StartPage(&SDDSout, rows) || !SDDS_CopyParameters(&SDDSout, &SDDSin))
287 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
288 xError = NULL;
289 if (!(xData = SDDS_GetColumnInDoubles(&SDDSin, xName)) ||
290 (xErrorName && !(xError = SDDS_GetColumnInDoubles(&SDDSin, xErrorName))))
291 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
292 for (i = 0; i < yNames; i++) {
293 yError = NULL;
294 if (!(yData = SDDS_GetColumnInDoubles(&SDDSin, yName[i])) ||
295 (yErrorName && yErrorName[i] && !(yError = SDDS_GetColumnInDoubles(&SDDSin, yErrorName[i]))))
296 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
297 if (SGOrder >= 0)
298 takeSGDerivative(xData, yData, rows, derivative, derivativePosition, SGLeft, SGRight, SGOrder, SGDerivOrder);
299 else
300 takeDerivative(xData, yData, yError, rows, derivative, derivativeError, derivativePosition, interval);
301 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, derivative, rows, yOutputName[i]) ||
302 (yOutputErrorName && yOutputErrorName[i] && !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, derivativeError, rows, yOutputErrorName[i])))
303 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
304 if (yData)
305 free(yData);
306 if (yError)
307 free(yError);
308 yData = yError = NULL;
309 }
310 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, derivativePosition, rows, xName) ||
311 (xErrorName && !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, xError, rows, xErrorName)))
312 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
313 if (!SDDS_WritePage(&SDDSout))
314 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
315 if (xData)
316 free(xData);
317 if (xError)
318 free(xError);
319 xData = xError = NULL;
320 }
321 if (!SDDS_Terminate(&SDDSin) || !SDDS_Terminate(&SDDSout)) {
322 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
323 exit(EXIT_FAILURE);
324 }
325 if (derivative)
326 free(derivative);
327 if (derivativeError)
328 free(derivativeError);
329 if (derivativePosition)
330 free(derivativePosition);
331 return EXIT_SUCCESS;
332}
333
334void takeSGDerivative(double *x, double *y, int64_t rows, double *deriv, double *derivPosition, long left, long right, long sgOrder, long derivOrder) {
335 int64_t i;
336 double spacing, df;
337
338 spacing = (x[rows - 1] - x[0]) / (rows - 1);
339 df = dfactorial(derivOrder) / ipow(spacing, derivOrder);
340 for (i = 0; i < rows; i++) {
341 derivPosition[i] = x[i];
342 deriv[i] = df * y[i];
343 }
344 SavitzkyGolaySmooth(deriv, rows, sgOrder, left, right, derivOrder);
345}
346
347void takeDerivative(double *x, double *y, double *sy, int64_t rows, double *deriv, double *derivSigma, double *derivPosition, long interval) {
348 int64_t i, i1, i2;
349 double dx;
350
351 if (sy) {
352 for (i = 0; i < rows; i++) {
353 if (findDerivIndices(&i1, &i2, interval, i, rows) && (dx = x[i2] - x[i1])) {
354 deriv[i] = (y[i2] - y[i1]) / dx;
355 derivSigma[i] = sqrt(sqr(sy[i1]) + sqr(sy[i2])) / fabs(dx);
356 derivPosition[i] = (x[i2] + x[i1]) / 2;
357 } else
358 deriv[i] = derivSigma[i] = derivPosition[i] = DBL_MAX;
359 }
360 } else {
361 for (i = 0; i < rows; i++) {
362 if (findDerivIndices(&i1, &i2, interval, i, rows) && (dx = x[i2] - x[i1])) {
363 deriv[i] = (y[i2] - y[i1]) / dx;
364 derivPosition[i] = (x[i2] + x[i1]) / 2;
365 } else
366 deriv[i] = derivPosition[i] = DBL_MAX;
367 }
368 }
369}
370
371long findDerivIndices(int64_t *i1, int64_t *i2, long interval, int64_t i, int64_t rows) {
372 int64_t index, rows1;
373
374 rows1 = rows - 1;
375 *i1 = index = i - interval / 2;
376 if (index < 0) {
377 *i2 = 2 * i;
378 *i1 = 0;
379 if (*i1 == *i2)
380 *i2 += 1;
381 if (*i2 < rows)
382 return 1;
383 return 0;
384 }
385 *i2 = i + interval / 2;
386 index = rows1 - *i2;
387 if (index < 0) {
388 *i1 = 2 * i - rows1;
389 *i2 = rows1;
390 if (*i1 == *i2)
391 *i1 -= 1;
392 if (*i1 >= 0)
393 return 1;
394 return 0;
395 }
396 if (*i1 == *i2) {
397 if (*i2 < rows1)
398 *i2 = *i1 + 1;
399 else
400 *i1 = *i1 - 1;
401 }
402 if (*i2 < rows && *i1 >= 0)
403 return 1;
404 return 0;
405}
406
407long setupOutputFile(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *output,
408 char ***yOutputName, char ***yOutputErrorName, char ***yOutputUnits, char *xName, char *xErrorName, char **yName, char **yErrorName, long yNames, char **mainTemplate0, char **errorTemplate0, int32_t interval, long order, short columnMajorOrder) {
409 long i;
410 char *xSymbol, *ySymbol;
411 char *mainTemplate[3] = {"%yNameDeriv", "Derivative w.r.t. %xSymbol of %ySymbol", "d[%ySymbol]/d[%xSymbol]"};
412 char *errorTemplate[3] = {"%yNameDerivSigma", "Sigma of derivative w.r.t. %xSymbol of %ySymbol",
413 "Sigma[d[%ySymbol]/d[%xSymbol]]"};
414 char buffer[1024];
415
416 for (i = 0; i < 3; i++) {
417 if (!mainTemplate0[i]) {
418 if (order != 1) {
419 switch (i) {
420 case 0:
421 /* name */
422 snprintf(buffer, sizeof(buffer), "%%yNameDeriv%ld", order);
423 break;
424 case 1:
425 /* description */
426 snprintf(buffer, sizeof(buffer), "Derivative %ld w.r.t. %%xSymbol of %%ySymbol", order);
427 break;
428 case 2:
429 /* symbol */
430 snprintf(buffer, sizeof(buffer), "d[%s%ld]/d[%s]", "ySymbol", order, "xSymbol"); // Adjusted for clarity
431 break;
432 }
433 cp_str(&mainTemplate[i], buffer);
434 }
435 } else {
436 mainTemplate[i] = mainTemplate0[i];
437 }
438 if (errorTemplate0[i]) {
439 errorTemplate[i] = errorTemplate0[i];
440 }
441 }
442
443 *yOutputName = tmalloc(sizeof(**yOutputName) * yNames);
444 *yOutputErrorName = tmalloc(sizeof(**yOutputErrorName) * yNames);
445 *yOutputUnits = tmalloc(sizeof(**yOutputUnits) * yNames);
446 if (!SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL, "sddsderiv output", output) ||
447 SDDS_DefineParameter1(SDDSout, "derivInterval", NULL, NULL, NULL, NULL, SDDS_LONG, &interval) < 0)
448 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
449 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, xName, NULL) ||
450 (xErrorName && !SDDS_TransferColumnDefinition(SDDSout, SDDSin, xErrorName, NULL)))
451 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
452 if (SDDS_GetColumnInformation(SDDSout, "symbol", &xSymbol, SDDS_GET_BY_NAME, xName) != SDDS_STRING) {
453 fprintf(stderr, "error: problem getting symbol for column %s\n", xName);
454 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
455 }
456 if (!xSymbol)
457 SDDS_CopyString(&xSymbol, xName);
458 for (i = 0; i < yNames; i++) {
459 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, yName[i], NULL)) {
460 fprintf(stderr, "error: problem transferring definition for column %s\n", yName[i]);
461 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
462 }
463 if (SDDS_GetColumnInformation(SDDSout, "symbol", &ySymbol, SDDS_GET_BY_NAME, yName[i]) != SDDS_STRING) {
464 fprintf(stderr, "error: problem getting symbol for column %s\n", yName[i]);
465 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
466 }
467 if (!ySymbol || SDDS_StringIsBlank(ySymbol))
468 SDDS_CopyString(&ySymbol, yName[i]);
469 (*yOutputUnits)[i] = divideColumnUnits(SDDSout, yName[i], xName);
470 (*yOutputName)[i] = changeInformation(SDDSout, yName[i], yName[i], ySymbol, xName, xSymbol, mainTemplate, (*yOutputUnits)[i]);
471 if (yErrorName || xErrorName) {
472 if (yErrorName && yErrorName[i]) {
473 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, yErrorName[i], NULL)) {
474 fprintf(stderr, "error: problem transferring definition for column %s\n", yErrorName[i]);
475 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
476 }
477 (*yOutputErrorName)[i] = changeInformation(SDDSout, yErrorName[i], yName[i], ySymbol, xName, xSymbol, errorTemplate, (*yOutputUnits)[i]);
478 } else {
479 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, yName[i], NULL)) {
480 fprintf(stderr, "error: problem transferring error definition for column %s\n", yName[i]);
481 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
482 }
483 (*yOutputErrorName)[i] = changeInformation(SDDSout, yName[i], yName[i], ySymbol, xName, xSymbol, errorTemplate, (*yOutputUnits)[i]);
484 }
485 } else {
486 (*yOutputErrorName)[i] = NULL;
487 }
488 }
489 if (columnMajorOrder != -1)
490 SDDSout->layout.data_mode.column_major = columnMajorOrder;
491 else
492 SDDSout->layout.data_mode.column_major = SDDSin->layout.data_mode.column_major;
493 if (!SDDS_TransferAllParameterDefinitions(SDDSout, SDDSin, SDDS_TRANSFER_KEEPOLD) ||
494 !SDDS_WriteLayout(SDDSout))
495 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
496 return 1;
497}
498
499char *changeInformation(SDDS_DATASET *SDDSout, char *name, char *nameRoot, char *symbolRoot, char *xName, char *xSymbol, char **template, char *newUnits) {
500 char buffer1[SDDS_MAXLINE], buffer2[SDDS_MAXLINE], *ptr;
501
502 if (!SDDS_ChangeColumnInformation(SDDSout, "units", newUnits, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, name))
503 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
504
505 makeSubstitutions(buffer1, buffer2, template[2], nameRoot, symbolRoot, xName, xSymbol);
506 if (!SDDS_ChangeColumnInformation(SDDSout, "symbol", buffer2, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, name))
507 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
508
509 makeSubstitutions(buffer1, buffer2, template[1], nameRoot, symbolRoot, xName, xSymbol);
510 if (!SDDS_ChangeColumnInformation(SDDSout, "description", buffer2, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, name))
511 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
512
513 makeSubstitutions(buffer1, buffer2, template[0], nameRoot, symbolRoot, xName, xSymbol);
514 if (!SDDS_ChangeColumnInformation(SDDSout, "name", buffer2, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, name))
515 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
516 SDDS_CopyString(&ptr, buffer2);
517 return ptr;
518}
519
520void makeSubstitutions(char *buffer1, char *buffer2, char *template, char *nameRoot, char *symbolRoot, char *xName, char *xSymbol) {
521 strcpy(buffer2, template);
522 replace_string(buffer1, buffer2, "%ySymbol", symbolRoot);
523 replace_string(buffer2, buffer1, "%xSymbol", xSymbol);
524 replace_string(buffer1, buffer2, "%yName", nameRoot);
525 replace_string(buffer2, buffer1, "%xName", xName);
526 strcpy(buffer1, buffer2);
527}
528
529long checkErrorNames(char **yErrorName, long yNames) {
530 long i;
531 if (yErrorName[0]) {
532 for (i = 1; i < yNames; i++)
533 if (!yErrorName[i])
534 return 0;
535 } else {
536 for (i = 1; i < yNames; i++)
537 if (yErrorName[i])
538 return 0;
539 }
540 return 1;
541}
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_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.
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_ChangeColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Modifies a specific field in a column definition within the SDDS dataset.
Definition SDDS_info.c:364
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
Definition SDDS_info.c:41
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_DefineParameter1(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, void *fixed_value)
Defines a data parameter with a fixed numerical value.
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_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_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
char * SDDS_FindColumn(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Finds the first column in the SDDS dataset that matches the specified criteria.
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
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#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
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
double dfactorial(long n)
Computes the factorial of a given number as a double.
Definition factorial.c:43
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
Definition ipow.c:33
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 replace_string(char *t, char *s, char *orig, char *repl)
Replace all occurrences of one string with another string.
long SavitzkyGolaySmooth(double *data, long rows, long order, long nLeft, long nRight, long derivativeOrder)
Applies Savitzky-Golay smoothing or differentiation to a data array.
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.