SDDSlib
Loading...
Searching...
No Matches
sddsderiv.c File Reference

Differentiates a data set in SDDS format. More...

#include "mdb.h"
#include "SDDS.h"
#include "SDDSutils.h"
#include "scan.h"
#include <ctype.h>

Go to the source code of this file.

Enumerations

enum  option_type {
  CLO_DIFFERENTIATE , CLO_VERSUS , CLO_INTERVAL , CLO_MAINTEMPLATE ,
  CLO_ERRORTEMPLATE , CLO_PIPE , CLO_EXCLUDE , CLO_SAVITZKYGOLAY ,
  CLO_MAJOR_ORDER , N_OPTIONS
}
 

Functions

long checkErrorNames (char **yErrorName, long nDerivatives)
 
void makeSubstitutions (char *buffer1, char *buffer2, char *template, char *nameRoot, char *symbolRoot, char *xName, char *xSymbol)
 
char * changeInformation (SDDS_DATASET *SDDSout, char *name, char *nameRoot, char *symbolRoot, char *xName, char *xSymbol, char **template, char *newUnits)
 
long setupOutputFile (SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *output, char ***yOutputName, char ***yOutputErrorName, char ***yOutputUnits, char *xName, char *xErrorName, char **yName, char **yErrorName, long yNames, char **mainTemplate, char **errorTemplate, int32_t interval, long order, short columnMajorOrder)
 
long findDerivIndices (int64_t *i1, int64_t *i2, long interval, int64_t i, int64_t rows)
 
void takeDerivative (double *x, double *y, double *sy, int64_t rows, double *deriv, double *derivSigma, double *derivPosition, long interval)
 
void takeSGDerivative (double *x, double *y, int64_t rows, double *deriv, double *derivPosition, long left, long right, long sgOrder, long derivOrder)
 
int main (int argc, char **argv)
 

Variables

static char * USAGE
 
static char * option [N_OPTIONS]
 

Detailed Description

Differentiates a data set in SDDS format.

This program calculates the derivative of specified columns in an SDDS data set. It supports various options including handling error columns, Savitzky-Golay filtering, and customizable output templates.

Usage: sddsderiv [<input>] [<output>] [-pipe=[input][,output]] -differentiate=<column-name>[,<sigma-name>]... [-exclude=<column-name>[,...]] -versus=<column-name> [-interval=<integer>] [-SavitzkyGolay=<left>,<right>,<fitOrder>[,<derivOrder>]] [-mainTemplates==<string>[,...]] [-errorTemplates==<string>[,...]] [-majorOrder=row|column]

Options: -pipe=[input][,output] Use standard input/output. -differentiate=<col>[,<sigma-col>]... Columns to differentiate, optionally specifying sigma columns. -exclude=<col>[,...] Columns to exclude from differentiation. -versus=<col> Column to differentiate with respect to. -interval=<integer> Interval for finite difference. -SavitzkyGolay=<left>,<right>,<fitOrder>[,<derivOrder>] Apply Savitzky-Golay filter with specified parameters. -mainTemplates==<string>[,...] Templates for main output columns. Items: name, symbol, description. -errorTemplates==<string>[,...] Templates for error output columns. Items: name, symbol, description. -majorOrder=row|column Set major order of data.

The -templates may be "name", "symbol" or "description". The default main name, description, and symbol templates are "%yNameDeriv", "Derivative w.r.t %xSymbol of %ySymbol", and "d[%ySymbol]/d[%xSymbol]", respectively. The default error name, description, and symbol templates are "%yNameDerivSigma", "Sigma of derivative w.r.t %xSymbol of %ySymbol", and "Sigma[d[%ySymbol]/d[%xSymbol]]", respectively.

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, C. Saunders, R. Soliday, H. Shang

Definition in file sddsderiv.c.

Enumeration Type Documentation

◆ option_type

enum option_type

Definition at line 86 of file sddsderiv.c.

86 {
87 CLO_DIFFERENTIATE,
88 CLO_VERSUS,
89 CLO_INTERVAL,
90 CLO_MAINTEMPLATE,
91 CLO_ERRORTEMPLATE,
92 CLO_PIPE,
93 CLO_EXCLUDE,
94 CLO_SAVITZKYGOLAY,
95 CLO_MAJOR_ORDER,
96 N_OPTIONS
97};

