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