57#include "match_string.h"
62 CLO_INDEPENDENT_PARAMETER,
73char *commandline_option[N_OPTIONS] = {
74 "independentVariable",
84#define DEFAULT_EXCLUDED_COLUMNS 3
85char *defaultExcludedColumn[DEFAULT_EXCLUDED_COLUMNS] = {
90#define DEFAULT_COPY_COLUMNS 2
91char *defaultCopyColumn[DEFAULT_COPY_COLUMNS] = {
96 "sddsvslopes [<inputfile>] [<outputfile>]\n"
97 " [-pipe=[input][,output]]\n"
98 " -independentVariable=<parametername>\n"
99 " [-columns=<list-of-names>] \n"
100 " [-excludeColumns=<list-of-names>] \n"
103 " [-majorOrder=row|column]\n"
105 " -pipe=[input][,output] Read input or output from a pipe.\n"
106 " -independentVariable=<name> Name of the independent variable parameter.\n"
107 " -columns=<list-of-names> Columns to perform straight line fitting.\n"
108 " -excludeColumns=<list-of-names> Columns to exclude from fitting.\n"
109 " -sigma Generate errors for slopes using sigma columns.\n"
110 " -verbose Print detailed output to stderr.\n"
111 " -majorOrder=row|column Specify output file in row or column major order.\n"
113 " Computes straight line fits of column data in the input SDDS file using a specified\n"
114 " independent variable parameter. The output file contains tables of slopes and intercepts.\n"
115 " The independent parameter is removed from the output file and its name is converted\n"
116 " to a parameter string.\n"
118 " Louis Emery, ANL (Date: " __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
120long set_multicolumn_flags(
SDDS_TABLE *SDDSin,
char ***column, int32_t *columns,
char **exclude,
long excludes);
122int main(
int argc,
char **argv) {
123 SCANNED_ARG *scanned;
124 SDDS_TABLE inputPage, *copiedPage, outputPage;
126 char *inputfile, *outputfile;
127 char **column, **excludeColumn = NULL;
130 char *indParameterName;
138 char **intColumn, **slopeColumn, **slopeSigmaColumn;
139 char *Units, *slopeUnits;
142 double *coef, *coefsigma, *weight, *diff, chi;
145 double *slope, slope2, slopeAve, slopeSigma;
146 unsigned long pipeFlags, majorOrderFlag;
147 long tmpfile_used, noWarnings;
149 short columnMajorOrder = -1;
152 slopeSigmaColumn = NULL;
153 slopeUnits = Units = indVarUnits = NULL;
157 coef = coefsigma = weight = diff = slope = NULL;
159 argc =
scanargs(&scanned, argc, argv);
163 inputfile = outputfile = NULL;
164 columns = excludeColumns = 0;
165 column = excludeColumn = NULL;
166 indParameterName = NULL;
172 for (iArg = 1; iArg < argc; iArg++) {
173 if (scanned[iArg].arg_type == OPTION) {
175 switch (
match_string(scanned[iArg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
176 case CLO_MAJOR_ORDER:
178 scanned[iArg].n_items--;
179 if (scanned[iArg].n_items > 0 &&
180 (!
scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
181 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
182 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
183 SDDS_Bomb(
"invalid -majorOrder syntax/values");
184 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
185 columnMajorOrder = 1;
186 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
187 columnMajorOrder = 0;
189 case CLO_INDEPENDENT_PARAMETER:
190 if (!(indParameterName = scanned[iArg].list[1]))
191 SDDS_Bomb(
"no string given for option -independentVariable");
195 SDDS_Bomb(
"only one -columns option may be given");
196 if (scanned[iArg].n_items < 2)
198 column =
tmalloc(
sizeof(*column) * (columns = scanned[iArg].n_items - 1));
199 for (i = 0; i < columns; i++)
200 column[i] = scanned[iArg].list[i + 1];
204 SDDS_Bomb(
"only one -excludeColumns option may be given");
205 if (scanned[iArg].n_items < 2)
206 SDDS_Bomb(
"invalid -excludeColumns syntax");
207 excludeColumn =
tmalloc(
sizeof(*excludeColumn) * (excludeColumns = scanned[iArg].n_items - 1));
208 for (i = 0; i < excludeColumns; i++)
209 excludeColumn[i] = scanned[iArg].list[i + 1];
215 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
218 case CLO_SLOPE_ERRORS:
227 inputfile = scanned[iArg].list[0];
228 else if (!outputfile)
229 outputfile = scanned[iArg].list[0];
235 processFilenames(
"sddsvslopes", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
237 if (!indParameterName)
238 SDDS_Bomb(
"independentVariable not given");
240 if (!excludeColumns) {
241 excludeColumn = defaultExcludedColumn;
242 excludeColumns = DEFAULT_EXCLUDED_COLUMNS;
246 fprintf(stderr,
"Reading file %s.\n", inputfile);
249 while (SDDS_ReadTable(&inputPage) > 0) {
258 if (!SDDS_CopyTable(&copiedPage[copiedPages], &inputPage))
262 if (copiedPages < 2) {
263 fprintf(stderr,
"Insufficient data (i.e., number of data pages) to fit a straight line.\n");
267 case SDDS_CHECK_WRONGUNITS:
268 case SDDS_CHECK_OKAY:
271 fprintf(stderr,
"Something wrong with column %s.\n",
"Rootname");
275 case SDDS_CHECK_WRONGUNITS:
276 case SDDS_CHECK_OKAY:
279 case SDDS_CHECK_NONEXISTENT:
283 fprintf(stderr,
"Something wrong with column %s.\n",
"Index");
289 indVar = (
double *)malloc(
sizeof(*indVar) * copiedPages);
291 case SDDS_CHECK_WRONGUNITS:
292 case SDDS_CHECK_OKAY:
295 fprintf(stderr,
"Something wrong with parameter %s.\n", indParameterName);
298 for (iPage = 0; iPage < copiedPages; iPage++) {
305 indVarUnits = (
char *)malloc(
sizeof(*indVarUnits));
312 if (!set_multicolumn_flags(&inputPage, &column, &columns, excludeColumn, excludeColumns)) {
319 intColumn = (
char **)malloc((
sizeof(
char *) * columns));
320 slopeColumn = (
char **)malloc((
sizeof(
char *) * columns));
322 slopeSigmaColumn = (
char **)malloc((
sizeof(
char *) * columns));
323 for (i = 0; i < columns; i++) {
324 intColumn[i] = (
char *)malloc((
sizeof(
char) * (strlen(column[i]) + strlen(
"Intercept") + 1)));
325 strcat(strcpy(intColumn[i], column[i]),
"Intercept");
326 slopeColumn[i] = (
char *)malloc((
sizeof(
char) * (strlen(column[i]) + strlen(
"Slope") + 1)));
327 strcat(strcpy(slopeColumn[i], column[i]),
"Slope");
329 slopeSigmaColumn[i] = (
char *)malloc((
sizeof(
char) * (strlen(column[i]) + strlen(
"SlopeSigma") + 1)));
330 strcat(strcpy(slopeSigmaColumn[i], column[i]),
"SlopeSigma");
337 fprintf(stderr,
"Opening file %s.\n", outputfile);
338 if (!
SDDS_InitializeOutput(&outputPage, SDDS_BINARY, 1,
"lsf of sddsvexperiment", NULL, outputfile) ||
344 if (columnMajorOrder != -1)
345 outputPage.layout.data_mode.column_major = columnMajorOrder;
347 outputPage.layout.data_mode.column_major = inputPage.layout.data_mode.column_major;
348 for (iCol = 0; iCol < columns; iCol++) {
352 Units = (
char *)malloc(
sizeof(*Units));
358 if (strlen(indVarUnits) && strlen(Units)) {
359 slopeUnits = (
char *)malloc(
sizeof(*slopeUnits) * (strlen(Units) + strlen(indVarUnits) + 2));
360 strcat(strcat(strcpy(slopeUnits, Units),
"/"), indVarUnits);
362 if (strlen(indVarUnits) && !strlen(Units)) {
363 slopeUnits = (
char *)malloc(
sizeof(*slopeUnits) * (strlen(indVarUnits) + 2));
364 strcat(strcpy(slopeUnits,
"1/"), indVarUnits);
366 if (!strlen(indVarUnits) && strlen(Units)) {
367 slopeUnits = (
char *)malloc(
sizeof(*slopeUnits) * (strlen(Units) + 2));
368 strcpy(slopeUnits, Units);
370 if (!strlen(indVarUnits) && !strlen(Units)) {
371 slopeUnits = (
char *)malloc(
sizeof(*slopeUnits));
372 slopeUnits[0] =
'\0';
383 !SDDS_StartTable(&outputPage, rows) ||
384 !
SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
"InputFile", inputfile ? inputfile :
"pipe", NULL) ||
385 !
SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, 0,
"IndependentVariable", indParameterName, NULL))
391 copyColumns = DEFAULT_COPY_COLUMNS;
392 copyColumn = defaultCopyColumn;
393 if (!set_multicolumn_flags(&inputPage, ©Column, ©Columns, NULL, 0)) {
399 depVar = (
double *)malloc(
sizeof(*depVar) * copiedPages);
400 weight = (
double *)malloc(
sizeof(*weight) * copiedPages);
401 diff = (
double *)malloc(
sizeof(*diff) * copiedPages);
403 coef = (
double *)malloc(
sizeof(*coef) * (order + 1));
404 coefsigma = (
double *)malloc(
sizeof(*coefsigma) * (order + 1));
406 slope = (
double *)malloc(
sizeof(*slope) * copiedPages);
407 for (iCol = 0; iCol < columns; iCol++) {
408 for (iPage = 0; iPage < copiedPages; iPage++)
411 fprintf(stderr,
"Doing column %s.\n", column[iCol]);
412 for (iRow = 0; iRow < rows; iRow++) {
413 for (iPage = 0; iPage < copiedPages; iPage++) {
414 if (!
SDDS_GetValue(&copiedPage[iPage], column[iCol], iRow, &depVar[iPage]))
417 if (!(
lsfn(indVar, depVar, weight, copiedPages, order, coef, coefsigma, &chi, diff))) {
418 fprintf(stderr,
"Problem with call to lsfn.\n");
422 if (!
SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, iRow,
"Index", iRow, intColumn[iCol], coef[0], slopeColumn[iCol], coef[1], NULL))
425 if (!
SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, iRow, intColumn[iCol], coef[0], slopeColumn[iCol], coef[1], NULL))
430 slopeAve = slope2 = 0;
431 for (iPage = 0; iPage < copiedPages; iPage++) {
432 weight[iPage] = 1e10;
434 weight[iPage - 1] = 1;
435 if (!(
lsfn(indVar, depVar, weight, copiedPages, order, coef, coefsigma, &chi, diff))) {
436 fprintf(stderr,
"Problem with call to lsfn.\n");
439 slope[iPage] = coef[1];
440 slopeAve += slope[iPage];
441 slope2 += slope[iPage] * slope[iPage];
443 slopeSigma = sqrt(slope2 / copiedPages - (slopeAve / copiedPages) * (slopeAve / copiedPages));
444 if (!
SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, iRow, slopeSigmaColumn[iCol], slopeSigma, NULL))
452 for (iPage = 0; iPage < copiedPages; iPage++) {
469 free(slopeSigmaColumn);
495long set_multicolumn_flags(
SDDS_TABLE *SDDSin,
char ***column, int32_t *columns,
char **exclude,
long excludes) {
500 for (i = 0; i < *columns; i++) {
510 for (i = 0; i < *columns; i++) {
520 for (i = 0; i < excludes; i++)
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyColumns(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
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_GetParameterInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified parameter in the SDDS dataset.
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.
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.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
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.
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.
int32_t SDDS_CheckParameter(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a parameter exists in the SDDS dataset with the specified name, units, and type.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
#define SDDS_ANY_INTEGER_TYPE
Special identifier used by SDDS_Check*() routines to accept any integer type.
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
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.
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.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
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.