Function Documentation

◆ changeInformation()

char * changeInformation ( SDDS_DATASET * SDDSout,
char * name,
char * nameRoot,
char * symbolRoot,
char * xName,
char * xSymbol,
char ** template,
char * newUnits )

Definition at line 499 of file sddsderiv.c.

499 {
500 char buffer1[SDDS_MAXLINE], buffer2[SDDS_MAXLINE], *ptr;
501
502 if (!SDDS_ChangeColumnInformation(SDDSout, "units", newUnits, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, name))
503 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
504
505 makeSubstitutions(buffer1, buffer2, template[2], nameRoot, symbolRoot, xName, xSymbol);
506 if (!SDDS_ChangeColumnInformation(SDDSout, "symbol", buffer2, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, name))
507 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
508
509 makeSubstitutions(buffer1, buffer2, template[1], nameRoot, symbolRoot, xName, xSymbol);
510 if (!SDDS_ChangeColumnInformation(SDDSout, "description", buffer2, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, name))
511 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
512
513 makeSubstitutions(buffer1, buffer2, template[0], nameRoot, symbolRoot, xName, xSymbol);
514 if (!SDDS_ChangeColumnInformation(SDDSout, "name", buffer2, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, name))
515 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
516 SDDS_CopyString(&ptr, buffer2);
517 return ptr;
518}
int32_t SDDS_ChangeColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Modifies a specific field in a column definition within the SDDS dataset.
Definition SDDS_info.c:364
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856

◆ checkErrorNames()

long checkErrorNames ( char ** yErrorName,
long nDerivatives )

Definition at line 529 of file sddsderiv.c.

529 {
530 long i;
531 if (yErrorName[0]) {
532 for (i = 1; i < yNames; i++)
533 if (!yErrorName[i])
534 return 0;
535 } else {
536 for (i = 1; i < yNames; i++)
537 if (yErrorName[i])
538 return 0;
539 }
540 return 1;
541}

◆ findDerivIndices()

long findDerivIndices ( int64_t * i1,
int64_t * i2,
long interval,
int64_t i,
int64_t rows )

Definition at line 371 of file sddsderiv.c.

371 {
372 int64_t index, rows1;
373
374 rows1 = rows - 1;
375 *i1 = index = i - interval / 2;
376 if (index < 0) {
377 *i2 = 2 * i;
378 *i1 = 0;
379 if (*i1 == *i2)
380 *i2 += 1;
381 if (*i2 < rows)
382 return 1;
383 return 0;
384 }
385 *i2 = i + interval / 2;
386 index = rows1 - *i2;
387 if (index < 0) {
388 *i1 = 2 * i - rows1;
389 *i2 = rows1;
390 if (*i1 == *i2)
391 *i1 -= 1;
392 if (*i1 >= 0)
393 return 1;
394 return 0;
395 }
396 if (*i1 == *i2) {
397 if (*i2 < rows1)
398 *i2 = *i1 + 1;
399 else
400 *i1 = *i1 - 1;
401 }
402 if (*i2 < rows && *i1 >= 0)
403 return 1;
404 return 0;
405}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 120 of file sddsderiv.c.

