SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsconvolve.c
Go to the documentation of this file.
1/**
2 * @file sddsconvolve.c
3 * @brief Perform convolution, deconvolution, and correlation operations using the SDDS library.
4 *
5 * @details
6 * This program handles discrete Fourier convolution, deconvolution, and correlation between signal and response files.
7 * It assumes that the input files have uniform spacing of points and an equal number of data points.
8 *
9 * ### Features:
10 * - Convolution: \‍( O = S * R \‍)
11 * - Deconvolution: \‍( O = S / R \‍)
12 * - Correlation: \‍( O = S * Conj(R) \‍)
13 *
14 * It also supports options for Wiener filtering and noise handling during deconvolution.
15 *
16 * @section Usage
17 * ```
18 * sddsconvolve <signal-file> <response-file> <output>
19 * [-pipe=[input][,output]]
20 * [-signalColumns=<indepColumn>,<dataName>]
21 * [-responseColumns=<indepColumn>,<dataName>]
22 * [-outputColumns=<indepColumn>,<dataName>]
23 * [-reuse]
24 * [-majorOrder=row|column]
25 * [-deconvolve]
26 * [-noiseFraction=value]
27 * [-wienerFilter=value]
28 * [-correlate]
29 * ```
30 *
31 * @section Options
32 * | Option | Description |
33 * |---------------------------------------|---------------------------------------------------------------------------------------|
34 * | `-pipe` | Use standard input/output in place of the signal file and output file. |
35 * | `-signalColumns` | Specify the independent column and data name for the signal file. |
36 * | `-responseColumns` | Specify the independent column and data name for the response file. |
37 * | `-outputColumns` | Specify the independent column and data name for the output file. |
38 * | `-reuse` | Reuse the first page of the response file for each page of the signal file. |
39 * | `-majorOrder` | Set data ordering in the output file. |
40 * | `-deconvolve` | Perform deconvolution instead of convolution. |
41 * | `-noiseFraction` | Specify noise fraction to prevent divide-by-zero errors during deconvolution. |
42 * | `-wienerFilter` | Apply a Wiener filter with the specified fraction during deconvolution. |
43 * | `-correlate` | Perform correlation instead of convolution. |
44 *
45 * @subsection Incompatibilities
46 * - `-deconvolve` is incompatible with:
47 * - `-correlate`
48 * - For `-deconvolve`:
49 * - At least one of `-noiseFraction` or `-wienerFilter` must be specified.
50 * - Only one of the following may be specified:
51 * - `-noiseFraction=<value>`
52 * - `-wienerFilter=<value>`
53 *
54 * @copyright
55 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
56 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
57 *
58 * @license
59 * This file is distributed under the terms of the Software License Agreement
60 * found in the file LICENSE included with this distribution.
61 *
62 * @author
63 * Michael Borland, R. Soliday, H. Shang
64 */
65
66#include "mdb.h"
67#include "SDDS.h"
68#include "scan.h"
69#include "fftpackC.h"
70
71/* Enumeration for option types */
72enum option_type {
73 CLO_DECONVOLVE,
74 CLO_PIPE,
75 CLO_NOISE_FRACTION,
76 CLO_CORRELATE,
77 CLO_INDEPENDENTCOLUMN,
78 CLO_SIGNALCOLUMN,
79 CLO_RESPONSECOLUMN,
80 CLO_OUTPUTCOLUMN,
81 CLO_WIENER_FILTER,
82 CLO_MAJOR_ORDER,
83 CLO_REUSE,
84 N_OPTIONS
85};
86
87char *option[N_OPTIONS] = {
88 "deconvolve",
89 "pipe",
90 "noisefraction",
91 "correlate",
92 "independentcolumn",
93 "signalcolumn",
94 "responsecolumn",
95 "outputcolumn",
96 "wienerfilter",
97 "majorOrder",
98 "reuse",
99};
100
101#define USAGE "sddsconvolve <signal-file> <response-file> <output>\n\
102 [-pipe=[input][,output]]\n\
103 -signalColumns=<indepColumn>,<dataName>\n\
104 -responseColumns=<indepColumn>,<dataName>\n\
105 -outputColumns=<indepColumn>,<dataName>\n\
106 [-reuse] [-majorOrder=row|column]\n\
107 [{-deconvolve [{-noiseFraction=<value> | -wienerFilter=<value>}] | -correlate}]\n\n\
108Description:\n\
109 Performs discrete Fourier convolution, deconvolution, or correlation between signal and response files.\n\
110 Assumes uniform spacing of points in both input files and that both files contain the same number of data points.\n\
111\n\
112Mathematical Operations:\n\
113 - Convolution: O = S * R\n\
114 - Deconvolution: O = S / R\n\
115 - Correlation: O = S * Conj(R)\n\
116\n\
117Options:\n\
118 -signalColumns=<indepColumn>,<dataName> Specify the independent column and data name for the signal file.\n\
119 -responseColumns=<indepColumn>,<dataName> Specify the independent column and data name for the response file.\n\
120 -outputColumns=<indepColumn>,<dataName> Specify the independent column and data name for the output file.\n\
121 -reuse Reuse the first page of the response file for each page of the signal file.\n\
122 -majorOrder=row|column Set data ordering in the output file.\n\
123 -deconvolve Perform deconvolution instead of convolution.\n\
124 -noiseFraction=<value> Specify noise fraction to prevent divide-by-zero.\n\
125 -wienerFilter=<value> Apply a Wiener filter with the specified fraction.\n\
126 -correlate Perform correlation instead of convolution.\n\
127 -pipe=[input][,output] Use standard input/output in place of the signal file and output file.\n\
128\n\
129Program Information:\n\
130 Michael Borland (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n"
131
132void complex_multiply(double *r0, double *i0, double r1, double i1, double r2, double i2);
133void complex_divide(double *r0, double *i0, double r1, double i1, double r2, double i2, double threshold);
134void wrap_around_order(double *response1, double *t, double *response, int64_t nres, int64_t nsig);
135
136#define MODE_CONVOLVE 1
137#define MODE_DECONVOLVE 2
138#define MODE_CORRELATE 3
139
140int main(int argc, char **argv) {
141 SDDS_DATASET SDDS1, SDDS2, SDDSout;
142 int i_arg;
143 SCANNED_ARG *scanned;
144 char *input1, *input2, *output;
145 long mode, doWiener;
146 double *fft_sig, *fft_res, noise, mag2, threshold, range;
147 double *signal1, *signal2, *indep1, *indep2;
148 double WienerFraction, *WienerFilter = NULL;
149 unsigned long pipeFlags, majorOrderFlag;
150 char *input1Column[2], *input2Column[2], *outputColumn[2];
151 char description[1024];
152 long tmpfile_used, code1, code2;
153 int64_t i, rows1, rows2, nfreq;
154 int32_t parameters = 0;
155 char **parameterName = NULL;
156 short columnMajorOrder = -1, reuse = 0;
157
159 argc = scanargs(&scanned, argc, argv);
160 if (argc < 4 || argc > (4 + N_OPTIONS))
161 bomb(NULL, USAGE);
162
163 input1 = input2 = output = NULL;
164 mode = MODE_CONVOLVE;
165 noise = 1e-14;
166 input1Column[0] = input1Column[1] = NULL;
167 input2Column[0] = input2Column[1] = NULL;
168 outputColumn[0] = outputColumn[1] = NULL;
169 pipeFlags = 0;
170 doWiener = 0;
171
172 for (i_arg = 1; i_arg < argc; i_arg++) {
173 if (scanned[i_arg].arg_type == OPTION) {
174 /* process options here */
175 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
176 case CLO_MAJOR_ORDER:
177 majorOrderFlag = 0;
178 scanned[i_arg].n_items--;
179 if (scanned[i_arg].n_items > 0 &&
180 (!scanItemList(&majorOrderFlag, scanned[i_arg].list + 1, &scanned[i_arg].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 or values.");
184 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
185 columnMajorOrder = 1;
186 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
187 columnMajorOrder = 0;
188 break;
189 case CLO_DECONVOLVE:
190 mode = MODE_DECONVOLVE;
191 break;
192 case CLO_CORRELATE:
193 mode = MODE_CORRELATE;
194 break;
195 case CLO_PIPE:
196 if (!processPipeOption(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1, &pipeFlags))
197 SDDS_Bomb("Invalid -pipe syntax.");
198 break;
199 case CLO_NOISE_FRACTION:
200 if (scanned[i_arg].n_items != 2 || sscanf(scanned[i_arg].list[1], "%lf", &noise) != 1 || noise <= 0)
201 SDDS_Bomb("Invalid -noisefraction syntax or value.");
202 break;
203 case CLO_WIENER_FILTER:
204 if (scanned[i_arg].n_items != 2 || sscanf(scanned[i_arg].list[1], "%lf", &WienerFraction) != 1 ||
205 WienerFraction <= 0 || WienerFraction >= 1)
206 SDDS_Bomb("Invalid -wienerfilter syntax or value.");
207 doWiener = 1;
208 break;
209 case CLO_SIGNALCOLUMN:
210 if (scanned[i_arg].n_items != 3 ||
211 !strlen(input1Column[0] = scanned[i_arg].list[1]) ||
212 !strlen(input1Column[1] = scanned[i_arg].list[2]))
213 SDDS_Bomb("Invalid -signalColumns syntax.");
214 break;
215 case CLO_RESPONSECOLUMN:
216 if (scanned[i_arg].n_items != 3 ||
217 !strlen(input2Column[0] = scanned[i_arg].list[1]) ||
218 !strlen(input2Column[1] = scanned[i_arg].list[2]))
219 SDDS_Bomb("Invalid -responseColumns syntax.");
220 break;
221 case CLO_OUTPUTCOLUMN:
222 if (scanned[i_arg].n_items != 3 ||
223 !strlen(outputColumn[0] = scanned[i_arg].list[1]) ||
224 !strlen(outputColumn[1] = scanned[i_arg].list[2]))
225 SDDS_Bomb("Invalid -outputColumns syntax.");
226 break;
227 case CLO_REUSE:
228 reuse = 1;
229 break;
230 default:
231 SDDS_Bomb("Unknown option provided.");
232 break;
233 }
234 } else {
235 if (!input1)
236 input1 = scanned[i_arg].list[0];
237 else if (!input2)
238 input2 = scanned[i_arg].list[0];
239 else if (!output)
240 output = scanned[i_arg].list[0];
241 else
242 SDDS_Bomb("Too many filenames provided.");
243 }
244 }
245
246 if (pipeFlags & USE_STDIN && input1) {
247 if (output)
248 SDDS_Bomb("Too many filenames provided.");
249 output = input2;
250 input2 = input1;
251 input1 = NULL;
252 }
253 if (!input1Column[0] || !input1Column[1] || !strlen(input1Column[0]) || !strlen(input1Column[1]))
254 SDDS_Bomb("SignalColumns not provided.");
255 if (!input2Column[0] || !input2Column[1] || !strlen(input2Column[0]) || !strlen(input2Column[1]))
256 SDDS_Bomb("ResponseColumns not provided.");
257 if (!outputColumn[0] || !outputColumn[1] || !strlen(outputColumn[0]) || !strlen(outputColumn[1]))
258 SDDS_Bomb("OutputColumns not provided.");
259
260 processFilenames("sddsconvolve", &input1, &output, pipeFlags, 1, &tmpfile_used);
261 if (!input2)
262 SDDS_Bomb("Second input file not specified.");
263
264 if (!SDDS_InitializeInput(&SDDS1, input1) || !SDDS_InitializeInput(&SDDS2, input2)) {
265 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
266 exit(EXIT_FAILURE);
267 }
268
269 switch (mode) {
270 case MODE_CONVOLVE:
271 sprintf(description, "Convolution of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
272 break;
273 case MODE_DECONVOLVE:
274 sprintf(description, "Deconvolution of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
275 break;
276 case MODE_CORRELATE:
277 sprintf(description, "Correlation of signal '%s' with response '%s'", input1Column[1], input2Column[1]);
278 break;
279 }
280
281 parameterName = SDDS_GetParameterNames(&SDDS1, &parameters);
282 if (!SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 1, NULL, NULL, output) ||
283 !SDDS_TransferColumnDefinition(&SDDSout, &SDDS1, input1Column[0], outputColumn[0]) ||
284 0 > SDDS_DefineColumn(&SDDSout, outputColumn[1], NULL, NULL, description, NULL, SDDS_DOUBLE, 0)) {
285 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
286 exit(EXIT_FAILURE);
287 }
288 if (columnMajorOrder != -1)
289 SDDSout.layout.data_mode.column_major = columnMajorOrder;
290 else
291 SDDSout.layout.data_mode.column_major = SDDS1.layout.data_mode.column_major;
292
293 if (parameters) {
294 for (i = 0; i < parameters; i++)
295 if (!SDDS_TransferParameterDefinition(&SDDSout, &SDDS1, parameterName[i], parameterName[i]))
296 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
297 }
298
299 if (!SDDS_WriteLayout(&SDDSout)) {
300 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
301 exit(EXIT_FAILURE);
302 }
303
304 code2 = -1;
305 while ((code1 = SDDS_ReadPage(&SDDS1)) > 0) {
306 if ((rows1 = SDDS_RowCount(&SDDS1)) <= 0) {
307 fprintf(stderr, "Warning (sddsconvolve): Skipping page due to no signal rows.\n");
308 continue;
309 }
310 if (reuse) {
311 if (code2 == -1) {
312 if ((code2 = SDDS_ReadPage(&SDDS2)) <= 0) {
313 fprintf(stderr, "Error (sddsconvolve): Couldn't read data from response file.\n");
314 exit(EXIT_FAILURE);
315 }
316 if ((rows2 = SDDS_RowCount(&SDDS2)) < 0) {
317 fprintf(stderr, "Error (sddsconvolve): Response file has zero rows on first page.\n");
318 exit(EXIT_FAILURE);
319 }
320 }
321 } else {
322 if ((code2 = SDDS_ReadPage(&SDDS2)) <= 0)
323 break;
324 rows2 = SDDS_RowCount(&SDDS2);
325 }
326 if (rows1 != rows2)
327 SDDS_Bomb("Different numbers of points for signal and response.");
328
329 if (!(signal1 = SDDS_GetColumnInDoubles(&SDDS1, input1Column[1])) ||
330 !(indep1 = SDDS_GetColumnInDoubles(&SDDS1, input1Column[0])) ||
331 !(signal2 = SDDS_GetColumnInDoubles(&SDDS2, input2Column[1])) ||
332 !(indep2 = SDDS_GetColumnInDoubles(&SDDS2, input2Column[0]))) {
333 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
334 exit(EXIT_FAILURE);
335 }
336
337 if (!(fft_sig = SDDS_Calloc(sizeof(*fft_sig), (2 * rows1 + 2))) ||
338 !(fft_res = SDDS_Calloc(sizeof(*fft_res), (2 * rows1 + 2)))) {
339 SDDS_SetError("Memory allocation failure.");
340 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
341 exit(EXIT_FAILURE);
342 }
343
344 /* Rearrange response for FFT */
345 wrap_around_order(fft_res, indep2, signal2, rows2, rows1);
346 for (i = 0; i < rows1; i++)
347 fft_sig[i] = signal1[i];
348
349 /* Perform FFT on signal and response */
350 realFFT2(fft_sig, fft_sig, 2 * rows1, 0);
351 realFFT2(fft_res, fft_res, 2 * rows1, 0);
352 nfreq = rows1 + 1;
353 range = 2 * rows1 * (indep1[rows1 - 1] - indep1[0]) / (rows1 - 1);
354
355 if (mode == MODE_CONVOLVE || mode == MODE_CORRELATE) {
356 if (mode == MODE_CORRELATE)
357 /* Take complex conjugate of response FFT */
358 for (i = 0; i < nfreq; i++)
359 fft_res[2 * i + 1] = -fft_res[2 * i + 1];
360
361 /* Multiply FFTs */
362 for (i = 0; i < nfreq; i++) {
363 complex_multiply(&fft_sig[2 * i], &fft_sig[2 * i + 1],
364 fft_sig[2 * i], fft_sig[2 * i + 1],
365 fft_res[2 * i], fft_res[2 * i + 1]);
366 }
367
368 /* Inverse FFT */
369 realFFT2(fft_sig, fft_sig, 2 * rows1, INVERSE_FFT);
370
371 /* Apply normalization factor */
372 for (i = 0; i < rows1; i++)
373 fft_sig[i] *= range;
374
375 /* Write output */
376 if (!SDDS_StartPage(&SDDSout, rows1) ||
377 !SDDS_CopyParameters(&SDDSout, &SDDS1) ||
378 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, fft_sig, rows1, outputColumn[1]) ||
379 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, indep1, rows1, outputColumn[0]) ||
380 !SDDS_WritePage(&SDDSout)) {
381 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
382 exit(EXIT_FAILURE);
383 }
384 } else if (mode == MODE_DECONVOLVE) {
385 double maxMag2;
386 /* Calculate maximum magnitude squared */
387 for (i = threshold = 0; i < nfreq; i++) {
388 if ((mag2 = sqr(fft_res[2 * i]) + sqr(fft_res[2 * i + 1])) > threshold)
389 threshold = mag2;
390 }
391 maxMag2 = threshold;
392 threshold = threshold * noise;
393
394 if (doWiener) {
395 /* Compute and apply Wiener filter */
396 double *S = NULL, *N = NULL, wThreshold;
397 if (!(WienerFilter = malloc(sizeof(*WienerFilter) * nfreq)) ||
398 !(S = malloc(sizeof(*S) * nfreq)) ||
399 !(N = malloc(sizeof(*N) * nfreq))) {
400 SDDS_Bomb("Memory allocation failure.");
401 }
402 wThreshold = maxMag2 * sqr(WienerFraction);
403 for (i = 0; i < nfreq; i++) {
404 S[i] = sqrt(sqr(fft_res[2 * i]) + sqr(fft_res[2 * i + 1]));
405 if (sqr(S[i]) < wThreshold) {
406 N[i] = S[i];
407 S[i] = 0;
408 } else {
409 S[i] = S[i] - sqrt(wThreshold);
410 N[i] = sqrt(wThreshold);
411 }
412 }
413 for (i = 0; i < nfreq; i++)
414 WienerFilter[i] = sqr(S[i]) / (sqr(S[i]) + sqr(N[i]) + threshold);
415 free(N);
416 free(S);
417 }
418
419 /* Perform division in frequency domain */
420 for (i = 0; i < nfreq; i++) {
421 complex_divide(&fft_sig[2 * i], &fft_sig[2 * i + 1],
422 fft_sig[2 * i], fft_sig[2 * i + 1],
423 fft_res[2 * i], fft_res[2 * i + 1],
424 threshold);
425 }
426
427 if (doWiener) {
428 for (i = 0; i < nfreq; i++) {
429 fft_sig[2 * i] *= WienerFilter[i];
430 fft_sig[2 * i + 1] *= WienerFilter[i];
431 }
432 free(WienerFilter);
433 }
434
435 /* Inverse FFT */
436 realFFT2(fft_sig, fft_sig, 2 * rows1, INVERSE_FFT);
437
438 /* Apply normalization factor */
439 for (i = 0; i < rows1; i++)
440 fft_sig[i] = fft_sig[i] / range;
441
442 /* Write output */
443 if (!SDDS_StartPage(&SDDSout, rows1) ||
444 !SDDS_CopyParameters(&SDDSout, &SDDS1) ||
445 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, fft_sig, rows1, outputColumn[1]) ||
446 !SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, indep1, rows1, outputColumn[0]) ||
447 !SDDS_WritePage(&SDDSout)) {
448 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
449 exit(EXIT_FAILURE);
450 }
451 } else {
452 SDDS_Bomb("Unexpected processing mode encountered.");
453 }
454
455 /* Free allocated memory for this iteration */
456 free(fft_sig);
457 fft_sig = NULL;
458 free(fft_res);
459 fft_res = NULL;
460 free(signal1);
461 free(indep1);
462 free(signal2);
463 free(indep2);
464 signal1 = indep1 = signal2 = indep2 = NULL;
465 }
466
467 if (!SDDS_Terminate(&SDDS1) || !SDDS_Terminate(&SDDS2) || !SDDS_Terminate(&SDDSout)) {
468 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
469 exit(EXIT_FAILURE);
470 }
471
472 if (tmpfile_used && !replaceFileAndBackUp(input1, output))
473 exit(EXIT_FAILURE);
474
475 free(parameterName);
476 free_scanargs(&scanned, argc);
477
478 return EXIT_SUCCESS;
479}
480
481void wrap_around_order(double *response1, double *t, double *response, int64_t nres, int64_t nsig) {
482 int64_t i;
483 int64_t iz;
484
485 for (iz = 0; iz < nres; iz++)
486 if (t[iz] >= 0)
487 break;
488 if (iz == nres)
489 bomb("Response function is acausal.", NULL);
490
491 fill_double_array(response1, 2 * nsig + 2, 0.0L);
492 for (i = iz; i < nres; i++)
493 response1[i - iz] = response[i];
494 for (i = 0; i < iz; i++)
495 response1[2 * nsig - (iz - i)] = response[i];
496}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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.
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_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_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_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_TransferParameterDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a parameter definition from a source dataset to a target dataset.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters 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
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * SDDS_Calloc(size_t nelem, size_t elem_size)
Allocates zero-initialized memory for an array of elements.
Definition SDDS_utils.c:617
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
void fill_double_array(double *array, long n, double value)
Fills a double array with the specified value.
Definition fill_array.c:27
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
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
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.
void complex_divide(double *r0, double *i0, double r1, double i1, double r2, double i2, double threshold)
Divides two complex numbers.
Definition complex.cc:105
void complex_multiply(double *r0, double *i0, double r1, double i1, double r2, double i2)
Multiplies two complex numbers.
Definition complex.cc:81