60 "Usage: sddsinteg [<input>] [<output>]\n"
61 " [-pipe=[input][,output]]\n"
62 " -integrate=<column-name>[,<sigma-name>] ...\n"
63 " [-exclude=<column-name>[,...]]\n"
64 " -versus=<column-name>[,<sigma-name>]\n"
65 " [-mainTemplates=<item>=<string>[,...]]\n"
66 " [-errorTemplates=<item>=<string>[,...]]\n"
67 " [-copycolumns=<list of column names>]\n"
68 " [-method={trapazoid|GillMiller}]\n"
69 " [-printFinal[=bare][,stdout][,format=<string>]]\n\n"
71 " -pipe Standard SDDS pipe option.\n"
72 " -integrate Name of column to integrate, plus optional RMS error.\n"
73 " Column name may include wildcards, with error name using %%s.\n"
74 " -exclude List of column names to exclude from integration.\n"
75 " -versus Name of column to integrate against, plus optional RMS error.\n"
76 " -mainTemplates Customize main templates for name, symbol, or description.\n"
77 " -errorTemplates Customize error templates for name, symbol, or description.\n"
78 " -copycolumns Comma-separated list of columns to copy to the output.\n"
79 " -method Integration method: trapazoid (default) or GillMiller.\n"
80 " -printFinal Print the final integral value. Options:\n"
81 " bare - Print only the integral value.\n"
82 " stdout - Print to standard output.\n"
83 " format=<s> - Specify printf format string.\n\n"
84 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")";
101static char *option[N_OPTIONS] = {
114void trapizoid(
double *x,
double *y,
double *sx,
double *sy, int64_t n,
double *integ,
double *error);
115long checkErrorNames(
char **yErrorName,
long nIntegrals);
116void makeSubstitutions(
char *buffer1,
char *buffer2,
char *
template,
char *nameRoot,
char *symbolRoot,
char *xName,
char *xSymbol);
117char *changeInformation(
SDDS_DATASET *SDDSout,
char *name,
char *nameRoot,
char *symbolRoot,
118 char *xName,
char *xSymbol,
char **
template,
char *newUnits);
120 char ***yOutputName,
char ***yOutputErrorName,
char ***yOutputUnits,
121 char *xName,
char *xErrorName,
char **yName,
char **yErrorName,
122 long yNames,
char **mainTemplate,
char **errorTemplate,
long methodCode,
123 short columnMajorOrder,
char **colMatch, int32_t colMatches);
125#define NORMAL_PRINTOUT 1
126#define BARE_PRINTOUT 2
127#define STDOUT_PRINTOUT 4
129#define TRAPAZOID_METHOD 0
130#define GILLMILLER_METHOD 1
133static char *methodOption[N_METHODS] = {
138int main(
int argc,
char **argv) {
139 double *xData = NULL, *yData = NULL, *xError = NULL, *yError = NULL, *integral = NULL, *integralError = NULL;
140 char *input = NULL, *output = NULL, *xName = NULL, *xErrorName = NULL;
141 char **yName = NULL, **yErrorName = NULL, **yOutputName = NULL, **yOutputErrorName = NULL, *ptr = NULL, **colMatch = NULL;
142 char **yOutputUnits = NULL, **yExcludeName = NULL;
143 char *mainTemplate[3] = {
"%yNameInteg",
"Integral w.r.t. %xSymbol of %ySymbol",
"$sI$e %ySymbol d%xSymbol"};
144 char *errorTemplate[3] = {
"%yNameIntegSigma",
"Sigma of integral w.r.t. %xSymbol of %ySymbol",
145 "Sigma[$sI$e %ySymbol d%xSymbol]"};
146 char *GMErrorTemplate[3] = {
"%yNameIntegError",
"Error estimate for integral w.r.t. %xSymbol of %ySymbol",
147 "Error[$sI$e %ySymbol d%xSymbol]"};
148 long i, iArg, yNames = 0, yExcludeNames = 0;
149 int32_t colMatches = 0;
152 SCANNED_ARG *scanned = NULL;
153 unsigned long flags = 0, pipeFlags = 0, printFlags = 0, majorOrderFlag = 0;
154 FILE *fpPrint = stderr;
155 char *printFormat =
"%21.15e";
156 int methodCode = TRAPAZOID_METHOD;
157 short columnMajorOrder = -1;
161 argc =
scanargs(&scanned, argc, argv);
163 fprintf(stderr,
"%s\n", USAGE);
169 input = output = xName = xErrorName = NULL;
170 yName = yErrorName = yExcludeName = NULL;
171 integral = integralError = yError = yData = xData = xError = NULL;
172 yNames = yExcludeNames = 0;
173 pipeFlags = printFlags = 0;
175 printFormat =
"%21.15e";
176 methodCode = TRAPAZOID_METHOD;
178 for (iArg = 1; iArg < argc; iArg++) {
179 if (scanned[iArg].arg_type == OPTION) {
181 switch (
match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
182 case CLO_MAJOR_ORDER:
184 scanned[iArg].n_items--;
185 if (scanned[iArg].n_items > 0 &&
186 !
scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
187 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
188 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)) {
189 SDDS_Bomb(
"invalid -majorOrder syntax/values");
191 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
192 columnMajorOrder = 1;
193 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
194 columnMajorOrder = 0;
197 if (scanned[iArg].n_items != 2 && scanned[iArg].n_items != 3)
199 yName =
SDDS_Realloc(yName,
sizeof(*yName) * (yNames + 1));
200 yErrorName =
SDDS_Realloc(yErrorName,
sizeof(*yErrorName) * (yNames + 1));
201 yName[yNames] = scanned[iArg].list[1];
202 if (scanned[iArg].n_items == 3)
203 yErrorName[yNames] = scanned[iArg].list[2];
205 yErrorName[yNames] = NULL;
209 if (scanned[iArg].n_items < 2)
211 moveToStringArray(&yExcludeName, &yExcludeNames, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
216 if (scanned[iArg].n_items != 2 && scanned[iArg].n_items != 3)
218 xName = scanned[iArg].list[1];
219 if (scanned[iArg].n_items == 3)
220 xErrorName = scanned[iArg].list[2];
225 if (scanned[iArg].n_items != 2 ||
226 (methodCode =
match_string(scanned[iArg].list[1], methodOption, N_METHODS, 0)) < 0)
230 if ((scanned[iArg].n_items -= 1) >= 1) {
231 if (!
scanItemList(&printFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
232 "bare", -1, NULL, 0, BARE_PRINTOUT,
233 "stdout", -1, NULL, 0, STDOUT_PRINTOUT,
234 "format",
SDDS_STRING, &printFormat, 1, 0, NULL)) {
238 if (!(printFlags & BARE_PRINTOUT))
239 printFlags |= NORMAL_PRINTOUT;
241 case CLO_MAINTEMPLATE:
242 if (scanned[iArg].n_items < 2)
243 SDDS_Bomb(
"invalid -mainTemplate syntax");
244 scanned[iArg].n_items--;
245 if (!
scanItemList(&flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
247 "description",
SDDS_STRING, mainTemplate + 1, 1, 0,
248 "symbol",
SDDS_STRING, mainTemplate + 2, 1, 0, NULL)) {
249 SDDS_Bomb(
"invalid -mainTemplate syntax");
252 case CLO_ERRORTEMPLATE:
253 if (scanned[iArg].n_items < 2)
254 SDDS_Bomb(
"invalid -errorTemplate syntax");
255 scanned[iArg].n_items--;
256 if (!
scanItemList(&flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
258 "description",
SDDS_STRING, errorTemplate + 1, 1, 0,
259 "symbol",
SDDS_STRING, errorTemplate + 2, 1, 0, NULL)) {
260 SDDS_Bomb(
"invalid -errorTemplate syntax");
264 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
268 if (scanned[iArg].n_items < 2)
269 SDDS_Bomb(
"Invalid copycolumns syntax provided.");
270 colMatch =
tmalloc(
sizeof(*colMatch) * (colMatches = scanned[iArg].n_items - 1));
271 for (i = 0; i < colMatches; i++)
272 colMatch[i] = scanned[iArg].list[i + 1];
275 fprintf(stderr,
"invalid option seen: %s\n", scanned[iArg].list[0]);
280 input = scanned[iArg].list[0];
282 output = scanned[iArg].list[0];
290 if (methodCode != TRAPAZOID_METHOD) {
292 for (i = 0; i < yNames; i++)
293 yErrorName[i] = NULL;
296 if (printFlags & STDOUT_PRINTOUT)
300 SDDS_Bomb(
"-integrate option must be given at least once");
301 if (!checkErrorNames(yErrorName, yNames))
302 SDDS_Bomb(
"either all -integrate quantities must have errors, or none");
307 if (!(ptr =
SDDS_FindColumn(&SDDSin, FIND_NUMERIC_TYPE, xName, NULL))) {
308 fprintf(stderr,
"error: column %s doesn't exist\n", xName);
315 if (!(ptr =
SDDS_FindColumn(&SDDSin, FIND_NUMERIC_TYPE, xErrorName, NULL))) {
316 fprintf(stderr,
"error: column %s doesn't exist\n", xErrorName);
324 if (!(yNames = expandColumnPairNames(&SDDSin, &yName, &yErrorName, yNames, yExcludeName, yExcludeNames, FIND_NUMERIC_TYPE, 0))) {
325 fprintf(stderr,
"error: no quantities to integrate found in file\n");
329 if (!setupOutputFile(&SDDSout, &SDDSin, output, &yOutputName, &yOutputErrorName, &yOutputUnits,
330 xName, xErrorName, yName, yErrorName, yNames,
331 mainTemplate, (methodCode == GILLMILLER_METHOD) ? (
char **)GMErrorTemplate : (
char **)errorTemplate,
332 methodCode, columnMajorOrder, colMatch, colMatches)) {
333 SDDS_Bomb(
"Failed to set up output file.");
338 integral =
SDDS_Realloc(integral,
sizeof(*integral) * rows);
339 integralError =
SDDS_Realloc(integralError,
sizeof(*integralError) * rows);
353 for (i = 0; i < yNames; i++) {
356 (yErrorName && yErrorName[i] &&
360 switch (methodCode) {
361 case TRAPAZOID_METHOD:
362 trapizoid(xData, yData, xError, yError, rows, integral, integralError);
364 case GILLMILLER_METHOD:
366 SDDS_Bomb(
"Problem with integration: check for monotonically changing independent variable values");
371 (yOutputErrorName && yOutputErrorName[i] &&
375 if (printFlags & BARE_PRINTOUT) {
376 fprintf(fpPrint, printFormat, integral[rows - 1]);
377 if (xError || yError || (yOutputErrorName && yOutputErrorName[i])) {
379 fprintf(fpPrint, printFormat, integralError[rows - 1]);
381 fputc(
'\n', fpPrint);
382 }
else if (printFlags & NORMAL_PRINTOUT) {
383 fprintf(fpPrint,
"%s: ", yName[i]);
384 fprintf(fpPrint, printFormat, integral[rows - 1]);
385 if (xError || yError || (yOutputErrorName && yOutputErrorName[i])) {
386 fputs(
" +/- ", fpPrint);
387 fprintf(fpPrint, printFormat, integralError[rows - 1]);
388 fputs(yOutputUnits[i], fpPrint);
390 fputc(
'\n', fpPrint);
397 yData = yError = NULL;
407 xData = xError = NULL;
426 char ***yOutputName,
char ***yOutputErrorName,
char ***yOutputUnits,
427 char *xName,
char *xErrorName,
char **yName,
char **yErrorName,
428 long yNames,
char **mainTemplate,
char **errorTemplate,
long methodCode,
429 short columnMajorOrder,
char **colMatch, int32_t colMatches) {
431 char *xSymbol = NULL, *ySymbol = NULL, **col = NULL;
434 *yOutputName =
tmalloc(
sizeof(**yOutputName) * yNames);
435 *yOutputErrorName =
tmalloc(
sizeof(**yOutputErrorName) * yNames);
436 *yOutputUnits =
tmalloc(
sizeof(**yOutputUnits) * yNames);
446 fprintf(stderr,
"error: problem getting symbol for column %s\n", xName);
450 if (columnMajorOrder != -1)
451 SDDSout->layout.data_mode.column_major = columnMajorOrder;
453 SDDSout->layout.data_mode.column_major = SDDSin->layout.data_mode.column_major;
458 for (i = 0; i < yNames; i++) {
460 fprintf(stderr,
"error: problem transferring definition for column %s\n", yName[i]);
465 fprintf(stderr,
"error: problem getting symbol for column %s\n", yName[i]);
472 (*yOutputUnits)[i] = multiplyColumnUnits(SDDSout, yName[i], xName);
473 (*yOutputName)[i] = changeInformation(SDDSout, yName[i], yName[i], ySymbol, xName, xSymbol, mainTemplate, (*yOutputUnits)[i]);
475 if (yErrorName || xErrorName || methodCode == GILLMILLER_METHOD) {
476 if (yErrorName && yErrorName[i]) {
478 fprintf(stderr,
"error: problem transferring definition for column %s\n", yErrorName[i]);
481 (*yOutputErrorName)[i] = changeInformation(SDDSout, yErrorName[i], yName[i], ySymbol, xName, xSymbol, errorTemplate, (*yOutputUnits)[i]);
484 fprintf(stderr,
"error: problem transferring error definition for column %s\n", yName[i]);
487 (*yOutputErrorName)[i] = changeInformation(SDDSout, yName[i], yName[i], ySymbol, xName, xSymbol, errorTemplate, (*yOutputUnits)[i]);
490 (*yOutputErrorName)[i] = NULL;
496 for (i = 0; i < cols; i++) {
511char *changeInformation(
SDDS_DATASET *SDDSout,
char *name,
char *nameRoot,
char *symbolRoot,
512 char *xName,
char *xSymbol,
char **
template,
char *newUnits) {
513 char buffer1[SDDS_MAXLINE], buffer2[SDDS_MAXLINE], *ptr = NULL;
518 makeSubstitutions(buffer1, buffer2,
template[2], nameRoot, symbolRoot, xName, xSymbol);
522 makeSubstitutions(buffer1, buffer2,
template[1], nameRoot, symbolRoot, xName, xSymbol);
526 makeSubstitutions(buffer1, buffer2,
template[0], nameRoot, symbolRoot, xName, xSymbol);
534void makeSubstitutions(
char *buffer1,
char *buffer2,
char *
template,
char *nameRoot,
char *symbolRoot,
535 char *xName,
char *xSymbol) {
536 strcpy(buffer2,
template);
541 strcpy(buffer1, buffer2);
544void trapizoid(
double *x,
double *y,
double *sx,
double *sy, int64_t n,
double *integ,
double *error) {
548 integ[0] = error[0] = 0;
549 for (i = 1; i < n; i++) {
550 dy = y[i] + y[i - 1];
551 dx = x[i] - x[i - 1];
552 integ[i] = integ[i - 1] + dy * dx;
554 error[i] = error[i - 1] + sqr(dy) * (sqr(sx[i - 1]) + sqr(sx[i])) + sqr(dx) * (sqr(sy[i - 1]) + sqr(sy[i]));
556 error[i] = error[i - 1] + sqr(dy) * (sqr(sx[i - 1]) + sqr(sx[i]));
558 error[i] = error[i - 1] + sqr(dx) * (sqr(sy[i - 1]) + sqr(sy[i]));
562 for (i = 0; i < n; i++) {
563 error[i] = sqrt(error[i]) / 2;
568long checkErrorNames(
char **yErrorName,
long yNames) {
571 for (i = 1; i < yNames; i++)
575 for (i = 1; i < yNames; i++)
int GillMillerIntegration(double *integral, double *error, double *f, double *x, long n)
Performs numerical integration using the Gill-Miller method.
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
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.
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.
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_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.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
char ** getMatchingSDDSNames(SDDS_DATASET *dataset, char **matchName, int32_t matches, int32_t *names, short type)
Retrieves an array of matching SDDS entity names based on specified criteria.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
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.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_STRING
Identifier for the string data type.
Utility functions for SDDS dataset manipulation and string array operations.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
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.
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)
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.