120 {
121 double *xData, *yData, *xError, *yError, *derivative, *derivativeError, *derivativePosition;
122 char *input, *output, *xName, *xErrorName, **yName, **yErrorName, **yOutputName, **yOutputErrorName, *ptr;
123 char **yOutputUnits, **yExcludeName;
124 char *mainTemplate[3] = {NULL, NULL, NULL};
125 char *errorTemplate[3] = {NULL, NULL, NULL};
126 long i, iArg, yNames, yExcludeNames;
127 int64_t rows;
128 int32_t interval;
129 SDDS_DATASET SDDSin, SDDSout;
130 SCANNED_ARG *scanned;
131 unsigned long flags, pipeFlags, majorOrderFlag;
132 long SGLeft, SGRight, SGOrder, SGDerivOrder, intervalGiven, yErrorsSeen;
133 short columnMajorOrder = -1;
134
136
137 argc = scanargs(&scanned, argc, argv);
138 if (argc == 1)
139 bomb(NULL, USAGE);
140
141 input = output = xName = xErrorName = NULL;
142 yName = yErrorName = yExcludeName = NULL;
143 derivative = derivativeError = derivativePosition = yError = yData = xData = xError = NULL;
144 yNames = yExcludeNames = 0;
145 pipeFlags = 0;
146 interval = 2;
147 SGOrder = -1;
148 SGDerivOrder = 1;
149 intervalGiven = 0;
150 yErrorsSeen = 0;
151
152 for (iArg = 1; iArg < argc; iArg++) {
153 if (scanned[iArg].arg_type == OPTION) {
154 /* process options here */
155 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
156 case CLO_MAJOR_ORDER:
157 majorOrderFlag = 0;
158 scanned[iArg].n_items--;
159 if (scanned[iArg].n_items > 0 && (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
160 SDDS_Bomb("invalid -majorOrder syntax/values");
161 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
162 columnMajorOrder = 1;
163 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
164 columnMajorOrder = 0;
165 break;
166 case CLO_DIFFERENTIATE:
167 if (scanned[iArg].n_items != 2 && scanned[iArg].n_items != 3)
168 SDDS_Bomb("invalid -differentiate syntax");
169 yName = SDDS_Realloc(yName, sizeof(*yName) * (yNames + 1));
170 yErrorName = SDDS_Realloc(yErrorName, sizeof(*yErrorName) * (yNames + 1));
171 yName[yNames] = scanned[iArg].list[1];
172 if (scanned[iArg].n_items == 3) {
173 yErrorsSeen = 1;
174 yErrorName[yNames] = scanned[iArg].list[2];
175 } else
176 yErrorName[yNames] = NULL;
177 yNames++;
178 break;
179 case CLO_EXCLUDE:
180 if (scanned[iArg].n_items < 2)
181 SDDS_Bomb("invalid -exclude syntax");
182 moveToStringArray(&yExcludeName, &yExcludeNames, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
183 break;
184 case CLO_VERSUS:
185 if (xName)
186 SDDS_Bomb("give -versus only once");
187 if (scanned[iArg].n_items != 2)
188 SDDS_Bomb("invalid -versus syntax");
189 xName = scanned[iArg].list[1];
190 xErrorName = NULL;
191 break;
192 case CLO_MAINTEMPLATE:
193 if (scanned[iArg].n_items < 2)
194 SDDS_Bomb("invalid -mainTemplate syntax");
195 scanned[iArg].n_items--;
196 if (!scanItemList(&flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "name", SDDS_STRING, mainTemplate + 0, 1, 0, "description", SDDS_STRING, mainTemplate + 1, 1, 0, "symbol", SDDS_STRING, mainTemplate + 2, 1, 0, NULL))
197 SDDS_Bomb("invalid -mainTemplate syntax");
198 break;
199 case CLO_ERRORTEMPLATE:
200 if (scanned[iArg].n_items < 2)
201 SDDS_Bomb("invalid -errorTemplate syntax");
202 scanned[iArg].n_items--;
203 if (!scanItemList(&flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "name", SDDS_STRING, errorTemplate + 0, 1, 0, "description", SDDS_STRING, errorTemplate + 1, 1, 0, "symbol", SDDS_STRING, errorTemplate + 2, 1, 0, NULL))
204 SDDS_Bomb("invalid -errorTemplate syntax");
205 break;
206 case CLO_PIPE:
207 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
208 SDDS_Bomb("invalid -pipe syntax");
209 break;
210 case CLO_INTERVAL:
211 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%" SCNd32, &interval) != 1 || interval <= 0)
212 SDDS_Bomb("invalid -interval syntax/value");
213 intervalGiven = 1;
214 break;
215 case CLO_SAVITZKYGOLAY:
216 if ((scanned[iArg].n_items != 4 && scanned[iArg].n_items != 5) ||
217 sscanf(scanned[iArg].list[1], "%ld", &SGLeft) != 1 ||
218 sscanf(scanned[iArg].list[2], "%ld", &SGRight) != 1 ||
219 sscanf(scanned[iArg].list[3], "%ld", &SGOrder) != 1 ||
220 (scanned[iArg].n_items == 5 && sscanf(scanned[iArg].list[4], "%ld", &SGDerivOrder) != 1) ||
221 SGLeft < 0 ||
222 SGRight < 0 ||
223 (SGLeft + SGRight) < SGOrder ||
224 SGOrder < 0 ||
225 SGDerivOrder < 0)
226 SDDS_Bomb("invalid -SavitzkyGolay syntax/values");
227 break;
228 default:
229 fprintf(stderr, "invalid option seen: %s\n", scanned[iArg].list[0]);
230 exit(EXIT_FAILURE);
231 break;
232 }
233 } else {
234 if (!input)
235 input = scanned[iArg].list[0];
236 else if (!output)
237 output = scanned[iArg].list[0];
238 else
239 SDDS_Bomb("too many filenames");
240 }
241 }
242
243 if (intervalGiven && SGOrder >= 0)
244 SDDS_Bomb("-interval and -SavitzkyGolay options are incompatible");
245 if (SGOrder >= 0 && (xErrorName || yErrorsSeen))
246 SDDS_Bomb("Savitzky-Golay method does not support errors in data");
247
248 processFilenames("sddsderiv", &input, &output, pipeFlags, 0, NULL);
249
250 if (!yNames)
251 SDDS_Bomb("-differentiate option must be given at least once");
252 if (!checkErrorNames(yErrorName, yNames))
253 SDDS_Bomb("either all -differentiate quantities must have errors, or none");
254
255 if (!SDDS_InitializeInput(&SDDSin, input))
256 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
257 if (!(ptr = SDDS_FindColumn(&SDDSin, FIND_NUMERIC_TYPE, xName, NULL))) {
258 fprintf(stderr, "error: column %s doesn't exist\n", xName);
259 exit(EXIT_FAILURE);
260 }
261 free(xName);
262 xName = ptr;
263 if (xErrorName) {
264 if (!(ptr = SDDS_FindColumn(&SDDSin, FIND_NUMERIC_TYPE, xErrorName, NULL))) {
265 fprintf(stderr, "error: column %s doesn't exist\n", xErrorName);
266 exit(EXIT_FAILURE);
267 } else {
268 free(xErrorName);
269 xErrorName = ptr;
270 }
271 }
272
273 if (!(yNames = expandColumnPairNames(&SDDSin, &yName, &yErrorName, yNames, yExcludeName, yExcludeNames, FIND_NUMERIC_TYPE, 0))) {
274 fprintf(stderr, "error: no quantities to differentiate found in file\n");
275 exit(EXIT_FAILURE);
276 }
277
278 setupOutputFile(&SDDSout, &SDDSin, output, &yOutputName, &yOutputErrorName, &yOutputUnits, xName, xErrorName, yName, yErrorName, yNames, mainTemplate, errorTemplate, interval, SGOrder >= 0 ? SGDerivOrder : 1, columnMajorOrder);
279
280 while (SDDS_ReadPage(&SDDSin) > 0) {
281 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) < 2)
282 SDDS_Bomb("Can't compute derivatives: too little data.");
283 derivative = SDDS_Realloc(derivative, sizeof(*derivative) * rows);
284 derivativeError = SDDS_Realloc(derivativeError, sizeof(*derivativeError) * rows);
285 derivativePosition = SDDS_Realloc(derivativePosition, sizeof(*derivativePosition) * rows);
286 if (!SDDS_StartPage(&SDDSout, rows) || !SDDS_CopyParameters(&SDDSout, &SDDSin))
287 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
288 xError = NULL;
289 if (!(xData = SDDS_GetColumnInDoubles(&SDDSin, xName)) ||
290 (xErrorName && !(xError = SDDS_GetColumnInDoubles(&SDDSin, xErrorName))))
291 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
292 for (i = 0; i < yNames; i++) {
293 yError = NULL;
294 if (!(yData = SDDS_GetColumnInDoubles(&SDDSin, yName[i])) ||
295 (yErrorName && yErrorName[i] && !(yError = SDDS_GetColumnInDoubles(&SDDSin, yErrorName[i]))))
296 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
297 if (SGOrder >= 0)
298 takeSGDerivative(xData, yData, rows, derivative, derivativePosition, SGLeft, SGRight, SGOrder, SGDerivOrder);
299 else
300 takeDerivative(xData, yData, yError, rows, derivative, derivativeError, derivativePosition, interval);
301 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, derivative, rows, yOutputName[i]) ||
302 (yOutputErrorName && yOutputErrorName[i] && !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, derivativeError, rows, yOutputErrorName[i])))
303 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
304 if (yData)
305 free(yData);
306 if (yError)
307 free(yError);
308 yData = yError = NULL;
309 }
310 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, derivativePosition, rows, xName) ||
311 (xErrorName && !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, xError, rows, xErrorName)))
312 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
313 if (!SDDS_WritePage(&SDDSout))
314 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
315 if (xData)
316 free(xData);
317 if (xError)
318 free(xError);
319 xData = xError = NULL;
320 }
321 if (!SDDS_Terminate(&SDDSin) || !SDDS_Terminate(&SDDSout)) {
322 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
323 exit(EXIT_FAILURE);
324 }
325 if (derivative)
326 free(derivative);
327 if (derivativeError)
328 free(derivativeError);
329 if (derivativePosition)
330 free(derivativePosition);
331 return EXIT_SUCCESS;
332}
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
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.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
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 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.

