SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsslopes.c
Go to the documentation of this file.
1/**
2 * @file sddsslopes.c
3 * @brief Computes straight-line fits of numerical column data from an SDDS experiment output file.
4 *
5 * @details
6 * This program reads an SDDS input file, performs linear fits on specified columns using a defined
7 * independent variable, and writes the slopes and intercepts to an output file. It supports options
8 * to generate residuals, handle sigma values for error calculations, and configure output formats and ordering.
9 *
10 * @section Usage
11 * ```
12 * sddsslopes [<inputfile>] [<outputfile>]
13 * [-pipe=[input][,output]]
14 * -independentVariable=<columnName>
15 * [-range=<lower>,<upper>]
16 * [-columns=<list-of-names>]
17 * [-excludeColumns=<list-of-names>]
18 * [-sigma[=generate][,minimum=<val>]
19 * [-residual=<file>]
20 * [-ascii]
21 * [-verbose]
22 * [-majorOrder=row|column]
23 * [-nowarnings]
24 * ```
25 *
26 * @section Options
27 * | Required | Description |
28 * |---------------------------------------|---------------------------------------------------------------------------------------|
29 * | `-independentVariable` | Specifies the independent variable column for the linear fits. |
30 *
31 * | Optional | Description |
32 * |---------------------------------------|---------------------------------------------------------------------------------------|
33 * | `-pipe` | Read input or write output through a pipe. |
34 * | `-range` | Specifies the range of the independent variable for fitting. |
35 * | `-columns` | Comma-separated list of columns to perform fits on. |
36 * | `-excludeColumns` | Comma-separated list of columns to exclude from fitting. |
37 * | `-sigma` | Calculates errors using sigma columns or generates them. |
38 * | `-residual` | Outputs residuals of the linear fit to a specified file. |
39 * | `-ascii` | Outputs the slopes file in ASCII format (default is binary). |
40 * | `-verbose` | Enables verbose output to stderr. |
41 * | `-majorOrder` | Specifies output file ordering. |
42 * | `-nowarnings` | Suppresses warning messages. |
43 *
44 * @subsection Incompatibilities
45 * - For `-sigma`:
46 * - `generate` and `minimum=<val>` cannot be used together.
47 *
48 * @copyright
49 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
50 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
51 *
52 * @license
53 * This file is distributed under the terms of the Software License Agreement
54 * found in the file LICENSE included with this distribution.
55 *
56 * @author
57 * L. Emery, M. Borland, C. Saunders, R. Soliday, H. Shang
58 */
59
60#include "mdb.h"
61#include "scan.h"
62#include "match_string.h"
63#include "SDDS.h"
64
65/* Enumeration for option types */
66enum option_type {
67 CLO_INDEPENDENT_COLUMN,
68 CLO_COLUMNS,
69 CLO_EXCLUDE,
70 CLO_VERBOSE,
71 CLO_SIGMA,
72 CLO_ASCII,
73 CLO_PIPE,
74 CLO_RESIDUAL,
75 CLO_RANGE,
76 CLO_MAJOR_ORDER,
77 CLO_NO_WARNINGS,
78 N_OPTIONS
79};
80
81char *commandline_option[N_OPTIONS] = {
82 "independentVariable",
83 "columns",
84 "excludeColumns",
85 "verbose",
86 "sigma",
87 "ascii",
88 "pipe",
89 "residual",
90 "range",
91 "majorOrder",
92 "nowarnings"
93};
94
95#define SIGMA_GENERATE 0
96#define SIGMA_OPTIONS 1
97char *sigma_option[SIGMA_OPTIONS] = {
98 "generate"
99};
100
101#define DEFAULT_EXCLUDED_COLUMNS 1
102char *defaultExcludedColumn[DEFAULT_EXCLUDED_COLUMNS] = {
103 "Time",
104};
105
106static char *USAGE =
107 "sddsslopes [<inputfile>] [<outputfile>]\n"
108 " [-pipe=[input][,output]]\n"
109 " -independentVariable=<columnName> \n"
110 " [-range=<lower>,<upper>]\n"
111 " [-columns=<list-of-names>] \n"
112 " [-excludeColumns=<list-of-names>] \n"
113 " [-sigma[=generate][,minimum=<val>]\n"
114 " [-residual=<file>] \n"
115 " [-ascii] \n"
116 " [-verbose] \n"
117 " [-majorOrder=row|column]\n"
118 " [-nowarnings]\n"
119 "Options:\n"
120 " -pipe=[input][,output] Read input or write output from/to a pipe.\n"
121 " -independentVariable=<columnName> Specify the independent variable column.\n"
122 " -range=<lower>,<upper> Specify the range of the independent variable for fitting.\n"
123 " -columns=<list-of-names> Comma-separated list of columns to perform fits on.\n"
124 " -excludeColumns=<list-of-names> Comma-separated list of columns to exclude from fitting.\n"
125 " -sigma[=generate][,minimum=<val>] Calculate errors using sigma columns or generate them.\n"
126 " -residual=<file> Output file for residuals of the linear fit.\n"
127 " -ascii Output slopes file in ASCII mode (default is binary).\n"
128 " -verbose Enable verbose output to stderr.\n"
129 " -majorOrder=<row|column> Specify output file ordering.\n"
130 " -nowarnings Suppress warning messages.\n\n"
131 "Description:\n"
132 " Performs straight line fits on numerical columns in the input SDDS file using a specified\n"
133 " independent variable. Outputs the slope and intercept for each selected column.\n"
134 " The independent variable column is excluded from the output but its name is stored as a parameter.\n\n"
135 "Example:\n"
136 " sddsslopes data_input.sdds data_output.sdds -independentVariable=Time -columns=X,Y,Z -verbose\n"
137 "Program by Louis Emery, ANL (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
138
139long set_multicolumn_flags(SDDS_TABLE *SDDSin, char ***column, int32_t *columns, char **exclude, long excludes);
140
141int main(int argc, char **argv) {
142 SCANNED_ARG *scanned;
143 SDDS_TABLE inputPage, outputPage, residualPage;
144 char *inputfile, *outputfile;
145 char **column, **excludeColumn;
146 int32_t columns;
147 long excludeColumns;
148 char *indColumnName;
149 long verbose;
150 long iArg, ipage;
151 double *indVar, *indVarOrig;
152 char *indVarUnits;
153 char **intColumn, **slopeColumn, **slopeSigmaColumn, **interceptSigmaColumn;
154 char *Units, *slopeUnits;
155 double *depVar, *depVarOrig;
156 long order;
157 double *coef, *coefsigma, *weight, *diff, *diffOrig, chi;
158 long iCol;
159 int64_t i, j, rows, rowsOrig, iRow;
160 double rmsResidual;
161 double slopeSigma, interceptSigma;
162 char **sigmaColumn, **chiSquaredColumn;
163 long *sigmaColumnExists;
164 long doSlopeSigma, generateSigma, doPreliminaryFit;
165 int64_t validSigmas;
166 double sigmaSum, averageSigma, minSigma;
167 long ascii;
168 char *residualFile;
169 unsigned long pipeFlags;
170 long tmpfile_used, noWarnings;
171 long unsigned int majorOrderFlag;
172 double xMin, xMax;
173 short columnMajorOrder = -1;
174
175 indVar = indVarOrig = depVar = depVarOrig = coef = coefsigma = weight = diff = NULL;
176 intColumn = slopeColumn = slopeSigmaColumn = interceptSigmaColumn = sigmaColumn = chiSquaredColumn = NULL;
177 slopeUnits = NULL;
178 sigmaColumnExists = NULL;
179
181 argc = scanargs(&scanned, argc, argv);
182 if (argc == 1)
183 bomb(NULL, USAGE);
184
185 inputfile = outputfile = NULL;
186 columns = excludeColumns = 0;
187 column = excludeColumn = NULL;
188 indColumnName = NULL;
189 verbose = 0;
190 doSlopeSigma = 0;
191 generateSigma = 0;
192 minSigma = 0;
193 doPreliminaryFit = 0;
194 ascii = 0;
195 pipeFlags = 0;
196 tmpfile_used = 0;
197 noWarnings = 0;
198 residualFile = NULL;
199 xMin = xMax = 0;
200
201 for (iArg = 1; iArg < argc; iArg++) {
202 if (scanned[iArg].arg_type == OPTION) {
203 delete_chars(scanned[iArg].list[0], "_");
204 switch (match_string(scanned[iArg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
205 case CLO_MAJOR_ORDER:
206 majorOrderFlag = 0;
207 scanned[iArg].n_items--;
208 if (scanned[iArg].n_items > 0 &&
209 (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
210 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
211 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
212 SDDS_Bomb("invalid -majorOrder syntax/values");
213 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
214 columnMajorOrder = 1;
215 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
216 columnMajorOrder = 0;
217 break;
218 case CLO_INDEPENDENT_COLUMN:
219 if (!(indColumnName = scanned[iArg].list[1]))
220 SDDS_Bomb("no string given for option -independentVariable");
221 break;
222 case CLO_COLUMNS:
223 if (columns)
224 SDDS_Bomb("only one -columns option may be given");
225 if (scanned[iArg].n_items < 2)
226 SDDS_Bomb("invalid -columns syntax");
227 column = tmalloc(sizeof(*column) * (columns = scanned[iArg].n_items - 1));
228 for (i = 0; i < columns; i++)
229 column[i] = scanned[iArg].list[i + 1];
230 break;
231 case CLO_EXCLUDE:
232 if (excludeColumns)
233 SDDS_Bomb("only one -excludecolumns option may be given");
234 if (scanned[iArg].n_items < 2)
235 SDDS_Bomb("invalid -excludecolumns syntax");
236 excludeColumn = tmalloc(sizeof(*excludeColumn) * (excludeColumns = scanned[iArg].n_items - 1));
237 for (i = 0; i < excludeColumns; i++)
238 excludeColumn[i] = scanned[iArg].list[i + 1];
239 break;
240 case CLO_VERBOSE:
241 verbose = 1;
242 break;
243 case CLO_ASCII:
244 ascii = 1;
245 break;
246 case CLO_PIPE:
247 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
248 SDDS_Bomb("invalid -pipe syntax");
249 break;
250 case CLO_SIGMA:
251 doSlopeSigma = 1;
252 if (scanned[iArg].n_items > 1) {
253 unsigned long sigmaFlags = 0;
254 scanned[iArg].n_items--;
255 if (!scanItemList(&sigmaFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
256 "generate", -1, NULL, 0, 1,
257 "minimum", SDDS_DOUBLE, &minSigma, 1, 0,
258 NULL) ||
259 minSigma < 0)
260 SDDS_Bomb("invalid -sigma syntax");
261 if (sigmaFlags & 1)
262 generateSigma = 1;
263 }
264 break;
265 case CLO_RESIDUAL:
266 if (!(residualFile = scanned[iArg].list[1])) {
267 fprintf(stderr, "No file specified in -residual option.\n");
268 exit(EXIT_FAILURE);
269 }
270 break;
271 case CLO_RANGE:
272 if (scanned[iArg].n_items != 3 ||
273 1 != sscanf(scanned[iArg].list[1], "%lf", &xMin) ||
274 1 != sscanf(scanned[iArg].list[2], "%lf", &xMax) ||
275 xMin >= xMax)
276 SDDS_Bomb("incorrect -range syntax");
277 break;
278 case CLO_NO_WARNINGS:
279 noWarnings = 1;
280 break;
281 default:
282 SDDS_Bomb("unrecognized option given");
283 break;
284 }
285 } else {
286 if (!inputfile)
287 inputfile = scanned[iArg].list[0];
288 else if (!outputfile)
289 outputfile = scanned[iArg].list[0];
290 else
291 SDDS_Bomb("too many filenames given");
292 }
293 }
294
295 if (residualFile && outputfile) {
296 if (!strcmp(residualFile, outputfile)) {
297 fprintf(stderr, "Residual file can't be the same as the output file.\n");
298 exit(EXIT_FAILURE);
299 }
300 }
301
302 processFilenames("sddsslopes", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
303
304 if (!indColumnName) {
305 fprintf(stderr, "independentVariable not given\n");
306 exit(EXIT_FAILURE);
307 }
308
309 if (!excludeColumns) {
310 excludeColumn = defaultExcludedColumn;
311 excludeColumns = DEFAULT_EXCLUDED_COLUMNS;
312 }
313
314 if (verbose)
315 fprintf(stderr, "Reading file %s.\n", inputfile);
316 if (!SDDS_InitializeInput(&inputPage, inputfile))
317 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
318 while (0 < (ipage = SDDS_ReadTable(&inputPage))) {
319 if (verbose) {
320 fprintf(stderr, "working on page %ld\n", ipage);
321 }
322 rows = SDDS_CountRowsOfInterest(&inputPage);
323 rowsOrig = rows;
324 /*************************************\
325 * make array of independent variable
326 \*************************************/
327 if (ipage == 1) {
328 indVar = (double *)malloc(sizeof(*indVar) * rows);
329 if (!indVar) {
330 fprintf(stderr, "Memory allocation failed for indVar.\n");
331 exit(EXIT_FAILURE);
332 }
333 } else {
334 indVar = (double *)realloc(indVar, sizeof(*indVar) * rows);
335 if (!indVar) {
336 fprintf(stderr, "Memory reallocation failed for indVar.\n");
337 exit(EXIT_FAILURE);
338 }
339 }
340 if (ipage == 1) {
341 if (!SDDS_FindColumn(&inputPage, FIND_NUMERIC_TYPE, indColumnName, NULL)) {
342 fprintf(stderr, "Something wrong with column %s.\n", indColumnName);
343 SDDS_CheckColumn(&inputPage, indColumnName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr);
344 exit(EXIT_FAILURE);
345 }
346 }
347 /* filter out the specified range in independent variable */
348 if (xMin != xMax) {
349 if (!(indVarOrig = SDDS_GetColumnInDoubles(&inputPage, indColumnName)))
350 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
351 for (i = j = 0; i < rowsOrig; i++) {
352 if (indVarOrig[i] <= xMax && indVarOrig[i] >= xMin) {
353 indVar[j] = indVarOrig[i];
354 j++;
355 }
356 }
357 } else {
358 if (!(indVar = SDDS_GetColumnInDoubles(&inputPage, indColumnName)))
359 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
360 }
361 if (ipage == 1) {
362 if (!SDDS_GetColumnInformation(&inputPage, "units", &indVarUnits, SDDS_GET_BY_NAME, indColumnName))
363 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
364 if (!indVarUnits) {
365 indVarUnits = (char *)malloc(sizeof(*indVarUnits));
366 indVarUnits[0] = 0;
367 }
368 }
369 /************************************\
370 * initialize residual file
371 \************************************/
372 if (residualFile) {
373 if (ipage == 1) {
374 if (!SDDS_InitializeOutput(&residualPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, "Residual of 2-term fit", NULL, outputfile) ||
375 !SDDS_InitializeCopy(&residualPage, &inputPage, residualFile, "w"))
376 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
377 if (columnMajorOrder != -1)
378 residualPage.layout.data_mode.column_major = columnMajorOrder;
379 else
380 residualPage.layout.data_mode.column_major = inputPage.layout.data_mode.column_major;
381 if (!SDDS_WriteLayout(&residualPage))
382 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
383 }
384 if (!SDDS_CopyPage(&residualPage, &inputPage))
385 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
386 }
387
388 /************************************\
389 * get columns of interest. use set_multicolumn_flags to simply
390 * return new values for array column.
391 \************************************/
392 if (!set_multicolumn_flags(&inputPage, &column, &columns, excludeColumn, excludeColumns)) {
393 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
394 exit(EXIT_FAILURE);
395 }
396 /************************************\
397 * make column names for the output
398 \************************************/
399 if (ipage == 1) {
400 intColumn = (char **)malloc((sizeof(char *) * columns));
401 slopeColumn = (char **)malloc((sizeof(char *) * columns));
402 if (doSlopeSigma) {
403 slopeSigmaColumn = (char **)malloc((sizeof(char *) * columns));
404 interceptSigmaColumn = (char **)malloc((sizeof(char *) * columns));
405 chiSquaredColumn = (char **)malloc((sizeof(char *) * columns));
406 }
407 for (i = 0; i < columns; i++) {
408 intColumn[i] = (char *)malloc((sizeof(char) * (strlen(column[i]) + strlen("Intercept") + 1)));
409 snprintf(intColumn[i], strlen(column[i]) + strlen("Intercept") + 1, "%sIntercept", column[i]);
410
411 slopeColumn[i] = (char *)malloc((sizeof(char) * (strlen(column[i]) + strlen("Slope") + 1)));
412 snprintf(slopeColumn[i], strlen(column[i]) + strlen("Slope") + 1, "%sSlope", column[i]);
413
414 if (doSlopeSigma) {
415 slopeSigmaColumn[i] = (char *)malloc((sizeof(char) * (strlen(column[i]) + strlen("SlopeSigma") + 1)));
416 snprintf(slopeSigmaColumn[i], strlen(column[i]) + strlen("SlopeSigma") + 1, "%sSlopeSigma", column[i]);
417
418 interceptSigmaColumn[i] = (char *)malloc((sizeof(char) * (strlen(column[i]) + strlen("InterceptSigma") + 1)));
419 snprintf(interceptSigmaColumn[i], strlen(column[i]) + strlen("InterceptSigma") + 1, "%sInterceptSigma", column[i]);
420
421 chiSquaredColumn[i] = (char *)malloc((sizeof(char) * (strlen(column[i]) + strlen("ChiSquared") + 1)));
422 snprintf(chiSquaredColumn[i], strlen(column[i]) + strlen("ChiSquared") + 1, "%sChiSquared", column[i]);
423 }
424 }
425 }
426 /************************************\
427 * Write layout for output file
428 \************************************/
429 if (ipage == 1) {
430 if (verbose)
431 fprintf(stderr, "Opening file %s.\n", outputfile);
432 if (!SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, "2-term fit", NULL, outputfile) ||
433 0 > SDDS_DefineParameter(&outputPage, "InputFile", "InputFile", NULL, "InputFile", NULL, SDDS_STRING, 0) ||
434 0 > SDDS_DefineColumn(&outputPage, "IndependentVariable", NULL, NULL, NULL, NULL, SDDS_STRING, 0))
435 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
436 if (columnMajorOrder != -1)
437 outputPage.layout.data_mode.column_major = columnMajorOrder;
438 else
439 outputPage.layout.data_mode.column_major = inputPage.layout.data_mode.column_major;
440 for (iCol = 0; iCol < columns; iCol++) {
441 if (!SDDS_GetColumnInformation(&inputPage, "units", &Units, SDDS_GET_BY_NAME, column[iCol]))
442 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
443 if (!Units) {
444 Units = (char *)malloc(sizeof(*Units));
445 Units[0] = 0;
446 }
447 if (0 > SDDS_DefineColumn(&outputPage, intColumn[iCol], NULL, Units, NULL, NULL, SDDS_DOUBLE, 0))
448 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
449 /* units for slopes columns */
450 if (strlen(indVarUnits) && strlen(Units)) {
451 slopeUnits = (char *)malloc(sizeof(*slopeUnits) * (strlen(Units) + strlen(indVarUnits) + 2));
452 snprintf(slopeUnits, strlen(Units) + strlen(indVarUnits) + 2, "%s/%s", Units, indVarUnits);
453 }
454 if (strlen(indVarUnits) && !strlen(Units)) {
455 slopeUnits = (char *)malloc(sizeof(*slopeUnits) * (strlen(indVarUnits) + 2));
456 snprintf(slopeUnits, strlen(indVarUnits) + 2, "1/%s", indVarUnits);
457 }
458 if (!strlen(indVarUnits) && strlen(Units)) {
459 slopeUnits = (char *)malloc(sizeof(*slopeUnits) * (strlen(Units) + 1));
460 strcpy(slopeUnits, indVarUnits); // Fix this
461 }
462 if (!strlen(indVarUnits) && !strlen(Units)) {
463 slopeUnits = (char *)malloc(sizeof(*slopeUnits));
464 strcpy(slopeUnits, "");
465 }
466 if (0 > SDDS_DefineColumn(&outputPage, slopeColumn[iCol], NULL, slopeUnits, NULL, NULL, SDDS_DOUBLE, 0))
467 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
468 if (doSlopeSigma) {
469 if (0 > SDDS_DefineColumn(&outputPage, interceptSigmaColumn[iCol], NULL, Units, NULL, NULL, SDDS_DOUBLE, 0) ||
470 0 > SDDS_DefineColumn(&outputPage, slopeSigmaColumn[iCol], NULL, slopeUnits, NULL, NULL, SDDS_DOUBLE, 0) ||
471 0 > SDDS_DefineColumn(&outputPage, chiSquaredColumn[iCol], NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0))
472 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
473 }
474 free(slopeUnits);
475 }
476 if (!SDDS_WriteLayout(&outputPage))
477 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
478 }
479
480 if (!SDDS_StartTable(&outputPage, 1) ||
481 !SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, "InputFile", inputfile ? inputfile : "pipe", NULL) ||
482 !SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, 0, "IndependentVariable", indColumnName, NULL))
483 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
484
485 /* determine which included columns has a Sigma column defined in the input file */
486 if (ipage == 1) {
487 sigmaColumn = (char **)malloc(sizeof(*sigmaColumn) * columns);
488 sigmaColumnExists = (long *)malloc(columns * sizeof(*sigmaColumnExists));
489 for (iCol = 0; iCol < columns; iCol++) {
490 sigmaColumn[iCol] = (char *)malloc(sizeof(**sigmaColumn) * (strlen(column[iCol]) + strlen("Sigma") + 1));
491 snprintf(sigmaColumn[iCol], strlen(column[iCol]) + strlen("Sigma") + 1, "%sSigma", column[iCol]);
492 switch (SDDS_CheckColumn(&inputPage, sigmaColumn[iCol], NULL, SDDS_DOUBLE, NULL)) {
493 case SDDS_CHECK_WRONGUNITS:
494 case SDDS_CHECK_OKAY:
495 sigmaColumnExists[iCol] = 1;
496 break;
497 default:
498 /* try other possible spelling */
499 snprintf(sigmaColumn[iCol], strlen("Sigma") + strlen(column[iCol]) + 1, "Sigma%s", column[iCol]);
500 switch (SDDS_CheckColumn(&inputPage, sigmaColumn[iCol], NULL, SDDS_DOUBLE, NULL)) {
501 case SDDS_CHECK_WRONGUNITS:
502 case SDDS_CHECK_OKAY:
503 sigmaColumnExists[iCol] = 1;
504 break;
505 default:
506 sigmaColumnExists[iCol] = 0;
507 }
508 break;
509 }
510 }
511 }
512
513 if (ipage == 1) {
514 weight = (double *)malloc(sizeof(*weight) * rows);
515 diff = (double *)malloc(sizeof(*diff) * rows);
516 order = 1;
517 coef = (double *)malloc(sizeof(*coef) * (order + 1));
518 coefsigma = (double *)malloc(sizeof(*coefsigma) * (order + 1));
519 if (!weight || !diff || !coef || !coefsigma) {
520 fprintf(stderr, "Memory allocation failed.\n");
521 exit(EXIT_FAILURE);
522 }
523 } else {
524 weight = (double *)realloc(weight, sizeof(*weight) * rows);
525 diff = (double *)realloc(diff, sizeof(*diff) * rows);
526 coef = (double *)realloc(coef, sizeof(*coef) * (order + 1));
527 coefsigma = (double *)realloc(coefsigma, sizeof(*coefsigma) * (order + 1));
528 if (!weight || !diff || !coef || !coefsigma) {
529 fprintf(stderr, "Memory reallocation failed.\n");
530 exit(EXIT_FAILURE);
531 }
532 }
533
534 if (ipage == 1) {
535 depVar = (double *)malloc(sizeof(*depVar) * rows);
536 if (!depVar) {
537 fprintf(stderr, "Memory allocation failed for depVar.\n");
538 exit(EXIT_FAILURE);
539 }
540 } else {
541 depVar = (double *)realloc(depVar, sizeof(*depVar) * rows);
542 if (!depVar) {
543 fprintf(stderr, "Memory reallocation failed for depVar.\n");
544 exit(EXIT_FAILURE);
545 }
546 }
547 for (iCol = 0; iCol < columns; iCol++) {
548 if (verbose)
549 fprintf(stderr, "Doing column %s.\n", column[iCol]);
550 /* filter out the specified range in independent variable */
551 if (xMin != xMax) {
552 if (!(depVarOrig = (double *)SDDS_GetColumnInDoubles(&inputPage, column[iCol])))
553 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
554 for (i = j = 0; i < rowsOrig; i++) {
555 if (xMin <= indVarOrig[i] && indVarOrig[i] <= xMax) {
556 depVar[j] = depVarOrig[i];
557 j++;
558 }
559 }
560 rows = j;
561 } else {
562 if (!(depVar = SDDS_GetColumnInDoubles(&inputPage, column[iCol])))
563 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
564 }
565
566 /*********************
567 three possibilities:
568 1) don't do or write slope errors. (doSlopeSigma=0)
569 do one lsf call with all weights = 1
570 2) calculated slope errors from sigma columns in the input file.
571 (doSlopeSigma=1 && generateSigma=0 && sigmaColumnExists[iCol]=1 )
572 do one lsf call with weights from sigma columns
573 3) calculate slope errors from generated sigma from a preliminary fit.
574 (doSlopeSigma=1 && (generateSigma=1 || sigmaColumnExists[iCol]=NULL)
575 do preliminary fit to generate sigma
576 *********************/
577
578 for (iRow = 0; iRow < rows; iRow++)
579 weight[iRow] = 1;
580 if (doSlopeSigma) {
581 /*********************
582 check validity of sigma column values
583 *********************/
584 if (!generateSigma && sigmaColumnExists[iCol]) {
585 if (verbose)
586 fprintf(stderr, "\tUsing column %s for sigma.\n", sigmaColumn[iCol]);
587 if (!(weight = SDDS_GetColumnInDoubles(&inputPage, sigmaColumn[iCol])))
588 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
589 if (minSigma > 0) {
590 for (iRow = 0; iRow < rows; iRow++) {
591 if (weight[iRow] < minSigma)
592 weight[iRow] = minSigma;
593 }
594 }
595 /* check for zero weight values which will give lsfn problems */
596 validSigmas = rows;
597 sigmaSum = 0;
598 for (iRow = 0; iRow < rows; iRow++) {
599 sigmaSum += weight[iRow];
600 if (!weight[iRow]) {
601 validSigmas--;
602 /*
603 fprintf(stderr,"Warning: %s of row number %ld is zero. Using average sigma.\n",sigmaColumn[iCol],iRow); */
604 }
605 }
606 if (!validSigmas) {
607 if (!noWarnings)
608 fprintf(stderr, "Warning: All sigmas are zero.\n");
609 doPreliminaryFit = 1;
610 } else if (validSigmas != rows) {
611 /* fix some sigmas */
612 averageSigma = sigmaSum / validSigmas;
613 if (!noWarnings)
614 fprintf(stderr, "Warning: replacing %" PRId64 " invalid sigmas with average (%e)\n", rows - validSigmas, averageSigma);
615 for (iRow = 0; iRow < rows; iRow++) {
616 if (!weight[iRow]) {
617 weight[iRow] = averageSigma;
618 }
619 }
620 }
621 } else {
622 doPreliminaryFit = 1;
623 }
624 }
625
626 if (doPreliminaryFit) {
627 if (verbose)
628 fprintf(stderr, "\tGenerating sigmas from rms residual of a preliminary fit.\n");
629 if (!(lsfn(indVar, depVar, weight, rows, order, coef, coefsigma, &chi, diff))) {
630 fprintf(stderr, "Problem with call to lsfn\n.");
631 exit(EXIT_FAILURE);
632 }
633 rmsResidual = 0;
634 /* calculate rms residual */
635 for (iRow = 0; iRow < rows; iRow++) {
636 rmsResidual += sqr(diff[iRow]);
637 }
638 rmsResidual = sqrt(rmsResidual / (rows));
639 for (iRow = 0; iRow < rows; iRow++) {
640 weight[iRow] = rmsResidual;
641 }
642 if (minSigma > 0) {
643 for (iRow = 0; iRow < rows; iRow++) {
644 if (weight[iRow] < minSigma)
645 weight[iRow] = minSigma;
646 }
647 }
648 }
649
650 if (!(lsfn(indVar, depVar, weight, rows, order, coef, coefsigma, &chi, diff))) {
651 fprintf(stderr, "Problem with call to lsfn\n.");
652 exit(EXIT_FAILURE);
653 }
654 if (!SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, 0,
655 intColumn[iCol], coef[0], slopeColumn[iCol], coef[1], NULL))
656 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
657 if (doSlopeSigma) {
658 interceptSigma = coefsigma[0];
659 slopeSigma = coefsigma[1];
660 if (!SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, 0,
661 chiSquaredColumn[iCol], chi, interceptSigmaColumn[iCol],
662 interceptSigma, slopeSigmaColumn[iCol], slopeSigma, NULL))
663 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
664 }
665 if (residualFile) {
666 if (xMin != xMax) {
667 /* calculate the residuals for the whole column explicitly since there
668 are points outside the range of which the lsf call did not calculate
669 the difference. */
670 diffOrig = (double *)malloc(rowsOrig * sizeof(double));
671 if (!diffOrig) {
672 fprintf(stderr, "Memory allocation failed for diffOrig.\n");
673 exit(EXIT_FAILURE);
674 }
675 for (i = 0; i < rowsOrig; i++) {
676 diffOrig[i] = depVarOrig[i] - coef[0] - coef[1] * indVarOrig[i];
677 }
678 if (!SDDS_SetColumnFromDoubles(&residualPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE,
679 diffOrig, rowsOrig, column[iCol]))
680 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
681 free(diffOrig);
682 } else {
683 if (!SDDS_SetColumnFromDoubles(&residualPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE,
684 diff, rows, column[iCol]))
685 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
686 }
687 }
688 }
689
690 if (residualFile) {
691 if (!SDDS_WriteTable(&residualPage))
692 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
693 }
694
695 if (!SDDS_WriteTable(&outputPage))
696 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
697 }
698
699 if (residualFile) {
700 if (!SDDS_Terminate(&residualPage))
701 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
702 }
703 if (!SDDS_Terminate(&inputPage) || !SDDS_Terminate(&outputPage))
704 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
705
706 if (tmpfile_used && !replaceFileAndBackUp(inputfile, outputfile))
707 exit(EXIT_FAILURE);
708
709 /* Free allocated memory */
710 free(indVar);
711 free(indVarOrig);
712 free(depVar);
713 free(depVarOrig);
714 free(coef);
715 free(coefsigma);
716 free(weight);
717 free(diff);
718 if (intColumn) {
719 for (i = 0; i < columns; i++) {
720 free(intColumn[i]);
721 free(slopeColumn[i]);
722 if (doSlopeSigma) {
723 free(slopeSigmaColumn[i]);
724 free(interceptSigmaColumn[i]);
725 free(chiSquaredColumn[i]);
726 }
727 free(sigmaColumn[i]);
728 }
729 free(intColumn);
730 free(slopeColumn);
731 if (doSlopeSigma) {
732 free(slopeSigmaColumn);
733 free(interceptSigmaColumn);
734 free(chiSquaredColumn);
735 }
736 free(sigmaColumn);
737 free(sigmaColumnExists);
738 }
739 free(column);
740 if (excludeColumn && excludeColumn != defaultExcludedColumn)
741 free(excludeColumn);
742
743 return EXIT_SUCCESS;
744}
745
746long set_multicolumn_flags(SDDS_TABLE *SDDSin, char ***column, int32_t *columns, char **exclude, long excludes) {
747 long index, i;
748
749 if (*column) {
750 SDDS_SetColumnFlags(SDDSin, 0);
751 for (i = 0; i < *columns; i++) {
752 if (!SDDS_SetColumnsOfInterest(SDDSin, SDDS_MATCH_STRING, (*column)[i], SDDS_OR))
753 return 0;
754 }
755 } else {
756 SDDS_SetColumnFlags(SDDSin, 1);
757 if (!(*column = SDDS_GetColumnNames(SDDSin, columns)) || *columns == 0) {
758 SDDS_SetError("no columns found");
759 return 0;
760 }
761 for (i = 0; i < *columns; i++) {
762 index = SDDS_GetColumnIndex(SDDSin, (*column)[i]);
763 if (!SDDS_NUMERIC_TYPE(SDDS_GetColumnType(SDDSin, index)) &&
764 !SDDS_AssertColumnFlags(SDDSin, SDDS_INDEX_LIMITS, index, index, 0))
765 return 0;
766 }
767 }
768 free(*column);
769
770 for (i = 0; i < excludes; i++)
771 if (!SDDS_SetColumnsOfInterest(SDDSin, SDDS_MATCH_STRING, exclude[i], SDDS_NEGATE_MATCH | SDDS_AND))
772 return 0;
773
774 if (!(*column = SDDS_GetColumnNames(SDDSin, columns)) || *columns == 0) {
775 SDDS_SetError("Selected columns not found.");
776 return 0;
777 }
778
779 return 1;
780}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
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_AssertColumnFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode,...)
Sets acceptance flags for columns 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.
int32_t SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Sets the acceptance flags for columns based on specified naming criteria.
int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
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_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_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_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
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.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS 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
char * SDDS_FindColumn(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Finds the first column in the SDDS dataset that matches the specified criteria.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
Definition SDDStypes.h:157
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
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 * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long lsfn(double *xd, double *yd, double *sy, long nd, long nf, double *coef, double *s_coef, double *chi, double *diff)
Computes nth order polynomial least squares fit.
Definition lsfn.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.