SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
sddscombinelogfiles.c
Go to the documentation of this file.
1/**
2 * @file sddscombinelogfiles.c
3 * @brief Combines multiple SDDS log files into a single file, retaining only common timestamps.
4 *
5 * @details
6 * This program processes SDDS log files in the one-PV-per-file format, merging them into a single SDDS file.
7 * It retains only the timestamps common across all input files and supports flexible input-output configurations
8 * such as pipe-based I/O and overwriting existing output files.
9 *
10 * @section Usage
11 * ```
12 * sddscombinelogfiles [<SDDSinputfilelist>] [<SDDSoutputfile>]
13 * [-pipe=[output]]
14 * [-overwrite]
15 * [-threads=<number>]
16 * ```
17 *
18 * @section Options
19 * | Option | Description |
20 * |--------------------|-----------------------------------------------------------------|
21 * | `-pipe` | Use pipe output for the SDDS file instead of writing to a file. |
22 * | `-overwrite` | Overwrite the output file if it already exists. |
23 * | `-threads` | Number of input files to load concurrently. |
24 *
25 * @copyright
26 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
27 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
28 *
29 * @license
30 * This file is distributed under the terms of the Software License Agreement
31 * found in the file LICENSE included with this distribution.
32 *
33 * @author
34 * R. Soliday, L. Emery
35 */
36
37#include "mdb.h"
38#include "scan.h"
39#include "SDDS.h"
40
41/* Enumeration for option types */
42enum option_type {
43 SET_PIPE,
44 SET_OVERWRITE,
45 SET_THREADS,
46 N_OPTIONS
47};
48
49static char *option[N_OPTIONS] = {
50 "pipe",
51 "overwrite",
52 "threads"
53};
54
55const char *USAGE =
56 "Usage: sddscombinelogfiles [<SDDSinputfilelist>] [<SDDSoutputfile>]\n"
57 " [-pipe=[output]] [-overwrite] [-threads=<number>]\n\n"
58 "This program combines data logger output files that are in the one-PV-per-file format.\n"
59 "Only the timestamps present in all input files are retained in the output file.\n\n"
60 "Options:\n"
61 " -pipe=[output] Specify the pipe output.\n"
62 " -overwrite Overwrite the output file if it already exists.\n"
63 " -threads=<number> Number of input files to load concurrently. The default is 1.\n\n"
64 "Example:\n"
65 " sddscombinelogfiles input1.sdds input2.sdds output.sdds -overwrite\n\n"
66 "Link date: " __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION "\n";
67
68typedef struct {
69 double *timeValues;
70 double *dataValues;
71 char *dataName;
72 int64_t rows;
74
75typedef struct {
76 LOG_PAGE_DATA *page;
77 int pages;
78 int status;
79 char error[1024];
81
82static int LoadLogFile(const char *filename, LOG_FILE_DATA *logFile);
83static void FreeLogFileData(LOG_FILE_DATA *logFile);
84
85int main(int argc, char **argv) {
86 SDDS_DATASET SDDS_output;
87 SCANNED_ARG *s_arg;
88 KEYED_EQUIVALENT **keyGroup = NULL;
89 long keyGroups = 0;
90 char **inputfile = NULL;
91 int inputfiles = 0;
92 char *outputfile = NULL;
93 int i_arg, n, row, z;
94 int threads = 1;
95 int64_t i, j, m, r, s;
96 unsigned long pipeFlags = 0;
97 int overwrite = 0;
98 double **timeValues = NULL;
99 double **dataValues = NULL;
100 short **flag = NULL;
101 int64_t *rows = NULL;
102 char **dataNames = NULL;
103 char **uniqueDataName = NULL;
104 int uniqueDataNames = 0;
105 int page = 0;
106 int pages;
107 int found;
108 double *outputTimeValues = NULL;
109 double **outputDataValues = NULL;
110 int64_t allocated_rows = 0;
111 int **array = NULL;
112 int *arrayCount;
113 LOG_FILE_DATA *logFile = NULL;
114
116 argc = scanargs(&s_arg, argc, argv);
117
118 if (argc < 3) {
119 fprintf(stderr, "%s", USAGE);
120 return EXIT_FAILURE;
121 }
122
123 for (i_arg = 1; i_arg < argc; i_arg++) {
124 if (s_arg[i_arg].arg_type == OPTION) {
125 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
126 case SET_OVERWRITE:
127 overwrite = 1;
128 break;
129 case SET_THREADS:
130 if (s_arg[i_arg].n_items != 2 ||
131 sscanf(s_arg[i_arg].list[1], "%d", &threads) != 1 ||
132 threads < 1) {
133 fprintf(stderr, "Error: Invalid -threads option syntax.\n");
134 return EXIT_FAILURE;
135 }
136 break;
137 case SET_PIPE:
138 if (!processPipeOption(s_arg[i_arg].list + 1,
139 s_arg[i_arg].n_items - 1,
140 &pipeFlags)) {
141 fprintf(stderr, "Error: Invalid -pipe option syntax.\n");
142 return EXIT_FAILURE;
143 }
144 if (pipeFlags & USE_STDIN) {
145 fprintf(stderr, "Error: -pipe=in is not supported.\n");
146 return EXIT_FAILURE;
147 }
148 break;
149 default:
150 fprintf(stderr, "Error: Unrecognized option.\n%s", USAGE);
151 return EXIT_FAILURE;
152 }
153 } else {
154 inputfile = trealloc(inputfile, sizeof(*inputfile) * (inputfiles + 1));
155 inputfile[inputfiles++] = s_arg[i_arg].list[0];
156 }
157 }
158
159 if (inputfiles > 1) {
160 if (!(pipeFlags & USE_STDOUT)) {
161 outputfile = inputfile[--inputfiles];
162 if (fexists(outputfile) && !overwrite) {
163 fprintf(stderr, "Error: Output file '%s' already exists. Use -overwrite to replace it.\n", outputfile);
164 return EXIT_FAILURE;
165 }
166 }
167 } else if (inputfiles == 1) {
168 if ((pipeFlags & USE_STDOUT) && outputfile) {
169 fprintf(stderr, "Error: Too many filenames provided with -pipe=output.\n");
170 return EXIT_FAILURE;
171 }
172 } else {
173 fprintf(stderr, "Error: No input filenames provided.\n%s", USAGE);
174 return EXIT_FAILURE;
175 }
176
177 if (threads > inputfiles)
178 threads = inputfiles;
179
180 logFile = calloc(inputfiles, sizeof(*logFile));
181 if (!logFile) {
182 fprintf(stderr, "Error: Memory allocation failure.\n");
183 return EXIT_FAILURE;
184 }
185
186#pragma omp parallel for if (threads > 1 && inputfiles > 1) num_threads(threads) schedule(dynamic)
187 for (i = 0; i < inputfiles; i++) {
188 LoadLogFile(inputfile[i], &logFile[i]);
189 }
190
191 pages = 0;
192 for (i = 0; i < inputfiles; i++) {
193 if (!logFile[i].status) {
194 fprintf(stderr, "%s\n", logFile[i].error);
195 for (j = 0; j < inputfiles; j++)
196 FreeLogFileData(&logFile[j]);
197 free(logFile);
198 return EXIT_FAILURE;
199 }
200 pages += logFile[i].pages;
201 }
202
203 timeValues = malloc(sizeof(*timeValues) * pages);
204 dataValues = malloc(sizeof(*dataValues) * pages);
205 dataNames = malloc(sizeof(*dataNames) * pages);
206 rows = malloc(sizeof(*rows) * pages);
207 if (!timeValues || !dataValues || !dataNames || !rows) {
208 fprintf(stderr, "Error: Memory allocation failure.\n");
209 for (i = 0; i < inputfiles; i++)
210 FreeLogFileData(&logFile[i]);
211 free(logFile);
212 return EXIT_FAILURE;
213 }
214
215 page = 0;
216 for (i = 0; i < inputfiles; i++) {
217 int filePage;
218 for (filePage = 0; filePage < logFile[i].pages; filePage++) {
219 timeValues[page] = logFile[i].page[filePage].timeValues;
220 dataValues[page] = logFile[i].page[filePage].dataValues;
221 dataNames[page] = logFile[i].page[filePage].dataName;
222 rows[page] = logFile[i].page[filePage].rows;
223 logFile[i].page[filePage].timeValues = NULL;
224 logFile[i].page[filePage].dataValues = NULL;
225 logFile[i].page[filePage].dataName = NULL;
226 page++;
227 }
228 FreeLogFileData(&logFile[i]);
229 }
230 free(logFile);
231
232 pages = page;
233
234 /* Identify unique data names */
235 for (page = 0; page < pages; page++) {
236 found = 0;
237 for (i = 0; i < uniqueDataNames; i++) {
238 if (strcmp(dataNames[page], uniqueDataName[i]) == 0) {
239 found = 1;
240 break;
241 }
242 }
243 if (!found) {
244 uniqueDataName = realloc(uniqueDataName, sizeof(*uniqueDataName) * (uniqueDataNames + 1));
245 SDDS_CopyString(&uniqueDataName[uniqueDataNames], dataNames[page]);
246 uniqueDataNames++;
247 }
248 }
249
250 /* Initialize output SDDS file */
251 if (!SDDS_InitializeOutput(&SDDS_output, SDDS_BINARY, 0, NULL, NULL, outputfile)) {
252 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
253 return EXIT_FAILURE;
254 }
255
256 if (!SDDS_DefineSimpleColumn(&SDDS_output, "Time", "s", SDDS_DOUBLE)) {
257 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
258 return EXIT_FAILURE;
259 }
260
261 for (i = 0; i < uniqueDataNames; i++) {
262 if (!SDDS_DefineSimpleColumn(&SDDS_output, uniqueDataName[i], NULL, SDDS_DOUBLE)) {
263 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
264 return EXIT_FAILURE;
265 }
266 }
267
268 outputDataValues = malloc(sizeof(*outputDataValues) * uniqueDataNames);
269 if (uniqueDataNames == 1) {
270 /* Single PV: Concatenate all data */
271 for (page = 0; page < pages; page++) {
272 allocated_rows += rows[page];
273 }
274
275 outputTimeValues = malloc(sizeof(*outputTimeValues) * allocated_rows);
276 outputDataValues[0] = malloc(sizeof(*(outputDataValues[0])) * allocated_rows);
277
278 i = 0;
279 for (page = 0; page < pages; page++) {
280 for (j = 0; j < rows[page]; j++) {
281 outputTimeValues[i] = timeValues[page][j];
282 outputDataValues[0][i] = dataValues[page][j];
283 i++;
284 }
285 }
286 } else {
287 /* Multiple PVs: Retain only common timestamps */
288 flag = malloc(sizeof(*flag) * pages);
289 for (page = 0; page < pages; page++) {
290 flag[page] = calloc(rows[page], sizeof(*(flag[page])));
291 }
292
293 array = malloc(sizeof(*array) * uniqueDataNames);
294 arrayCount = calloc(uniqueDataNames, sizeof(*arrayCount));
295
296 for (i = 0; i < uniqueDataNames; i++) {
297 for (page = 0; page < pages; page++) {
298 if (strcmp(dataNames[page], uniqueDataName[i]) == 0) {
299 arrayCount[i]++;
300 if (arrayCount[i] == 1) {
301 array[i] = malloc(sizeof(*(array[i])));
302 } else {
303 array[i] = realloc(array[i], sizeof(*(array[i])) * arrayCount[i]);
304 }
305 array[i][arrayCount[i] - 1] = page;
306 }
307 }
308 }
309
310 for (i = 0; i < arrayCount[0]; i++) {
311 keyGroup = MakeSortedKeyGroups(&keyGroups, SDDS_DOUBLE, timeValues[array[0][i]], rows[array[0][i]]);
312 for (n = 1; n < uniqueDataNames; n++) {
313 for (m = 0; m < arrayCount[n]; m++) {
314 if ((i == m) && (rows[array[0][i]] == rows[array[n][m]]) && (rows[array[0][i]] > 10)) {
315 if ((timeValues[array[0][i]][0] == timeValues[array[n][m]][0]) &&
316 (timeValues[array[0][i]][1] == timeValues[array[n][m]][1]) &&
317 (timeValues[array[0][i]][rows[array[0][i]] - 2] == timeValues[array[n][m]][rows[array[n][m]] - 2]) &&
318 (timeValues[array[0][i]][rows[array[0][i]] - 1] == timeValues[array[n][m]][rows[array[n][m]] - 1])) {
319 /* Assume the entire page matches because it has the same number of rows and key timestamps match */
320 for (r = 0; r < rows[array[n][m]]; r++) {
321 if (flag[array[n][m]][r]) {
322 continue;
323 }
324 flag[array[0][i]][r] += 1;
325 flag[array[n][m]][r] = 1;
326 }
327 }
328 }
329
330 for (r = 0; r < rows[array[n][m]]; r++) {
331 if (flag[array[n][m]][r]) {
332 continue;
333 }
334 row = FindMatchingKeyGroup(keyGroup, keyGroups, SDDS_DOUBLE, &(timeValues[array[n][m]][r]), 1);
335 if (row >= 0) {
336 flag[array[0][i]][row] += 1;
337 flag[array[n][m]][r] = 1;
338 }
339 }
340 }
341 }
342
343 for (j = 0; j < keyGroups; j++) {
344 free(keyGroup[j]->equivalent);
345 free(keyGroup[j]);
346 }
347 free(keyGroup);
348 }
349
350 z = uniqueDataNames - 1;
351 for (n = 0; n < arrayCount[0]; n++) {
352 for (m = 0; m < rows[array[0][n]]; m++) {
353 if (flag[array[0][n]][m] >= z) {
354 allocated_rows++;
355 }
356 }
357 }
358
359 outputTimeValues = malloc(sizeof(*outputTimeValues) * allocated_rows);
360 for (i = 0; i < uniqueDataNames; i++) {
361 outputDataValues[i] = malloc(sizeof(*(outputDataValues[i])) * allocated_rows);
362 }
363
364 s = 0;
365 for (i = 0; i < arrayCount[0]; i++) {
366 for (j = 0; j < rows[array[0][i]]; j++) {
367 if (flag[array[0][i]][j] >= z) {
368 outputTimeValues[s] = timeValues[array[0][i]][j];
369 outputDataValues[0][s] = dataValues[array[0][i]][j];
370 s++;
371 }
372 }
373 }
374
375 if (s == 0) {
376 fprintf(stderr, "Error: No matching 'Time' rows found in input files.\n");
377 return EXIT_FAILURE;
378 }
379
380 keyGroup = MakeSortedKeyGroups(&keyGroups, SDDS_DOUBLE, outputTimeValues, s);
381
382 for (n = 1; n < uniqueDataNames; n++) {
383 for (m = 0; m < arrayCount[n]; m++) {
384 for (r = 0; r < rows[array[n][m]]; r++) {
385 if (flag[array[n][m]][r]) {
386 row = FindMatchingKeyGroup(keyGroup, keyGroups, SDDS_DOUBLE, &(timeValues[array[n][m]][r]), 1);
387 if (row >= 0) {
388 outputDataValues[n][row] = dataValues[array[n][m]][r];
389 }
390 }
391 }
392 }
393 }
394
395 for (i = 0; i < uniqueDataNames; i++) {
396 free(array[i]);
397 }
398
399 for (j = 0; j < keyGroups; j++) {
400 if (keyGroup[j]->equivalent)
401 free(keyGroup[j]->equivalent);
402 if (keyGroup[j])
403 free(keyGroup[j]);
404 }
405
406 for (page = 0; page < pages; page++) {
407 free(flag[page]);
408 }
409
410 free(array);
411 free(keyGroup);
412 free(arrayCount);
413 free(flag);
414 }
415
416 /* Free allocated memory for input data */
417 for (page = 0; page < pages; page++) {
418 if (timeValues[page])
419 free(timeValues[page]);
420 if (dataValues[page])
421 free(dataValues[page]);
422 free(dataNames[page]);
423 }
424 free(timeValues);
425 free(dataValues);
426 free(dataNames);
427
428 /* Write the output SDDS file */
429 if (!SDDS_WriteLayout(&SDDS_output)) {
430 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
431 return EXIT_FAILURE;
432 }
433
434 if (!SDDS_StartPage(&SDDS_output, allocated_rows)) {
435 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
436 return EXIT_FAILURE;
437 }
438
439 if (!SDDS_SetColumnFromDoubles(&SDDS_output, SDDS_SET_BY_NAME, outputTimeValues, allocated_rows, "Time")) {
440 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
441 return EXIT_FAILURE;
442 }
443
444 for (i = 0; i < uniqueDataNames; i++) {
445 if (!SDDS_SetColumnFromDoubles(&SDDS_output, SDDS_SET_BY_NAME, outputDataValues[i], allocated_rows, uniqueDataName[i])) {
446 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
447 return EXIT_FAILURE;
448 }
449 }
450
451 if (!SDDS_WriteTable(&SDDS_output)) {
452 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
453 return EXIT_FAILURE;
454 }
455
456 if (!SDDS_Terminate(&SDDS_output)) {
457 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
458 return EXIT_FAILURE;
459 }
460
461 /* Free allocated memory for output data */
462 for (i = 0; i < uniqueDataNames; i++) {
463 free(uniqueDataName[i]);
464 free(outputDataValues[i]);
465 }
466 free(outputTimeValues);
467 free(outputDataValues);
468 free(uniqueDataName);
469 free(rows);
470
471 if (inputfiles > 0) {
472 free(inputfile);
473 }
474
475 free_scanargs(&s_arg, argc);
476
477 return EXIT_SUCCESS;
478}
479
480static int LoadLogFile(const char *filename, LOG_FILE_DATA *logFile) {
481 SDDS_DATASET SDDS_input;
482 char **columnname = NULL;
483 int32_t columnnames = 0;
484 int dataIndex = -1;
485 int32_t readCode;
486 int64_t j;
487 int initialized = 0;
488
489 logFile->page = NULL;
490 logFile->pages = 0;
491 logFile->status = 0;
492 logFile->error[0] = 0;
493
494 if (!SDDS_InitializeInput(&SDDS_input, (char *)filename)) {
495 snprintf(logFile->error, sizeof(logFile->error), "Error: Unable to open '%s'.", filename);
496 return 0;
497 }
498 initialized = 1;
499
500 columnname = SDDS_GetColumnNames(&SDDS_input, &columnnames);
501 if (columnname == NULL) {
502 snprintf(logFile->error, sizeof(logFile->error), "Error: Unable to read column names from '%s'.", filename);
503 goto fail;
504 }
505
506 if (columnnames > 3 || columnnames < 2) {
507 snprintf(logFile->error, sizeof(logFile->error), "Error: Unexpected number of columns in '%s'.", filename);
508 goto fail;
509 }
510
511 if (columnnames == 2) {
512 if (strcmp("Time", columnname[0]) == 0) {
513 dataIndex = 1;
514 } else if (strcmp("Time", columnname[1]) == 0) {
515 dataIndex = 0;
516 } else {
517 snprintf(logFile->error, sizeof(logFile->error), "Error: 'Time' column is missing in '%s'.", filename);
518 goto fail;
519 }
520 }
521
522 if (columnnames == 3) {
523 if (strcmp("CAerrors", columnname[0]) == 0) {
524 if (strcmp("Time", columnname[1]) == 0) {
525 dataIndex = 2;
526 } else if (strcmp("Time", columnname[2]) == 0) {
527 dataIndex = 1;
528 } else {
529 snprintf(logFile->error, sizeof(logFile->error), "Error: 'Time' column is missing in '%s'.", filename);
530 goto fail;
531 }
532 } else if (strcmp("CAerrors", columnname[1]) == 0) {
533 if (strcmp("Time", columnname[0]) == 0) {
534 dataIndex = 2;
535 } else if (strcmp("Time", columnname[2]) == 0) {
536 dataIndex = 0;
537 } else {
538 snprintf(logFile->error, sizeof(logFile->error), "Error: 'Time' column is missing in '%s'.", filename);
539 goto fail;
540 }
541 } else if (strcmp("CAerrors", columnname[2]) == 0) {
542 if (strcmp("Time", columnname[0]) == 0) {
543 dataIndex = 1;
544 } else if (strcmp("Time", columnname[1]) == 0) {
545 dataIndex = 0;
546 } else {
547 snprintf(logFile->error, sizeof(logFile->error), "Error: 'Time' column is missing in '%s'.", filename);
548 goto fail;
549 }
550 } else {
551 snprintf(logFile->error, sizeof(logFile->error), "Error: 'CAerrors' column is missing in '%s'.", filename);
552 goto fail;
553 }
554 }
555
556 while ((readCode = SDDS_ReadTable(&SDDS_input)) > 0) {
557 int page = logFile->pages;
558 LOG_PAGE_DATA *pageData;
559 pageData = realloc(logFile->page, sizeof(*logFile->page) * (page + 1));
560 if (!pageData) {
561 snprintf(logFile->error, sizeof(logFile->error), "Error: Memory allocation failure.");
562 goto fail;
563 }
564 logFile->page = pageData;
565 logFile->page[page].timeValues = NULL;
566 logFile->page[page].dataValues = NULL;
567 logFile->page[page].dataName = NULL;
568 logFile->page[page].rows = SDDS_RowCount(&SDDS_input);
569 logFile->pages++;
570
571 if (!SDDS_CopyString(&logFile->page[page].dataName, columnname[dataIndex])) {
572 snprintf(logFile->error, sizeof(logFile->error), "Error: Memory allocation failure.");
573 goto fail;
574 }
575 if (logFile->page[page].rows > 0) {
576 logFile->page[page].timeValues = SDDS_GetColumnInDoubles(&SDDS_input, "Time");
577 if (logFile->page[page].timeValues == NULL) {
578 snprintf(logFile->error, sizeof(logFile->error), "Error: Unable to read 'Time' data from '%s'.", filename);
579 goto fail;
580 }
581
582 logFile->page[page].dataValues = SDDS_GetColumnInDoubles(&SDDS_input, columnname[dataIndex]);
583 if (logFile->page[page].dataValues == NULL) {
584 snprintf(logFile->error, sizeof(logFile->error), "Error: Unable to read '%s' data from '%s'.", columnname[dataIndex], filename);
585 goto fail;
586 }
587 }
588 }
589 if (readCode == 0) {
590 snprintf(logFile->error, sizeof(logFile->error), "Error: Unable to read data from '%s'.", filename);
591 goto fail;
592 }
593
594 for (j = 0; j < columnnames; j++)
595 free(columnname[j]);
596 free(columnname);
597 columnname = NULL;
598
599 if (!SDDS_Terminate(&SDDS_input)) {
600 initialized = 0;
601 snprintf(logFile->error, sizeof(logFile->error), "Error: Unable to close '%s'.", filename);
602 goto fail;
603 }
604 initialized = 0;
605
606 logFile->status = 1;
607 return 1;
608
609fail:
610 if (columnname) {
611 for (j = 0; j < columnnames; j++)
612 free(columnname[j]);
613 free(columnname);
614 }
615 if (initialized)
616 SDDS_Terminate(&SDDS_input);
617 FreeLogFileData(logFile);
618 return 0;
619}
620
621static void FreeLogFileData(LOG_FILE_DATA *logFile) {
622 int page;
623 if (!logFile)
624 return;
625 for (page = 0; page < logFile->pages; page++) {
626 free(logFile->page[page].timeValues);
627 free(logFile->page[page].dataValues);
628 free(logFile->page[page].dataName);
629 }
630 free(logFile->page);
631 logFile->page = NULL;
632 logFile->pages = 0;
633}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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:50
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_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
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:474
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:922
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:190
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.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.
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:357
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:588
KEYED_EQUIVALENT ** MakeSortedKeyGroups(long *keyGroups, long keyType, void *data, long points)
Create sorted key groups from data.
long FindMatchingKeyGroup(KEYED_EQUIVALENT **keyGroup, long keyGroups, long keyType, void *searchKeyData, long reuse)
Find a matching key group for a search key.