◆ makeSubstitutions()

void makeSubstitutions ( char * buffer1,
char * buffer2,
char * template,
char * nameRoot,
char * symbolRoot,
char * xName,
char * xSymbol )

Definition at line 520 of file sddsderiv.c.

520 {
521 strcpy(buffer2, template);
522 replace_string(buffer1, buffer2, "%ySymbol", symbolRoot);
523 replace_string(buffer2, buffer1, "%xSymbol", xSymbol);
524 replace_string(buffer1, buffer2, "%yName", nameRoot);
525 replace_string(buffer2, buffer1, "%xName", xName);
526 strcpy(buffer1, buffer2);
527}
int replace_string(char *t, char *s, char *orig, char *repl)
Replace all occurrences of one string with another string.

◆ setupOutputFile()

long setupOutputFile ( SDDS_DATASET * SDDSout,
SDDS_DATASET * SDDSin,
char * output,
char *** yOutputName,
char *** yOutputErrorName,
char *** yOutputUnits,
char * xName,
char * xErrorName,
char ** yName,
char ** yErrorName,
long yNames,
char ** mainTemplate,
char ** errorTemplate,
int32_t interval,
long order,
short columnMajorOrder )

Definition at line 407 of file sddsderiv.c.

408 {
409 long i;
410 char *xSymbol, *ySymbol;
411 char *mainTemplate[3] = {"%yNameDeriv", "Derivative w.r.t. %xSymbol of %ySymbol", "d[%ySymbol]/d[%xSymbol]"};
412 char *errorTemplate[3] = {"%yNameDerivSigma", "Sigma of derivative w.r.t. %xSymbol of %ySymbol",
413 "Sigma[d[%ySymbol]/d[%xSymbol]]"};
414 char buffer[1024];
415
416 for (i = 0; i < 3; i++) {
417 if (!mainTemplate0[i]) {
418 if (order != 1) {
419 switch (i) {
420 case 0:
421 /* name */
422 snprintf(buffer, sizeof(buffer), "%%yNameDeriv%ld", order);
423 break;
424 case 1:
425 /* description */
426 snprintf(buffer, sizeof(buffer), "Derivative %ld w.r.t. %%xSymbol of %%ySymbol", order);
427 break;
428 case 2:
429 /* symbol */
430 snprintf(buffer, sizeof(buffer), "d[%s%ld]/d[%s]", "ySymbol", order, "xSymbol"); // Adjusted for clarity
431 break;
432 }
433 cp_str(&mainTemplate[i], buffer);
434 }
435 } else {
436 mainTemplate[i] = mainTemplate0[i];
437 }
438 if (errorTemplate0[i]) {
439 errorTemplate[i] = errorTemplate0[i];
440 }
441 }
442
443 *yOutputName = tmalloc(sizeof(**yOutputName) * yNames);
444 *yOutputErrorName = tmalloc(sizeof(**yOutputErrorName) * yNames);
445 *yOutputUnits = tmalloc(sizeof(**yOutputUnits) * yNames);
446 if (!SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL, "sddsderiv output", output) ||
447 SDDS_DefineParameter1(SDDSout, "derivInterval", NULL, NULL, NULL, NULL, SDDS_LONG, &interval) < 0)
448 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
449 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, xName, NULL) ||
450 (xErrorName && !SDDS_TransferColumnDefinition(SDDSout, SDDSin, xErrorName, NULL)))
451 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
452 if (SDDS_GetColumnInformation(SDDSout, "symbol", &xSymbol, SDDS_GET_BY_NAME, xName) != SDDS_STRING) {
453 fprintf(stderr, "error: problem getting symbol for column %s\n", xName);
454 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
455 }
456 if (!xSymbol)
457 SDDS_CopyString(&xSymbol, xName);
458 for (i = 0; i < yNames; i++) {
459 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, yName[i], NULL)) {
460 fprintf(stderr, "error: problem transferring definition for column %s\n", yName[i]);
461 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
462 }
463 if (SDDS_GetColumnInformation(SDDSout, "symbol", &ySymbol, SDDS_GET_BY_NAME, yName[i]) != SDDS_STRING) {
464 fprintf(stderr, "error: problem getting symbol for column %s\n", yName[i]);
465 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
466 }
467 if (!ySymbol || SDDS_StringIsBlank(ySymbol))
468 SDDS_CopyString(&ySymbol, yName[i]);
469 (*yOutputUnits)[i] = divideColumnUnits(SDDSout, yName[i], xName);
470 (*yOutputName)[i] = changeInformation(SDDSout, yName[i], yName[i], ySymbol, xName, xSymbol, mainTemplate, (*yOutputUnits)[i]);
471 if (yErrorName || xErrorName) {
472 if (yErrorName && yErrorName[i]) {
473 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, yErrorName[i], NULL)) {
474 fprintf(stderr, "error: problem transferring definition for column %s\n", yErrorName[i]);
475 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
476 }
477 (*yOutputErrorName)[i] = changeInformation(SDDSout, yErrorName[i], yName[i], ySymbol, xName, xSymbol, errorTemplate, (*yOutputUnits)[i]);
478 } else {
479 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, yName[i], NULL)) {
480 fprintf(stderr, "error: problem transferring error definition for column %s\n", yName[i]);
481 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
482 }
483 (*yOutputErrorName)[i] = changeInformation(SDDSout, yName[i], yName[i], ySymbol, xName, xSymbol, errorTemplate, (*yOutputUnits)[i]);
484 }
485 } else {
486 (*yOutputErrorName)[i] = NULL;
487 }
488 }
489 if (columnMajorOrder != -1)
490 SDDSout->layout.data_mode.column_major = columnMajorOrder;
491 else
492 SDDSout->layout.data_mode.column_major = SDDSin->layout.data_mode.column_major;
493 if (!SDDS_TransferAllParameterDefinitions(SDDSout, SDDSin, SDDS_TRANSFER_KEEPOLD) ||
494 !SDDS_WriteLayout(SDDSout))
495 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
496 return 1;
497}
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_DefineParameter1(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, void *fixed_value)
Defines a data parameter with a fixed numerical value.
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_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_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28

◆ takeDerivative()

void takeDerivative ( double * x,
double * y,
double * sy,
int64_t rows,
double * deriv,
double * derivSigma,
double * derivPosition,
long interval )

Definition at line 347 of file sddsderiv.c.

347 {
348 int64_t i, i1, i2;
349 double dx;
350
351 if (sy) {
352 for (i = 0; i < rows; i++) {
353 if (findDerivIndices(&i1, &i2, interval, i, rows) && (dx = x[i2] - x[i1])) {
354 deriv[i] = (y[i2] - y[i1]) / dx;
355 derivSigma[i] = sqrt(sqr(sy[i1]) + sqr(sy[i2])) / fabs(dx);
356 derivPosition[i] = (x[i2] + x[i1]) / 2;
357 } else
358 deriv[i] = derivSigma[i] = derivPosition[i] = DBL_MAX;
359 }
360 } else {
361 for (i = 0; i < rows; i++) {
362 if (findDerivIndices(&i1, &i2, interval, i, rows) && (dx = x[i2] - x[i1])) {
363 deriv[i] = (y[i2] - y[i1]) / dx;
364 derivPosition[i] = (x[i2] + x[i1]) / 2;
365 } else
366 deriv[i] = derivPosition[i] = DBL_MAX;
367 }
368 }
369}

◆ takeSGDerivative()

void takeSGDerivative ( double * x,
double * y,
int64_t rows,
double * deriv,
double * derivPosition,
long left,
long right,
long sgOrder,
long derivOrder )

Definition at line 334 of file sddsderiv.c.

334 {
335 int64_t i;
336 double spacing, df;
337
338 spacing = (x[rows - 1] - x[0]) / (rows - 1);
339 df = dfactorial(derivOrder) / ipow(spacing, derivOrder);
340 for (i = 0; i < rows; i++) {
341 derivPosition[i] = x[i];
342 deriv[i] = df * y[i];
343 }
344 SavitzkyGolaySmooth(deriv, rows, sgOrder, left, right, derivOrder);
345}
double dfactorial(long n)
Computes the factorial of a given number as a double.
Definition factorial.c:43
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
Definition ipow.c:33
long SavitzkyGolaySmooth(double *data, long rows, long order, long nLeft, long nRight, long derivativeOrder)
Applies Savitzky-Golay smoothing or differentiation to a data array.

Variable Documentation

◆ option

char* option[N_OPTIONS]
static
Initial value:
= {
"differentiate",
"versus",
"interval",
"maintemplate",
"errortemplate",
"pipe",
"exclude",
"savitzkygolay",
"majorOrder",
}

Definition at line 99 of file sddsderiv.c.

99 {
100 "differentiate",
101 "versus",
102 "interval",
103 "maintemplate",
104 "errortemplate",
105 "pipe",
106 "exclude",
107 "savitzkygolay",
108 "majorOrder",
109};

◆ USAGE

char* USAGE
static
Initial value:
=
"Usage: sddsderiv [<input>] [<output>]\n"
" [-pipe=[input][,output]]\n"
" -differentiate=<column-name>[,<sigma-name>]...\n"
" [-exclude=<column-name>[,...]]\n"
" -versus=<column-name>\n"
" [-interval=<integer>]\n"
" [-SavitzkyGolay=<left>,<right>,<fitOrder>[,<derivOrder>]]\n"
" [-mainTemplates=<item>=<string>[,...]]\n"
" [-errorTemplates=<item>=<string>[,...]]\n"
" [-majorOrder=row|column]\n\n"
"Options:\n"
" -pipe=[input][,output] Use standard input/output.\n"
" -differentiate=<col>[,<sigma-col>]... Columns to differentiate, optionally specifying sigma columns.\n"
" -exclude=<col>[,...] Columns to exclude from differentiation.\n"
" -versus=<col> Column to differentiate with respect to.\n"
" -interval=<integer> Interval for finite difference.\n"
" -SavitzkyGolay=<left>,<right>,<fitOrder>[,<derivOrder>]\n"
" Apply Savitzky-Golay filter with specified parameters.\n"
" -mainTemplates=<item>=<string>[,...] Templates for main output columns. Items: name, symbol, description.\n"
" -errorTemplates=<item>=<string>[,...] Templates for error output columns. Items: name, symbol, description.\n"
" -majorOrder=row|column Set major order of data.\n\n"
"The -templates <item> may be \"name\", \"symbol\" or \"description\".\n"
"The default main name, description, and symbol templates are \"%yNameDeriv\",\n"
" \"Derivative w.r.t %xSymbol of %ySymbol\", and \"d[%ySymbol]/d[%xSymbol]\", respectively.\n"
"The default error name, description, and symbol templates are \"%yNameDerivSigma\",\n"
" \"Sigma of derivative w.r.t %xSymbol of %ySymbol\", and \"Sigma[d[%ySymbol]/d[%xSymbol]]\", respectively.\n"
"Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")"

Definition at line 56 of file sddsderiv.c.